0%

强网拟态

强网拟态

re

本次出了三道逆向题,是有史以来最多的一次,两个题都是第7个做出来的。

comeongo

go语言逆向,main_main里两个地方,主要加密再greetingscheck()

1
2
3
v19 = fmt_Scan(v6, v12, v16);
v21 = main_Greetingscheck(v7, v13, v17, v19);
fmt_Printf(v8, v14, v18, v20, v21);
1
2
3
4
5
6
7
8
v8 = main_check1();
v10 = v6;
if ( v6 )
{
main_check2(v8);
v10 = v7;
}
return v10 != 0;

两个check函数,前16字节都是在check1

check1很好过,是一个base58

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
void __golang main_runtime_Encoding()
{
__int64 v0; // rax
__int64 v1; // r14
__int128 v2; // xmm15
__int64 v3; // rbx
__int64 v4; // rax
__int64 v5; // rcx
__int64 v6; // rax
__int64 v7; // rax
__int64 v8; // rax
__int64 v9; // rax
__int64 v10; // rax
__int64 v11; // rax
unsigned __int64 v12; // rax
__int64 v13; // rcx
__int64 v14; // rdi
__int64 v15; // rbx
__int64 v16; // rsi
__int64 v17; // rax
__int64 v18; // rcx
__int64 v19; // rcx
__int64 v20; // rsi
__int64 v21; // rdi
__int64 v22; // rbx
__int64 v23; // rax
__int64 v24; // rcx
__int64 v25; // rbx
__int64 v26; // rax
__int64 v27; // rcx
__int64 v28; // rbx
__int64 v29; // rax
__int64 v30; // [rsp-46h] [rbp-128h]
__int64 v31; // [rsp-46h] [rbp-128h]
__int64 v32; // [rsp-46h] [rbp-128h]
__int64 v33; // [rsp-46h] [rbp-128h]
__int64 v34; // [rsp-46h] [rbp-128h]
__int64 v35; // [rsp-46h] [rbp-128h]
__int64 v36; // [rsp-46h] [rbp-128h]
__int64 v37; // [rsp-46h] [rbp-128h]
__int64 v38; // [rsp-3Eh] [rbp-120h]
__int64 v39; // [rsp-3Eh] [rbp-120h]
__int64 v40; // [rsp-3Eh] [rbp-120h]
__int64 v41; // [rsp-3Eh] [rbp-120h]
__int64 v42; // [rsp-3Eh] [rbp-120h]
__int64 v43; // [rsp-3Eh] [rbp-120h]
__int64 v44; // [rsp-36h] [rbp-118h]
__int64 v45; // [rsp-36h] [rbp-118h]
__int64 v46; // [rsp-2Eh] [rbp-110h]
char v47; // [rsp+1h] [rbp-E1h]
__int64 v48; // [rsp+2h] [rbp-E0h]
__int64 v49; // [rsp+2h] [rbp-E0h]
__int64 v50; // [rsp+Ah] [rbp-D8h]
__int64 v51; // [rsp+12h] [rbp-D0h]
char v52; // [rsp+3Ah] [rbp-A8h] BYREF
__int64 v53; // [rsp+4Ah] [rbp-98h]
__int64 v54; // [rsp+52h] [rbp-90h]
__int64 v55; // [rsp+5Ah] [rbp-88h]
__int64 v56; // [rsp+62h] [rbp-80h]
__int128 v57; // [rsp+6Ah] [rbp-78h]
__int64 v58; // [rsp+7Ah] [rbp-68h]
__int64 v59; // [rsp+82h] [rbp-60h]
__int64 v60; // [rsp+8Ah] [rbp-58h]
__int64 v61; // [rsp+92h] [rbp-50h]
__int64 v62; // [rsp+9Ah] [rbp-48h]
__int64 v63; // [rsp+A2h] [rbp-40h]
__int64 v64; // [rsp+AAh] [rbp-38h]
__int128 i; // [rsp+B2h] [rbp-30h]
__int64 v66; // [rsp+C2h] [rbp-20h]
__int64 v67; // [rsp+CAh] [rbp-18h]
__int64 v68; // [rsp+D2h] [rbp-10h]
__int64 v70; // [rsp+EAh] [rbp+8h]

while ( (unsigned __int64)&v52 <= *(_QWORD *)(v1 + 16) )
{
v70 = v0;
runtime_morestack_noctxt();
v0 = v70;
}
v57 = v2;
v3 = v0;
v30 = runtime_stringtoslicebyte();
v58 = v4;
v59 = v3;
v60 = v5;
v38 = math_big_NewInt(v30);
v56 = v6;
math_big___ptr_Int__SetBytes(v31, v38);
v55 = v7;
v64 = 0LL;
for ( i = v2; ; *((_QWORD *)&i + 1) = v14 )
{
v39 = math_big_NewInt(v32);
v56 = v8;
v44 = math_big___ptr_Int__Cmp(v33, v39);
if ( v9 <= 0 )
break;
math_big_NewInt(v34);
v53 = v10;
v41 = math_big_NewInt(v35);
v54 = v11;
math_big___ptr_Int__DivMod(v36, v41, v44, v46);
v12 = math_big___ptr_Int__Int64();
if ( v12 >= qword_54A6B8 )
runtime_panicIndex();
v47 = off_54A6B0[v12];
v14 = *((_QWORD *)&i + 1);
v13 = i;
v15 = v64;
v16 = i + 1;
if ( *((_QWORD *)&i + 1) < (unsigned __int64)(i + 1) )
{
v48 = i;
runtime_growslice(v32, v42);
v16 = v15 + 1;
v15 = v17;
v14 = v18;
v13 = v48;
}
*(_BYTE *)(v15 + v13) = v47;
v64 = v15;
*(_QWORD *)&i = v16;
}
v66 = v58;
v67 = v59;
v68 = v60;
v51 = 0LL;
v50 = v59;
while ( v50 > v51 && !*(_BYTE *)(v51 + v66) )
{
v19 = i;
v20 = i + 1;
v21 = *((_QWORD *)&i + 1);
v22 = v64;
if ( *((_QWORD *)&i + 1) < (unsigned __int64)(i + 1) )
{
v49 = i;
v44 = runtime_growslice(v34, v40);
v20 = v22 + 1;
v22 = v23;
v21 = v24;
v19 = v49;
}
*(_BYTE *)(v22 + v19) = 49;
v64 = v22;
*(_QWORD *)&i = v20;
*((_QWORD *)&i + 1) = v21;
++v51;
}
v25 = i;
main_ReverseByteArr(v34, v40, v44);
v61 = v26;
v62 = v25;
v63 = v27;
v28 = v26;
runtime_slicebytetostring(v37, v43, v45);
*(_QWORD *)&v57 = v29;
*((_QWORD *)&v57 + 1) = v28;
}

