众所周知,密码手需要考虑的东西很多,但逆向手只要学会一把梭就完事了
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
|
#include <stdio.h> #include "AES.h"
int main() {
const uint8_t key[16] = "ABCDEFGHIJKLMNOP"; const uint8_t pt[] = "ABCDEFGHIJKLMNOP"; 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; }
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
|