Skip to content

Commit d3272aa

Browse files
committed
aes
1 parent 4742258 commit d3272aa

File tree

15 files changed

+344
-1
lines changed

15 files changed

+344
-1
lines changed

Android/A06/README.md

Lines changed: 343 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,343 @@
1+
#### so 实现AES算法:
2+
3+
```
4+
一个AES算法我们要关注哪些内容?
5+
是AES-128 还是 AES-192 还是 AES-256
6+
明文是什么
7+
密钥是什么
8+
什么模式 ECB还是CBC还是其他
9+
如果是非ECB模式,那么IV是什么
10+
明文填充模式呢,是PCKS#7吗?
11+
```
12+
13+
1. 调用open_ssl封装的EVP。传入结构体,百度搜索,查看参数信息。
14+
15+
![1](./pic/1.png)
16+
17+
2. 直接使用底层的代码,通过hook各个函数,得到信息。
18+
19+
![2](./pic/2.png)
20+
21+
#### 简介
22+
23+
```
24+
AES 高级加密标准
25+
Rijndael 分组加密荣耀
26+
27+
工作模式:ECB、CBC、CFB、OFB
28+
KEY:密钥
29+
IV: 初始化链接变量, 十六个字节长度
30+
PADDING:填充
31+
32+
明文:
33+
DES:分组长度64比特,明文会被切成64比特做运算,16个16进制数、8个字节
34+
hex:0123456789abcdef 1111111111111111 2222222222222222 3333333333333333
35+
明文会被切成4块,64比特为1块
36+
37+
AES:分组长度128比特,32个16进制数、16个字节
38+
hex:0123456789abcdef 1111111111111111 22222222222222223333333333333333
39+
明文会被切成2块,128比特为1块
40+
41+
DES中明文都是比特流,最小单位是比特
42+
AES中基于字节的,最小单位是字节
43+
44+
密钥:
45+
AES密钥 密钥长度分三种
46+
- 128比特长,16个字节 ----10轮运算
47+
- 192比特长,24个字节 ----12轮运算
48+
- 256比特长,32个字节 ----14轮运算
49+
不管是aes-128/192/256比特 aes分组大小以及密文输出大小都是不变的。
50+
假如密钥是255比特长依然会出结果?
51+
比如:1111111(比特)?不可能是3.5字节,他会在最后一个补个0变成: 11 11 11 01
52+
比如:111111111111111111111111111111111111111111111111111111111111111(252bit),少了4bit 半个字节
53+
等于:1111111111111111111111111111111111111111111111111111111111111101
54+
55+
特征:
56+
AES 不管输入的是什么,小于16个16进制数,输出都是32个16进制数。
57+
当明文恰好是一个分组长度,结果变成了两个分组大小。可能就是aes。
58+
```
59+
60+
#### AES算法原理
61+
62+
```
63+
- 密钥的编排
64+
- 明文的运算
65+
66+
一切基于字节做操作。
67+
68+
举例:
69+
明文:0123456789 to hexdump 30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66(16个字节)
70+
aes把明文放在一个4*4的矩阵当中,表中每个元素是一个字节大小
71+
30 34 38 63
72+
31 35 39 64
73+
32 36 61 65
74+
33 37 62 66
75+
密钥也同明文如此。表中每个元素都是一个字节大小
76+
```
77+
78+
1. ##### 明文加密流程
79+
80+
```
81+
AES-128 ----10轮运算
82+
83+
首先是一个初始变换 --addRoundKey
84+
- 明文 xor 密钥k (这个key就是我们输入的种子密钥)
85+
然后是9轮相同的运算
86+
- S盒替换 subBytes
87+
- 循环左移 shiftRows
88+
- 列混淆 mixcolumn
89+
- state xor 密钥 (密钥编排得到的子密钥,不是我们输入的密钥, k1-k9)addRoudKey
90+
末运算(第10轮)
91+
- S盒替换
92+
- 循环左移
93+
- state xor 密钥 (密钥编排得到的子密钥,不是我们输入的密钥, k10)addRoudKey
94+
```
95+
96+
**1.1 subBytes**
97+
98+
大小: 16 * 16 = 256
99+
100+
![3](./pic/3.png)
101+
102+
```
103+
行和列生成规则:
104+
从0开始数
105+
30 就代表第3行第0个 -> 04
106+
34 就代表第3行第4个 -> 18
107+
```
108+
109+
ida如何找s盒?
110+
ida view-> open subviews-> segments data数据断以及rodata只读数据断。
111+
112+
![4](./pic/4.png)
113+
114+
ida中找到s盒,选中0x63右键点击`Byte 0x63`,就识别成了byte数组了,选中右键,点击array,设置size:256。
115+
116+
![5](./pic/5.png)
117+
118+
![6](./pic/6.png)
119+
120+
通过对AES算法原理了解,学会通过查找`S盒`,来确定SO中是否有AES算法。
121+
122+
**1.2 循环左移**
123+
124+
```
125+
最小单位字节
126+
127+
举例:
128+
d4 e0 b8 1e
129+
27 bf b4 41
130+
11 98 5d 52
131+
ae f1 e5 30
132+
133+
把上面的循环左移一字节:
134+
d4 e0 b8 1e 第一行左移0个字节
135+
bf b4 41 27 第二行左移一个字节
136+
5d 52 11 98 第三行左移两个字节
137+
30 ae f1 e5 第四行左移三个字节
138+
```
139+
140+
ida中循环左移的特征:
141+
142+
实现方式1:
143+
144+
![7](./pic/7.png)
145+
146+
上图中:
147+
148+
v155[13] = v155[1] 就是1去13
149+
150+
v155[9] = v155[13] 就是13去9
151+
152+
然后就是 9去5、5去1、10去2、2去10
153+
154+
```
155+
如果明文用a表示的话,可以得到以下结论:
156+
a0 a4 a8 a12
157+
a1 a5 a9 a13
158+
a2 a6 a10 a14
159+
a3 a7 a11 a15
160+
循环左移后:
161+
a0 a3 a7 a11
162+
a5 a9 a13 a1
163+
a10 a14 a2 a6
164+
a15 a3 a7 a11
165+
166+
左移后 a1的位置就是原来的a13,a13的位置就是原来的a9
167+
```
168+
169+
实现方式2:
170+
171+
![8](./pic/8.png)
172+
173+
```
174+
5去1、9去5
175+
```
176+
177+
实现方式3:
178+
179+
![13](./pic/13.png)
180+
181+
ida中应用,识别出so中循环左移步骤的代码,然后以此为基点,把上面下面全部打通,可以被当作锚点
182+
183+
```c++
184+
sub_81A0的函数引用
185+
186+
int sub_7F8C()
187+
{
188+
int v0; // r0
189+
unsigned __int8 i; // [sp+7h] [bp-9h]
190+
191+
sub_80A0(0);
192+
for ( i = 1; (signed int)i <= 9; ++i )
193+
{
194+
sub_8120(); // 循环左移上一步就是S盒替换
195+
v0 = sub_81A0(); // 循环左移
196+
sub_8220(v0); // 循环左移下一步就是列混淆
197+
sub_80A0(i);
198+
}
199+
sub_8120();
200+
sub_81A0();
201+
return sub_80A0(10);
202+
}
203+
```
204+
205+
**1.3 列混淆 **
206+
207+
ida中特征:
208+
209+
会有两个数很关键:0x1B、0x80 这两个数很关键、很明显特征
210+
211+
```c++
212+
int __fastcall sub_8380(unsigned __int8 a1)
213+
{
214+
return (unsigned __int8)(0x1B * (a1 >> 7) ^ 2 * a1);
215+
}
216+
```
217+
218+
尤其与这个0x1B做异或 ^
219+
220+
![9](./pic/9.png)
221+
222+
**1.4 通过上述知识做还原**
223+
224+
![10](./pic/10.png)
225+
226+
初始化的addRoundKey,明文 xor 密钥k (这个key就是我们输入的种子密钥)。
227+
228+
2. ##### 密钥的编排(aes-128)
229+
230+
```
231+
假设我们的密钥为:
232+
d42711aee0bf98f1b8b45de51e415230
233+
234+
d4 e0 b8 1e
235+
27 bf b4 41
236+
11 98 5d 52
237+
ae f1 e5 30
238+
239+
w0 w1 w2 w3 w4 w5 w6 .....w43
240+
241+
242+
为什么到w43?
243+
因为是aes-128, 所以每一轮密钥是16个字节,4个w是一轮的密钥。
244+
245+
初始化的addRoundKey用到的key:
246+
key0 = w0w1w2w3 = d42711aee0... 我们的种子密钥,用来做初始变换。根据我们传入的种子密钥获得10个新的密钥, hook初始变化 addroundKey的异或后面的key,就是我们输入的种子key。
247+
248+
9轮运算用到的key分别是:
249+
k1:w4w5w6w7
250+
k2:w8w9w10w11
251+
......
252+
k9:w36w37w38w39
253+
254+
最后一轮:
255+
k10: w40w41w42w43
256+
257+
密钥编排:
258+
就是根据我们w0-w3传入的密钥,通过密钥编排,生成w4-w43,也叫密钥扩展算法
259+
密钥扩展:w0-w43,44个w,或者44 *4 = 176个字节
260+
261+
文章:
262+
https://blog.csdn.net/qq_28205153/article/details/55798628
263+
```
264+
265+
**2.1 w4-w17的生成**
266+
267+
```
268+
w4 = T(w3) ^ w0 每当Windex index为4的倍数时都需要wi-1走一遍T函数
269+
w5、w6、w7时 w5 = w4 ^ w1, wi = wi-1 ^ wi-4(如果i不是4的倍数)
270+
271+
T函数步骤:
272+
1. 循环左移1位
273+
2. S表替换
274+
3. rcon表异或
275+
276+
假如:
277+
w4的计算:
278+
w0 = 2b7e1516,w3 = 0x09cf4f3c,T(w3) = sbox(shiftrow(w3)) ^ rcon[i]
279+
循环左移1位 -> cf4f3c09
280+
S表替换 -> 8a84eb01
281+
rcon表异或 -> 8b84eb01(rcon表固定的,rcon表=01000000、02000000)
282+
最后 w4 = 8b84eb01 ^ w0 = a0fafe17
283+
w5的计算:
284+
w5 = w4 ^ w1 = a0fafe17 ^ w1
285+
```
286+
287+
![11](./pic/11.png)\
288+
289+
ida中特征:
290+
291+
> w43也是密钥扩展的特征,比如 <=43
292+
> <<31 分单双数
293+
> <<30 看是否为4的倍数
294+
295+
#### 拓展
296+
297+
```
298+
哈希算法:签名校验
299+
对称加密:DES、AES, 主要应用于对明文的处理
300+
非对称加密:RSA, 主要功能:提供AES/DES 密钥
301+
302+
非对称加密算法:RSA、ECC
303+
特点:安全性好、
304+
缺点:运算复杂慢、性能不好
305+
306+
RSA + AES:混合加密
307+
308+
findcrypt 可以找到特征
309+
310+
逆S盒:https://bbs.pediy.com/thread-266410.htm
311+
S盒 用来加密
312+
00 0x90
313+
逆S盒 用来解密
314+
第9行 第0列 为 00
315+
new_contrary_sbox = [0]*256
316+
317+
for i in range(256):
318+
line = (new_s_box[i]&0xf0)>>4
319+
rol = new_s_box[i]&0xf
320+
new_contrary_sbox[(line*16)+rol] = i
321+
322+
print (new_contrary_sbox)
323+
```
324+
325+
```
326+
输入:pcks#7 000102030405060708090a0b0c0d0e0f
327+
输出:a07999f0e2bfbe16f99593e984a449b7 377222e061a924c591cd9c27ea163ed4
328+
329+
aes一个分组会填充10101010101010101010101010101010
330+
输出:377222e061a924c591cd9c27ea163ed4 377222e061a924c591cd9c27ea163ed4
331+
332+
验证:
333+
hex
334+
01 15个0f的字节
335+
01 02 14个0e
336+
13 个 d
337+
12 个 c
338+
11 个 b
339+
10个a
340+
341+
101010
342+
```
343+

Android/A06/pic/1.png

201 KB
Loading

Android/A06/pic/10.png

166 KB
Loading

Android/A06/pic/11.png

167 KB
Loading

Android/A06/pic/12.png

69.8 KB
Loading

Android/A06/pic/13.png

94.9 KB
Loading

Android/A06/pic/2.png

122 KB
Loading

Android/A06/pic/3.png

274 KB
Loading

Android/A06/pic/4.png

133 KB
Loading

Android/A06/pic/5.png

354 KB
Loading

0 commit comments

Comments
 (0)