base58解密出来的就是账号和密码前8位,然后看check2,里面首先是对账号的密码的4位进行了字母表12的位移,然后进行base64加密,所以到目前为止已经推出了

1
2
3
账号:GoM0bi13_Bin4567

密码:G3tItEzForReEFGH

现在只剩账号和密码的后四位,而且经过动调发现真正的算法是在main_runtime_other函数中

1
2
3
4
5
if ( v54 )
{
main_runtime_other(v36, v41, v46, v50, v52, v53);
return v28;
}

可以采用爆破求解,因为该处是通过密码来爆破账号的,且密码已经给出两位,所以只用爆破最后两位

1
2
3
4
5
6
7
8
9
10
11
12
13
zhanghaohousiwei = [0xDD, 0x8F, 0xA1, 0x64]
flag = ''
code = 'vGGH'
for i in range(4):
flag+=chr(zhanghaohousiwei[i] - ord(code[i]) - i)
print(flag)
#账号:GoM0bi13_BingGo@
#密码:G3tItEzForRevG0!
for i in range(27,127):
for j in range(27,127):
if i + j + 3 == 0x64 and i-j == 0x1f://还有一个是64
print(i)
print(j)

得到flag:flag{GoM0bi13_BingGo@G3tItEzForRevG0!}

mcmc

这个题纯纯的做了10个小时

用d810搞一下看的会比较清楚

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
__int64 __fastcall main(int a1, char **a2, char **a3)
{
int v4; // [rsp+1Ch] [rbp-104h]
char s[4]; // [rsp+20h] [rbp-100h] BYREF
_BYTE v6[3]; // [rsp+24h] [rbp-FCh] BYREF
char v7; // [rsp+27h] [rbp-F9h]
_BYTE v8[4]; // [rsp+28h] [rbp-F8h] BYREF
_BYTE v9[3]; // [rsp+2Ch] [rbp-F4h] BYREF
char v10; // [rsp+2Fh] [rbp-F1h]
_BYTE v11[4]; // [rsp+30h] [rbp-F0h] BYREF
_BYTE v12[3]; // [rsp+34h] [rbp-ECh] BYREF
char v13; // [rsp+37h] [rbp-E9h]
_BYTE v14[4]; // [rsp+38h] [rbp-E8h] BYREF
_BYTE v15[3]; // [rsp+3Ch] [rbp-E4h] BYREF
char v16; // [rsp+3Fh] [rbp-E1h]
char v17[192]; // [rsp+50h] [rbp-D0h] BYREF
unsigned int v18; // [rsp+110h] [rbp-10h]
int v19; // [rsp+114h] [rbp-Ch]
char v20; // [rsp+11Bh] [rbp-5h]
int i; // [rsp+11Ch] [rbp-4h]

v18 = 0;
memset(s, 0, 0x21uLL);
memset(s, 0, 0x21uLL);
__isoc99_scanf(&unk_408004, s);
v4 = strlen(s);
v19 = v4;
i = -1341394107;
if ( v19 != 32 )
{
for ( i = -1901734900; ; i = -1901734900 )
;
}
i = 944589829;
if ( unk_40A0F8 >= 10 || unk_40A0F8 < 10 )
{
i = -2083856703;
goto LABEL_8;
}
for ( i = -984240755; ; i = -984240755 )
{
v7 ^= 0x44u;
v10 ^= 0x23u;
v13 ^= 0x5Bu;
v16 ^= 0x5Au;
sub_405480(s, v6, v8, v9);
sub_405480(v11, v12, v14, v15);
sub_4011A0(v17, &byte_40A0A0, &byte_40A0C0, 1LL);
sub_401820((__int64)v17, (__int64)s, v4);
i = -2083856703;
LABEL_8:
v7 ^= 0x44u;
v10 ^= 0x23u;
v13 ^= 0x5Bu;
v16 ^= 0x5Au;
sub_405480(s, v6, v8, v9);
sub_405480(v11, v12, v14, v15);
sub_4011A0(v17, &byte_40A0A0, &byte_40A0C0, 1LL);
sub_401820((__int64)v17, (__int64)s, v4);
if ( unk_40A0F8 < 10 || unk_40A0F8 >= 10 )
break;
}
for ( i = 269145055; ; i = 215820177 )
{
while ( i >= 269145055 )
{
i = 1215238956;
if ( v4 > 0 )
{
i = 1341239842;
goto LABEL_15;
}
i = -504198;
if ( unk_40A0F8 < 10 && unk_40A0F8 >= 10 )
{
i = 1576878451;
goto LABEL_17;
}
i = 215820177;
}
v20 = 0;
if ( unk_40A0F8 >= 10 || unk_40A0F8 < 10 )
break;
i = 1576878451;
LABEL_17:
;
}
i = 1408947266;
LABEL_15:
printf("Nice! flag:flag{(your input)}\n");
i = -198005779;
return v18;
}

好看多了,但是编译的不是很准确,可以看到最开始先对输入进行每8个字节异或,然后异或后的值传到sub_405480函数进行抽象的处理,接下来的函数就比较逆天了

1
2
3
sub_405480(v11, v12, v14, v15);
sub_4011A0(v17, &byte_40A0A0, &byte_40A0C0, 1LL);
sub_401820((__int64)v17, (__int64)s, v4);

本来以为是chacha20加密,但是发现不对,怎么解都不对,由于chacha是对称加密,所以进行了验证发现并不是对称的。最后还是超人发现真正的加密是在sub_401820,直接看汇编,如下图:

image-20221108152758147

进行正向算法的一个逆,然后缩减了一下算法:

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
#include <iostream>
using namespace std;

