白盒AES的初探

两只羊 Lv2

众所周知,密码手需要考虑的东西很多,但逆向手只要学会一把梭就完事了

main函数,首先进行一次标准的加密,然后进行16次的故障注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//
// Created by Liming Shao on 2018/4/24.
//

#include <stdio.h>
#include "AES.h"

int main() {

// case 1
const uint8_t key[16] = "ABCDEFGHIJKLMNOP";
const uint8_t pt[] = "ABCDEFGHIJKLMNOP";
//{0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34};
uint8_t ct[48] = { 0 };
uint8_t plain[16] = { 0 };

aesEncrypt(key, 16, pt, ct, 16, 0);
for (int i = 0; i < 16; i++)
{
printf("%02X", ct[i]);
}
printf("\n");

printf("start dfa \n");
for (int k = 0; k < 16; k++) {
aesEncrypt(key, 16, pt, ct, 16, 1);
for (int i = 0; i < 16; i++)
{
printf("%02X", ct[i]);
}
printf("\n");
}

return 0;
}

在aesEncrypt中,故障注入点在第9轮,替换state[round_count_1 * 4 + round_count_2]的字节

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
int round_count_1 = 0, round_count_2 = 0;
int aesEncrypt(const uint8_t* key, uint32_t keyLen, const uint8_t* pt, uint8_t* ct, uint32_t len, int isDFA) {

AesKey aesKey;
uint8_t* pos = ct;
const uint32_t* rk = aesKey.eK;
uint8_t out[BLOCKSIZE] = { 0 };
uint8_t actualKey[16] = { 0 };
uint8_t state[4][4] = { 0 };




if (NULL == key || NULL == pt || NULL == ct) {
printf("param err.\n");
return -1;
}

if (keyLen > 16) {
printf("keyLen must be 16.\n");
return -1;
}

if (len % BLOCKSIZE) {
printf("inLen is invalid.\n");
return -1;
}

memcpy(actualKey, key, keyLen);
keyExpansion(actualKey, 16, &aesKey);

for (int i = 0; i < len; i += BLOCKSIZE) {

loadStateArray(state, pt);
addRoundKey(state, rk);

for (int j = 1; j < 10; ++j) {
rk += 4;
subBytes(state);
shiftRows(state);

if (isDFA == 1) {
if (j == 9) {
if (round_count_2 == 4) {
round_count_1++;
round_count_2 = 0;
}

//printf("%d %d \n", round_count_1, round_count_2);
state[round_count_1][round_count_2] = 0x88;
round_count_2++;
}
}



mixColumns(state);
addRoundKey(state, rk);
}

subBytes(state);
shiftRows(state);
addRoundKey(state, rk + 4);

storeStateArray(state, pos);

pos += BLOCKSIZE;
pt += BLOCKSIZE;
rk = aesKey.eK;
}
return 0;
}

将正确的加密与故障输出用phoenixAES计算Last round key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import phoenixAES
with open('tracefile', 'wb') as t:
t.write("""
630D7913B3C526A1D46420231FFFB5D1
F40D7913B3C526DCD464DE231FB9B5D1
6328791332C526A1D46420C51FFFE3D1
630D7313B3F326A1156420231FFFB579
630D7962B3C5C6A1D4EE2023D1FFB5D1
160D7913B3C526C8D46405231F64B5D1
633C7913C8C526A1D46420221FFF2FD1
630D5613B3EE26A1096420231FFFB5EB
630D797EB3C51CA1D4022023A7FFB5D1
820D7913B3C5263CD46432231F87B5D1
63D3791309C526A1D464205B1FFFBBD1
630DBE13B35D26A1EA6420231FFFB5B3
630D79CFB3C5E0A1D43920237FFFB5D1
3E0D7913B3C5262FD464BF231F1DB5D1
630279131EC526A1D464207D1FFF9AD1
630D9E13B34E26A1616420231FFFB54A
630D7996B3C50CA1D44F2023BCFFB5D1
""".encode('utf8'))

phoenixAES.crack_file('tracefile',[],True,False,3)

得到

1
2
3
4
Round key bytes recovered:
882E11DBBF6B9708BB3E3DDA9DE9B7EF
Last round key #N found:
882E11DBBF6B9708BB3E3DDA9DE9B7EF

最后aes_keyschedule.exe得出正确的key

1
2
3
4
5
6
7
8
9
10
11
12
D:\Cyber Swat\Reverse\脚本\AES\whitebox>aes_keyschedule.exe 882E11DBBF6B9708BB3E3DDA9DE9B7EF 10
K00: 4142434445464748494A4B4C4D4E4F50
K01: 6FC610A72A8057EF63CA1CA32E8453F3
K02: 322B1D9618AB4A797B6156DA55E50529
K03: EF40B86AF7EBF2138C8AA4C9D96FA1E0
K04: 4F72595FB899AB4C34130F85ED7CAE65
K05: 4F96140AF70FBF46C31CB0C32E601EA6
K06: BFE4303B48EB8F7D8BF73FBEA5972118
K07: 77199D3D3FF21240B4052DFE11920CE6
K08: B8E713BF871501FF33102C01228220E7
K09: B050872C374586D30455AAD226D78A35
K10: 882E11DBBF6B9708BB3E3DDA9DE9B7EF
  • 标题: 白盒AES的初探
  • 作者: 两只羊
  • 创建于 : 2025-05-18 13:09:41
  • 更新于 : 2025-05-21 20:58:28
  • 链接: https://twogoat.github.io/2025/05/18/白盒AES的初探/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
目录
白盒AES的初探