int main(int argc, char** argv) {
uint32_t en_data[] = {0x93, 0x93, 0x93, 0xB8, 0x62, 0x62, 0x62, 0xC5, 0x00, 0x00, 0x00, 0xDB, 0xC4, 0xC4, 0xC4, 0x0E, 0x93, 0x93, 0x93, 0x06, 0x62, 0x62, 0x62, 0x61, 0x00, 0x00, 0x00, 0x8D, 0xC4, 0xC4, 0xC4, 0xAA};
uint32_t en[] = { 0x17, 0x40, 0x2B, 0xDD, 0x11, 0xC8, 0xBD, 0xA7, 0x1B, 0x05, 0xF9, 0x58, 0x60, 0x6C, 0x64, 0xB7, 0x17, 0x40, 0x2B, 0x37, 0x11, 0xC8, 0xBD, 0x6F, 0x1B, 0x05, 0xF9, 0xFE, 0x60, 0x6C, 0x64, 0x6B };
uint32_t table[] = { 0xD3, 0x1B, 0xCC, 0x7D, 0xEF, 0xB9, 0x0D, 0xC6, 0xA0, 0xDB, 0xE2, 0x07, 0xFB, 0x0F, 0xB7, 0x0E, 0xCB, 0x73, 0x3A, 0x8A, 0xC5, 0x4E, 0x3E, 0xEC, 0x0C, 0xF0, 0xA2, 0x48, 0x94, 0x70, 0x27, 0x1B, 0xA4, 0x1C, 0x17, 0x1C, 0x0D, 0x71, 0xC8, 0xF2, 0x28, 0x2B, 0x9A, 0xA7, 0x3A, 0x5F, 0xB8, 0x6E, 0x81, 0x80, 0x54, 0x3B, 0x9D, 0x51, 0x0E, 0xC6, 0x21, 0x03, 0x49, 0xD4, 0xB6, 0x36, 0x31, 0x7B };
uint32_t k1 = 0;
uint32_t k2 = 0;
uint32_t k3 = 0;
uint32_t k4 = 0;
uint32_t k6 = 0;
uint32_t k7 = 0;
int i, k;
for (int i = 0; i < 32; i++) {
uint64_t temp= 0xfffffffffffffffe;
temp ^= i;
temp &= i;
if (temp) {
k2 = en[i - 1];
if (k2 > 0xff)
k2 = en[i];
}
else
k2 = en[i + 1];
//k2 = en[(i)%32];
// en_data[i] = k4;
en[i] = (en[i] ^ 0x7deeb3f5 | en[i] ^ 0x7deeb3f5) ^ (table[i] + k2) & 0xff ^ 0x7deeb3f5;
// k2 = k4;
//k2 = en[(i + 1) % 32];
cout << hex << en[i] << endl;
}
}

/*
[0x93, 0x62, 0xB8, 0x19, 0x45, 0x20, 0x25, 0x25, 0x22, 0xFE, 0x7F, 0x00, 0x00, 0x16, 0x6D, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

*/

发现真正加密其实也就一个,但是不太好爆,考虑采用z3,又发现前面的判断条件其实有些抽象,直接舍去就好

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from z3 import*
s=Solver()
flag = [BitVec("flag%d" % i,8) for i in range(32)]
cmp = [0x06, 0x08, 0x65, 0x04, 0x60, 0x03, 0x08, 0x01, 0x4A, 0x10, 0x32, 0x58, 0xEE, 0x97, 0x65, 0x84, 0x44, 0xF2, 0x10, 0x6B, 0xE8, 0x50, 0x24, 0x99, 0xF6, 0xE3, 0x21, 0x51, 0xC2, 0x5D, 0xBF, 0x32]
table = [0xD3, 0x1B, 0xCC, 0x7D, 0xEF, 0xB9, 0x0D, 0xC6, 0xA0, 0xDB, 0xE2, 0x07, 0xFB, 0x0F, 0xB7, 0x0E, 0xCB, 0x73, 0x3A, 0x8A, 0xC5, 0x4E, 0x3E, 0xEC, 0x0C, 0xF0, 0xA2, 0x48, 0x94, 0x70, 0x27, 0x1B, 0xA4, 0x1C, 0x17, 0x1C, 0x0D, 0x71, 0xC8, 0xF2, 0x28, 0x2B, 0x9A, 0xA7, 0x3A, 0x5F, 0xB8, 0x6E, 0x81, 0x80, 0x54, 0x3B, 0x9D, 0x51, 0x0E, 0xC6, 0x21, 0x03, 0x49, 0xD4, 0xB6, 0x36, 0x31, 0x7B]
for i in range(32):
tmp = 0xfffffffffffffffe
tmp = tmp^i
tmp = tmp&i
if(tmp):
k2 = flag[i-1]
else:
k2 = flag[i+1]
flag[i] = (flag[i] ^ 0x7deeb3f5 | flag[i] ^ 0x7deeb3f5) ^ (table[i] + k2) & 0xff ^ 0x7deeb3f5
for i in range(32):
s.add(flag[i] == cmp[i])
if s.check() == sat:
model = s.model()
print(model)
else:
print("unsat")
#[250,41,215,230,105,26,212,207,159,53,113,97,139,106,203,247,84,69,59,241,195,102,227,137,231,5,251,56,193,111,176,232]

#0xe6d729fa, 0xcfd41a69, 0x6171359f, 0xf7cb6a8b, 0xf13b4554, 0x89e366c3, 0x38fb05e7, 0xe8b06fc1

得到的flag,每4个字节组合,并逆序

最抽象的是sub_405480函数

image-20221108160739412

我们的flag还要经过这个地方进行加密才能到达下一步,所以还要逆这个地方的汇编,明显是每4个字符进行加密,撸汇编然后z3解就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from z3 import*
s=Solver()
flag = [BitVec("flag%d" % i,32) for i in range(4)]
cmp = [0xe6d729fa, 0xcfd41a69, 0x6171359f, 0xf7cb6a8b, 0xf13b4554, 0x89e366c3, 0x38fb05e7, 0xe8b06fc1]
s.add(((flag[0] << 1) - ((0 - flag[1]) & 0xffffffff) - flag[2] + flag[3]) & 0xffffffff == cmp[0])
s.add(((flag[0] - flag[1] + flag[2]) + (0 - flag[3]) & 0xffffffff) & 0xffffffff == cmp[2])
s.add((flag[0] + flag[1] + flag[2] -flag[3])&0xffffffff == cmp[1])
s.add((flag[3] * 2 + flag[0] + flag[1] * 2 - flag[2])&0xffffffff == cmp[3])

if s.check() == sat:
model = s.model()
print(model)
else:
print("unsat")
flag3 = 1194345311,
flag0 = 1835889971,
flag2 = 1919252016,
flag1 = 925987429
flag4 = 0x63676e69
flag5 = 0x2874306e
flag6 = 0x30703054
flag7 = 0x32686868

那四个字节也需要异或回去,得到flag

3ummer1s0ver_C0dingcn0tsT0p0hhhh

windows_call

这个题是aes题,看起来是个混淆,但混的不多

1
sub_402613(v26, 1, 16, v38, v0 + 1028, v42);

这个函数是aes函数,经过动态调试发现key和iv做运算

1
2
3
4
5
6
7
 do
{
v29 = v38[v27] ^ (v27 - 64);
v37[v27] = v29;
v28 += v29;
++v27;
}

用z3找出前几个字节然后解aes就行

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
from z3 import *
s = Solver()
flag = [BitVec("flag%d" % i,16) for i in range(2)]
s.add((flag[0]+0x3800-0x10000)<=0x800)
s.add((flag[0]+0x3800)>0x10000)
s.add((flag[1]+0x3500-0x10000)<=0x500)
s.add((flag[1]+0x3500)>0x10000)
s.add(flag[0]&0xff00<0xca00)
s.add(flag[1]&0xff==0xa0)
s.add(flag[1]-flag[0]==0x2B8)
v25=(flag[0]^flag[1])&0xff
v55=(flag[0]^flag[1])>>8
iv=[]
for v23 in range(16):
iv.append((v55+v23)^(v25+v23))
v57=0
v37=[]
v28=0
for v27 in range(16):
v29=iv[v27]^(v27-64+0x100)
v37.append(v29)
v28+=v29
s.add(v28==0x8a8)
if s.check() == sat:
model = s.model()
print(model)
else:
print("unsat")
#[flag0 = 51688, flag1 = 52384]

然后求出key和iv

1
2
3
4
5
6
7
8
9
10
11
12
13
14
flag=[51688,52384]
v25=(flag[0]^flag[1])&0xff
v55=(flag[0]^flag[1])>>8
iv=[]
for v23 in range(16):
iv.append((v55+v23)^(v25+v23))
v57=0
key=[]
v28=0
for v27 in range(16):
v29=iv[v27]^(v27-64+0x100)
key.append(v29)
v28+=v29

最后解aes就行了

babyre

动调发现过不去,猜测tls里有反调试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int __stdcall TlsCallback_0_0(int a1, int a2, int a3)
{
int result; // eax
HANDLE CurrentProcess; // eax
int ProcessInformation; // [esp+E8h] [ebp-Ch] BYREF

__CheckForDebuggerJustMyCode(byte_2470F4);
ProcessInformation = 0;
AddVectoredExceptionHandler(0, Handler);//sbox加密
AddVectoredContinueHandler(0, sub_231041);
SetUnhandledExceptionFilter(TopLevelExceptionFilter);
result = j_NtQueryInformationProcess((HANDLE)0xFFFFFFFF, ProcessDebugPort, &ProcessInformation, 4u, 0);
if ( !result )
{
if ( ProcessInformation != 1 )
{
CurrentProcess = GetCurrentProcess();
TerminateProcess(CurrentProcess, 1u);
}
return 9 / 0;
}
return result;
}

看汇编把result判断的jnz改成jz就能跳过去,最牛的是这个tls里有一个veh,当我们主程序出现除0异常的时候,会跳到handle这个地方

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
int sub_239050()
{
char v0; // al
unsigned __int8 v1; // al
int result; // eax
char v3; // al
unsigned __int8 v4; // al
__int64 v5; // [esp-8h] [ebp-11Ch]
int v6; // [esp+10h] [ebp-104h]
int v7; // [esp+1Ch] [ebp-F8h]
char v8[12]; // [esp+28h] [ebp-ECh] BYREF
int v9; // [esp+34h] [ebp-E0h]
unsigned __int8 j; // [esp+103h] [ebp-11h]
unsigned __int8 i; // [esp+10Fh] [ebp-5h]

__CheckForDebuggerJustMyCode(byte_2470F4);
for ( i = 0; i < 0x10u; ++i )
{
for ( j = 0; j < 0x10u; ++j )
{
v5 = (j & 0xF) + (unsigned __int8)(16 * i);
sub_231442(v5, SHIDWORD(v5));
dword_244000[16 * i + j] = v9;
}
}
for ( i = 0; i < 0x10u; ++i )
{
for ( j = 0; j < 0x10u; ++j )
{
sub_231442(0, 0);
if ( (unsigned __int8)sub_2313AC((int)v8) )
{
v0 = sub_2312E4(&dword_244000[16 * i + j]);
v1 = sub_2315BE(v0, 283);
sub_231442(v1, 0);
dword_244000[16 * i + j] = v7;
}
}
}
for ( i = 0; ; ++i )
{
result = i;
if ( i >= 0x10u )
break;
for ( j = 0; j < 0x10u; ++j )
{
v3 = sub_2312E4(&dword_244000[16 * i + j]);
v4 = sub_231299(v3, 119);
sub_231442(v4, 0);
dword_244000[16 * i + j] = v6;
}
}
return result;
}

这个地方是对sbox进行的魔改,通过动调可以知道,他将逆sbox和sbox行列颠倒了,这是第一次魔改,再看主函数:

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
int __cdecl main_0(int argc, const char **argv, const char **envp)
{
int v3; // eax
int j; // [esp+D0h] [ebp-1D8h]
int i; // [esp+DCh] [ebp-1CCh]
char v7[184]; // [esp+E8h] [ebp-1C0h] BYREF
char v8[4]; // [esp+1A0h] [ebp-108h] BYREF
_DWORD v9[16]; // [esp+1E8h] [ebp-C0h] BYREF
int v10; // [esp+228h] [ebp-80h] BYREF
char Str[52]; // [esp+270h] [ebp-38h] BYREF

__CheckForDebuggerJustMyCode(byte_2470F4);
j_memset(Str, 0, 0x30u);
sub_2310AF((int)v9, 4, 32, (int)sub_23116D);
sub_2310F5(std::cin, Str);
if ( j_strlen(Str) != 32 )
exit(-1);
sub_231442(23, 0);
sub_231442(147, 0);
sub_231442(56, 0);
sub_231442(12, 0);
sub_231442(17, 0);
sub_231442(167, 0);
sub_231442(247, 0);
sub_231442(84, 0);
sub_231442(247, 0);
sub_231442(137, 0);
sub_231442(200, 0);
sub_231442(32, 0);
sub_231442(212, 0);
sub_231442(26, 0);
sub_231442(250, 0);
sub_231442(37, 0);
sub_23124E(Str, v9, 32);
sub_2310AF((int)v7, 4, 44, (int)sub_2313D4);
sub_231483((int)v8, (int)v7);//初始化
sub_2315FF((int)v9, (int)v7);//主要加密
for ( i = 0; i < 16; ++i )
sub_23164A(&v9[i]);//对key进行异或
sub_231483((int)v8, (int)v7);//初始化
sub_2315FF((int)&v10, (int)v7);//主要加密
for ( j = 0; j < 32; ++j )
{
if ( (unsigned __int8)sub_2313AC((int)&v9[j]) )
exit(-1);
}
v3 = sub_2312BC(std::cout, "Congratulations! Your flag is: flag{(your input)}");
std::ostream::operator<<(v3, sub_23105A);
return 0;
}

这个加密是将32位的字符串先进行前16位aes加密,然后得到加密后的16位再与之前的key进行异或,然后得到后16位的key

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
#include <stdio.h>
#include <stdint.h>
#include <memory.h>
/****************************************************************************************************************/
typedef enum {
AES_CYPHER_128,
AES_CYPHER_192,
AES_CYPHER_256,
} AES_CYPHER_T;
/****************************************************************************************************************/
/*
* Encryption Rounds
*/
int g_aes_key_bits[] = {
/* AES_CYPHER_128 */ 128,
/* AES_CYPHER_192 */ 192,
/* AES_CYPHER_256 */ 256,
};
int g_aes_rounds[] = {
/* AES_CYPHER_128 */ 10,
/* AES_CYPHER_192 */ 12,
/* AES_CYPHER_256 */ 14,
};
int g_aes_nk[] = {
/* AES_CYPHER_128 */ 4,
/* AES_CYPHER_192 */ 6,
/* AES_CYPHER_256 */ 8,
};
int g_aes_nb[] = {
/* AES_CYPHER_128 */ 4,
/* AES_CYPHER_192 */ 4,
/* AES_CYPHER_256 */ 4,
};
/****************************************************************************************************************/
/*
* aes Rcon:
*
* WARNING: Rcon is designed starting from 1 to 15, not 0 to 14.
* FIPS-197 Page 9: "note that i starts at 1, not 0"
*
* i | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
* -----+------------------------------------------------------------------------------------------
* | [01] [02] [04] [08] [10] [20] [40] [80] [1b] [36] [6c] [d8] [ab] [4d] [9a]
* RCON | [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00]
* | [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00]
* | [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00] [00]
*/
static const uint32_t g_aes_rcon[] = {
0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000,
0x1b000000, 0x36000000, 0x6c000000, 0xd8000000, 0xab000000, 0xed000000, 0x9a000000
};
/****************************************************************************************************************/
/*
* aes sbox and invert-sbox
*/
static const uint8_t g_aes_sbox[256] = {
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
0x77,0x68,0x63,0x6f,0xe6,0x7f,0x7b,0xd1,0x24,0x15,0x73,0x3f,0xea,0xc3,0xbf,0x62,0xde,0x96,0xdd,0x69,0xee,0x4d,0x53,0xe4,0xb9,0xc0,0xb6,0xbb,0x88,0xb0,0x66,0xd4,0xa3,0xe9,0x87,0x32,0x22,0x2b,0xe3,0xd8,0x20,0xb1,0xf1,0xe5,0x65,0xcc,0x25,0x1,0x10,0xd3,0x37,
0xd7,0xc,0x82,0x11,0x8e,0x13,0x6,0x94,0xf6,0xff,0x33,0xa6,0x61,0x1d,0x97,0x38,0xe,0xf,0x7a,0x4e,0xb4,0x46,0x2f,0xc2,0xa7,0x3d,0xf7,0x3b,0x90,0x47,0xc5,0x14,0xf9,0x34,0xe8,0xa5
,0x4f,0x7e,0xdf,0xaa,0x2d,0x5e,0x58,0x4c,0xdb,0xc4,0xfb,0xbe,0xef,0x57,0x59,0x27,0x91,0x51,0xed,0x16,0x6b,0x44,0x28,0x8b,0xbc,0x45,0xb7,0x54,0x9b,0x86,0x89,0x2c,0xe1,0xa8,0xa2,0xce,0x35,0x4,0xeb,0xe7,0xc6,0xd9,0x18,0x7,0xf8,0x4b,0x83,0x50,0x3,0xd0,0xb3,0x6a,0x29,0x70,0x49,0xd,0x67,0x74,0x95,0x5b,0xc8,0x36,0x3e,0x84,0x9c,0x52,0xfa,0xac,0x0,0xca,
0x4a,0x1f,0xcf,0xf4,0x26,0x2e,0x1e,0x5d,0x12,0x30,0x48,0xd6,0xc7,0xb8,0x76,0x85,0x81,0xf0,0x6d,0xf3,0xdc,0x23,0x79,0x99,0xc1,0x5a,0xbd,0x78,0x42,0xe0,0xfe,0x71,0x6e,0xba,0x1c
,0xae,0x6c,0x31,0x3a,0x8,0xb2,0xa0,0xd2,0xfc,0xc9,0x60,0xb,0x5f,0xa9,0x9f,0x9e,0x64,0x2a
,0xa1,0x72,0x5c,0x17,0xe2,0x1a,0x75,0x21,0x43,0xad,0x92,0xd5,0x9,0x8a,0xf5,0xec,0x8c,0x5,0x7d,0xcd,0x9a,0x80,0x8f,0xa,0x93,0xfd,0xda,0x41,0x3c,0xcb,0x98,0xb5,0x9d,0x19,0xab,0xf2,0x56,0x7c,0x55,0x8d,0x39,0x1b,0xa4,0x40,0xaf,0x2
};
static const uint8_t g_inv_sbox[256] = {
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
0x9B,0x2F,0xFF,0x87,0x7C,0xE3,0x39,0x82,0xC4,0xDE,0xE9,0xCB,0x34,0x8E,0x43,0x44,
0x30,0x36,0xA5,0x38,0x52,0x09,0x6A,0xD5,0x81,0xF3,0xD7,0xFB,0xBF,0x40,0xA3,0x9E,0x28
,0xD9,0x24,0xB2,0x08,0x2E,0xA1,0x66,0x6D,0x8B,0xD1,0x25,0x76,0x5B,0xA2,0x49,0xA6,0xC2,0x23,0x3D,0x54,0x7B,0x94,0x32,0x42,0xFA,0xC3,0x4E,0xEE,0x4C,0x95,0x0B,0xFD,0xED,0xB9,0xDA,0x6C,0x70,0x48,0x50,0xA7,0x8D,0x9D,0x84,0x5E,0x15,0x46,0x57,0x86,0x68,0x98,0x16,0x72,0xF8,0xF6,0x64,0x5D,0x65,0xB6,0x92,0xD4,0xA4,0x5C,0xCC,0xCA,0x3F,0x0F,0x02,0xD0,0x2C,0x1E,0x8F,0x01,0x13,0x8A,0x6B,0xC1,0xAF,0xBD,0x03,0x8C,0xBC,0xD3,0x0A,0x90,0xD8,0xAB,0x00,0xB8,0xB3,0x45,0x06,0xF7,0xE4,0x58,0x05,0xE7,0xAD,0x35,0x85,0x96,
0xAC,0x74,0x22,0x1C,0x75,0xDF,0x6E,0xE2,0xF9,0x37,0xE8,0x4F,0x67,0xDC,0xEA,0x3A,0x91,0x11,0x41,0xF0,0xB4,0xE6,0x73,0x97,0xF2,0xCF,0xCE,0xC6,0xD2,0x79,0x20,0xFC,0x56,0x3E,0x4B,0x78,0xCD,0x5A,0xF4,0x9A,0xDB,0xC0,0xFE,0x1D,0x29,0xC5,0x89,0x47,0xF1,0x1A,0x71,0xAA,0x18,0xBE,0x1B,0x6F,0xB7,0x62,0x0E,0x19,0xB5,0x4A,0x0D,0x60,0x51,0x7F,0xA9,
0x93,0xC9,0x9C,0xEF,0x2D,0xE5,0x7A,0x9F,0x88,0x07,0xC7,0x31,0x1F,0xDD,0xA8,0x33,0x27,0x80,0xEC,0x5F,0xB1,0x12,0x10,0x59,0xBA,0x77,0xD6,0x26,0x17,0x2B,0x04,0x7E,0x55,0x21,0x0C,0x7D,0xE1,0x69,0x14,0x63,0xAE,0x2A,0xF5,0xB0,0xA0,0xE0,0x3B,0x4D,0x83,0x53,0x99,0x61,0xC8,0xEB,0xBB,0x3C
};
/****************************************************************************************************************/
uint8_t aes_sub_sbox(uint8_t val)
{
return g_aes_sbox[val];
}
/****************************************************************************************************************/
uint32_t aes_sub_dword(uint32_t val)
{
uint32_t tmp = 0;

tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 0) & 0xFF))) << 0;
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 8) & 0xFF))) << 8;
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 16) & 0xFF))) << 16;
tmp |= ((uint32_t)aes_sub_sbox((uint8_t)((val >> 24) & 0xFF))) << 24;

return tmp;
}
/****************************************************************************************************************/
uint32_t aes_rot_dword(uint32_t val)
{
uint32_t tmp = val;

return (val >> 8) | ((tmp & 0xFF) << 24);
}
/****************************************************************************************************************/
uint32_t aes_swap_dword(uint32_t val)
{
return (((val & 0x000000FF) << 24) |
((val & 0x0000FF00) << 8) |
((val & 0x00FF0000) >> 8) |
((val & 0xFF000000) >> 24));
}
/****************************************************************************************************************/
/*
* nr: number of rounds
* nb: number of columns comprising the state, nb = 4 dwords (16 bytes)
* nk: number of 32-bit words comprising cipher key, nk = 4, 6, 8 (KeyLength/(4*8))
*/
void aes_key_expansion(AES_CYPHER_T mode, uint8_t *key, uint8_t *round)
{
uint32_t *w = (uint32_t *)round;
uint32_t t;
int i = 0;

do {
w[i] = *((uint32_t *)&key[i * 4 + 0]);
} while (++i < g_aes_nk[mode]);

do {
if ((i % g_aes_nk[mode]) == 0) {
t = aes_rot_dword(w[i - 1]);
t = aes_sub_dword(t);
t = t ^ aes_swap_dword(g_aes_rcon[i / g_aes_nk[mode] - 1]);
}
else if (g_aes_nk[mode] > 6 && (i % g_aes_nk[mode]) == 4) {
t = aes_sub_dword(w[i - 1]);
}
else {
t = w[i - 1];
}
w[i] = w[i - g_aes_nk[mode]] ^ t;
} while (++i < g_aes_nb[mode] * (g_aes_rounds[mode] + 1));
}
/****************************************************************************************************************/
void aes_add_round_key(AES_CYPHER_T mode, uint8_t *state,
uint8_t *round, int nr)
{
uint32_t *w = (uint32_t *)round;
uint32_t *s = (uint32_t *)state;
int i;

for (i = 0; i < g_aes_nb[mode]; i++) {
s[i] ^= w[nr * g_aes_nb[mode] + i];
}
}
/****************************************************************************************************************/
void aes_sub_bytes(AES_CYPHER_T mode, uint8_t *state)
{
int i, j;

for (i = 0; i < g_aes_nb[mode]; i++) {
for (j = 0; j < 4; j++) {
state[i * 4 + j] = aes_sub_sbox(state[i * 4 + j]);
}
}
}
/****************************************************************************************************************/
void aes_shift_rows(AES_CYPHER_T mode, uint8_t *state)
{
uint8_t *s = (uint8_t *)state;
int i, j, r;

for (i = 1; i < g_aes_nb[mode]; i++) {
for (j = 0; j < i; j++) {
uint8_t tmp = s[i];
for (r = 0; r < g_aes_nb[mode]; r++) {
s[i + r * 4] = s[i + (r + 1) * 4];
}
s[i + (g_aes_nb[mode] - 1) * 4] = tmp;
}
}
}
/****************************************************************************************************************/
uint8_t aes_xtime(uint8_t x)
{
return ((x << 1) ^ (((x >> 7) & 1) * 0x1b));
}
/****************************************************************************************************************/
uint8_t aes_xtimes(uint8_t x, int ts)
{
while (ts-- > 0) {
x = aes_xtime(x);
}

return x;
}
/****************************************************************************************************************/
uint8_t aes_mul(uint8_t x, uint8_t y)
{
/*
* encrypt: y has only 2 bits: can be 1, 2 or 3
* decrypt: y could be any value of 9, b, d, or e
*/

return ((((y >> 0) & 1) * aes_xtimes(x, 0)) ^
(((y >> 1) & 1) * aes_xtimes(x, 1)) ^
(((y >> 2) & 1) * aes_xtimes(x, 2)) ^
(((y >> 3) & 1) * aes_xtimes(x, 3)) ^
(((y >> 4) & 1) * aes_xtimes(x, 4)) ^
(((y >> 5) & 1) * aes_xtimes(x, 5)) ^
(((y >> 6) & 1) * aes_xtimes(x, 6)) ^
(((y >> 7) & 1) * aes_xtimes(x, 7)));
}
/****************************************************************************************************************/
void aes_mix_columns(AES_CYPHER_T mode, uint8_t *state)
{
uint8_t y[16] = { 2, 3, 1, 1, 1, 2, 3, 1, 1, 1, 2, 3, 3, 1, 1, 2 };
uint8_t s[4];
int i, j, r;

for (i = 0; i < g_aes_nb[mode]; i++) {
for (r = 0; r < 4; r++) {
s[r] = 0;
for (j = 0; j < 4; j++) {
s[r] = s[r] ^ aes_mul(state[i * 4 + j], y[r * 4 + j]);
}
}
for (r = 0; r < 4; r++) {
state[i * 4 + r] = s[r];
}
}
}
/****************************************************************************************************************/
int aes_encrypt(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key)
{
uint8_t w[4 * 4 * 15] = { 0 }; /* round key */
uint8_t s[4 * 4] = { 0 }; /* state */

int nr, i, j;

/* key expansion */
aes_key_expansion(mode, key, w);

/* start data cypher loop over input buffer */
for (i = 0; i < len; i += 4 * g_aes_nb[mode]) {

/* init state from user buffer (plaintext) */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
s[j] = data[i + j];

/* start AES cypher loop over all AES rounds */
for (nr = 0; nr <= g_aes_rounds[mode]; nr++) {

if (nr > 0) {

/* do SubBytes */
aes_sub_bytes(mode, s);

/* do ShiftRows */
aes_shift_rows(mode, s);

if (nr < g_aes_rounds[mode]) {
/* do MixColumns */
aes_mix_columns(mode, s);
}
}

/* do AddRoundKey */
aes_add_round_key(mode, s, w, nr);
}

/* save state (cypher) to user buffer */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
data[i + j] = s[j];
}

return 0;
}
/****************************************************************************************************************/
int aes_encrypt_ecb(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key)
{
return aes_encrypt(mode, data, len, key);
}
/****************************************************************************************************************/
int aes_encrypt_cbc(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key, uint8_t *iv)
{
uint8_t w[4 * 4 * 15] = { 0 }; /* round key */
uint8_t s[4 * 4] = { 0 }; /* state */
uint8_t v[4 * 4] = { 0 }; /* iv */

int nr, i, j;


/* key expansion */
aes_key_expansion(mode, key, w);

memcpy(v, iv, sizeof(v));

/* start data cypher loop over input buffer */
for (i = 0; i < len; i += 4 * g_aes_nb[mode]) {

/* init state from user buffer (plaintext) */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
s[j] = data[i + j] ^ v[j];

/* start AES cypher loop over all AES rounds */
for (nr = 0; nr <= g_aes_rounds[mode]; nr++) {

if (nr > 0) {

/* do SubBytes */
aes_sub_bytes(mode, s);

/* do ShiftRows */
aes_shift_rows(mode, s);

if (nr < g_aes_rounds[mode]) {
/* do MixColumns */
aes_mix_columns(mode, s);
}
}

/* do AddRoundKey */
aes_add_round_key(mode, s, w, nr);
}

/* save state (cypher) to user buffer */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
data[i + j] = v[j] = s[j];
}

return 0;
}
/****************************************************************************************************************/
void inv_shift_rows(AES_CYPHER_T mode, uint8_t *state)
{
uint8_t *s = (uint8_t *)state;
int i, j, r;

for (i = 1; i < g_aes_nb[mode]; i++) {
for (j = 0; j < g_aes_nb[mode] - i; j++) {
uint8_t tmp = s[i];
for (r = 0; r < g_aes_nb[mode]; r++) {
s[i + r * 4] = s[i + (r + 1) * 4];
}
s[i + (g_aes_nb[mode] - 1) * 4] = tmp;
}
}
}
/****************************************************************************************************************/
uint8_t inv_sub_sbox(uint8_t val)
{
return g_inv_sbox[val];
}
/****************************************************************************************************************/
void inv_sub_bytes(AES_CYPHER_T mode, uint8_t *state)
{
int i, j;

for (i = 0; i < g_aes_nb[mode]; i++) {
for (j = 0; j < 4; j++) {
state[i * 4 + j] = inv_sub_sbox(state[i * 4 + j]);
}
}
}
/****************************************************************************************************************/
void inv_mix_columns(AES_CYPHER_T mode, uint8_t *state)
{
uint8_t y[16] = { 0x0e, 0x0b, 0x0d, 0x09, 0x09, 0x0e, 0x0b, 0x0d,
0x0d, 0x09, 0x0e, 0x0b, 0x0b, 0x0d, 0x09, 0x0e };
uint8_t s[4];
int i, j, r;

for (i = 0; i < g_aes_nb[mode]; i++) {
for (r = 0; r < 4; r++) {
s[r] = 0;
for (j = 0; j < 4; j++) {
s[r] = s[r] ^ aes_mul(state[i * 4 + j], y[r * 4 + j]);
}
}
for (r = 0; r < 4; r++) {
state[i * 4 + r] = s[r];
}
}
}
/****************************************************************************************************************/
int aes_decrypt(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key)
{
uint8_t w[4 * 4 * 15] = { 0 }; /* round key */
uint8_t s[4 * 4] = { 0 }; /* state */

int nr, i, j;
//魔改
for(i=0;i<4;i++){
for(j=0;j<4;j++){
s[i+j*4]=data[i*4+j];
}
}
/* key expansion */
aes_key_expansion(mode, key, w);

/* start data cypher loop over input buffer */
for (i = 0; i < len; i += 4 * g_aes_nb[mode]) {

/* init state from user buffer (cyphertext) */
//for (j = 0; j < 4 * g_aes_nb[mode]; j++)
//s[j] = data[i + j];

/* start AES cypher loop over all AES rounds */
for (nr = g_aes_rounds[mode]; nr >= 0; nr--) {

/* do AddRoundKey */
aes_add_round_key(mode, s, w, nr);

if (nr > 0) {

if (nr < g_aes_rounds[mode]) {
/* do MixColumns */
inv_mix_columns(mode, s);
}

/* do ShiftRows */
inv_shift_rows(mode, s);

/* do SubBytes */
inv_sub_bytes(mode, s);
}
}

/* save state (cypher) to user buffer */
//for (j = 0; j < 4 * g_aes_nb[mode]; j++)
//data[i + j] = s[j];
//魔改
for(i=0;i<4;i++){
for(j=0;j<4;j++){
data[i*4+j]=s[i+j*4];
}
}
}

return 0;
}
/****************************************************************************************************************/
int aes_decrypt_ecb(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key)
{
return aes_decrypt(mode, data, len, key);
}
/****************************************************************************************************************/
int aes_decrypt_cbc(AES_CYPHER_T mode, uint8_t *data, int len, uint8_t *key, uint8_t *iv)
{
uint8_t w[4 * 4 * 15] = { 0 }; /* round key */
uint8_t s[4 * 4] = { 0 }; /* state */
uint8_t v[4 * 4] = { 0 }; /* iv */


int nr, i, j;

/* key expansion */
aes_key_expansion(mode, key, w);

memcpy(v, iv, sizeof(v));

/* start data cypher loop over input buffer */
for (i = 0; i < len; i += 4 * g_aes_nb[mode]) {


/* init state from user buffer (cyphertext) */
for (j = 0; j < 4 * g_aes_nb[mode]; j++)
s[j] = data[i + j];

/* start AES cypher loop over all AES rounds */
for (nr = g_aes_rounds[mode]; nr >= 0; nr--) {

/* do AddRoundKey */
aes_add_round_key(mode, s, w, nr);

if (nr > 0) {

if (nr < g_aes_rounds[mode]) {
/* do MixColumns */
inv_mix_columns(mode, s);
}

/* do ShiftRows */
inv_shift_rows(mode, s);

/* do SubBytes */
inv_sub_bytes(mode, s);
}
}

/* save state (cypher) to user buffer */
for (j = 0; j < 4 * g_aes_nb[mode]; j++) {
uint8_t p = s[j] ^ v[j];
v[j] = data[i + j];
data[i + j] = p;
}
}

return 0;
}
/****************************************************************************************************************/
void aes_cypher_128_test()
{
#if 1
uint8_t buf[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
uint8_t key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
#else
uint8_t buf[] = { 0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d,
0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34 };
uint8_t key[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c };
#endif

aes_encrypt(AES_CYPHER_128, buf, sizeof(buf), key);

aes_decrypt(AES_CYPHER_128, buf, sizeof(buf), key);
}
/****************************************************************************************************************/
void aes_cypher_192_test()
{
uint8_t buf[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
uint8_t key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };

aes_encrypt(AES_CYPHER_192, buf, sizeof(buf), key);

aes_decrypt(AES_CYPHER_192, buf, sizeof(buf), key);
}
/****************************************************************************************************************/
void aes_cypher_256_test()
{
uint8_t buf[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
uint8_t key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f };

aes_encrypt(AES_CYPHER_256, buf, sizeof(buf), key);

aes_decrypt(AES_CYPHER_256, buf, sizeof(buf), key);
}
/****************************************************************************************************************/
void main()
{
//数据
uint8_t buf[] = { 216, 87, 202, 196, 68, 68, 17, 110, 131, 11, 223, 113, 103, 120, 149,
125};

//密钥
uint8_t key[] = {23, 147, 56, 12, 17, 167, 247, 84, 247, 137, 200, 32, 212, 26, 250, 37};
//向量
uint8_t iv[] = {0x4d,0x4f,0x4d,0x43,0x45,0x47,0x45,0x43,0x5d,0x5f,0x5d,0x43,0x45,0x47,0x45,0x43};
switch (sizeof(key))
{
//ECB
case 16:aes_decrypt(AES_CYPHER_128, buf, sizeof(buf), key); break;
case 24:aes_decrypt(AES_CYPHER_192, buf, sizeof(buf), key); break;
case 32:aes_decrypt(AES_CYPHER_256, buf, sizeof(buf), key); break;
//CBC
/*
case 16:aes_decrypt_cbc(AES_CYPHER_128, buf, sizeof(buf), key, iv); break;
case 24:aes_decrypt_cbc(AES_CYPHER_192, buf, sizeof(buf), key, iv); break;
case 32:aes_decrypt_cbc(AES_CYPHER_256, buf, sizeof(buf), key, iv); break;
}
*/
}
for (int i = 0; i < sizeof(buf); i++)
{
printf("%c", buf[i] & 0xFF);
}
printf("\n");
return;
}
// 数据
uint8_t buf[] = { 180, 252, 42, 112, 54, 254, 140, 77, 50, 8, 226, 68, 27, 196, 57, 3 };
// 密钥
uint8_t key[] = { 207, 196, 242, 200, 85, 227, 230, 58, 116, 130, 23, 81, 179, 98, 111, 88 };

得到flag