0%

classicproblem

VMproblem

这是一道vm+golong的题,我们主要学习vm的解题技巧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void __cdecl main_main()
{
__int64 v0; // rcx
__int64 v1; // [rsp+10h] [rbp-18h]
void *v2; // [rsp+18h] [rbp-10h]
void *retaddr; // [rsp+28h] [rbp+0h] BYREF

while ( (unsigned __int64)&retaddr <= *(_QWORD *)(*(_QWORD *)NtCurrentTeb()->NtTib.ArbitraryUserPointer + 16LL) )
runtime_morestack_noctxt();
v1 = runtime_newobject((__int64)&unk_4D3F60);
main___ptr_MzVm__init(v1);
v2 = (void *)runtime_newobject((__int64)&unk_4C3940);
qmemcpy(v2, &unk_57D8A0, 0x2EE0uLL);
if ( dword_5B97D0 )
{
runtime_gcWriteBarrier();
}
else
{
v0 = v1;
*(_QWORD *)(v1 + 4096) = v2;
}
main___ptr_MzVm__run(v0);
}

这是主函数,能猜测出unk_57D8A0,就是opcode,我个人认为opcode相当于是出题人在这台vm机器上做了什么事!

接下来我们进入函数main___ptr_MzVm__run(v0),

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
void __golang main___ptr_MzVm__run(__int64 a1)
{
__int64 v1; // rbx
__int64 v2; // rsi
unsigned __int64 v3; // rax
unsigned __int64 v4; // rdi
unsigned __int64 v5; // r8
unsigned int v6; // er8
unsigned __int64 v7; // rax
unsigned int v8; // esi
__int64 v9; // [rsp+0h] [rbp-18h]
void *retaddr; // [rsp+18h] [rbp+0h] BYREF

while ( (unsigned __int64)&retaddr <= *(_QWORD *)(*(_QWORD *)NtCurrentTeb()->NtTib.ArbitraryUserPointer + 16LL) )
runtime_morestack_noctxt();
v1 = a1;
while ( !*(_BYTE *)(v1 + 4904) )
{
v2 = *(_QWORD *)(v1 + 4096);
v3 = *(unsigned int *)(v1 + 4084);
if ( v3 >= 0xBB8 )
runtime_panicIndex(v9);
v4 = *(unsigned int *)(v2 + 4 * v3);
v5 = (unsigned int)(v3 + 1);
if ( v5 >= 0xBB8 )
runtime_panicIndex(v9);
v6 = *(_DWORD *)(v2 + 4 * v5);
v7 = (unsigned int)(v3 + 2);
if ( v7 >= 0xBB8 )
runtime_panicIndex(v9);
v8 = *(_DWORD *)(v2 + 4 * v7);
if ( v4 >= 0x64 ) //组合为64位
runtime_panicIndex(v9);
v9 = __PAIR64__(v8, v6);
(**(void (***)(void))(v1 + 8 * v4 + 4104))();//这个是opcode的地址,也就是func2的指令
v1 = a1;
*(_DWORD *)(a1 + 4084) += 3;//指令长度3字节
}
}

也就是说,我们通过对地址偏移的分析,就能够还原每个opcode的指令

先看init的函数,我们的opcode是在这里执行的

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
__int64 (__usercall **__usercall main___ptr_MzVm__init@<rax>(__int64 a1))@<rax>(__int64 a1)
{
__int64 (__usercall **result)@<rax>(__int64); // rax
__int64 v2; // [rsp+8h] [rbp-10h]
void *retaddr; // [rsp+18h] [rbp+0h] BYREF

while ( (unsigned __int64)&retaddr <= *(_QWORD *)(*(_QWORD *)NtCurrentTeb()->NtTib.ArbitraryUserPointer + 16LL) )
runtime_morestack_noctxt();
*(_BYTE *)(a1 + 4904) = 0;
*(_QWORD *)(a1 + 4084) = 0x3E800000000LL;
if ( dword_A197D0 )
runtime_gcWriteBarrierCX();
else
*(_QWORD *)(a1 + 4104) = &off_9462D0;//这个地址对应的是1,0,87,我们要将func2与其对应
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func2;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4112) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func3;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4120) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func4;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4128) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func5;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4136) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func6;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4144) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func7;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4152) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func8;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4160) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func9;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4168) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func10;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4176) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func11;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4184) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func12;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4192) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func13;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4200) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func14;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4208) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func15;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4216) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func16;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4224) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func17;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4232) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func18;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4880) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
*(_QWORD *)v2 = main___ptr_MzVm__init_func19;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4888) = v2;
}
runtime_newobject((__int64)&unk_9295E0);
result = (__int64 (__usercall **)@<rax>(__int64))v2;
*(_QWORD *)v2 = main___ptr_MzVm__init_func20;
if ( dword_A197D0 )
{
runtime_gcWriteBarrierCX();
return (__int64 (__usercall **)@<rax>(__int64))runtime_gcWriteBarrier();
}
else
{
*(_QWORD *)(v2 + 8) = a1;
*(_QWORD *)(a1 + 4896) = v2;
}
return result;
}

简单分析几个函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int64 __usercall main___ptr_MzVm__init_func2@<rax>(__int64 a1)
{
__int64 v1; // rdx
__int64 v2; // rdx
__int64 result; // rax
__int64 v4; // [rsp+0h] [rbp-18h]

v2 = *(_QWORD *)(v1 + 8);
result = (unsigned int)a1;
if ( (unsigned int)a1 >= 0x15uLL )//存在0x14个寄存器
runtime_panicIndex(v4);
*(_DWORD *)(v2 + 4LL * (unsigned int)a1) = HIDWORD(a1);//取高位
return result;
}

func3 mov r[{Lnum}],r[{Rnum}]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
__int64 __usercall main___ptr_MzVm__init_func15@<rax>(__int64 a1)
{
__int64 v1; // rdx
__int64 v2; // rdx
__int64 result; // rax
__int64 v4; // [rsp+0h] [rbp-18h]

v2 = *(_QWORD *)(v1 + 8);
if ( (unsigned int)a1 >= 0x15uLL )
runtime_panicIndex(v4);
if ( HIDWORD(a1) >= 0x15uLL )
runtime_panicIndex(v4);
result = *(unsigned int *)(v2 + 4LL * HIDWORD(a1));
if ( (_DWORD)result != *(_DWORD *)(v2 + 4LL * (unsigned int)a1) )
{
result = (unsigned int)(3 * *(_DWORD *)(v2 + 76));
*(_DWORD *)(v2 + 4084) = result;
}
return result;
}

这个明显是个对比函数,cmp R[{num}] R[{right}], jne R[19]

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
op=[[0, 0, 0], [0, 0, 0], [1, 0, 87], [98, 0, 0], [1, 0, 101], [98, 0, 0], [1, 0, 108], [98, 0, 0], [1, 0, 99], [98, 0, 0], [1, 0, 111], [98, 0, 0], [1, 0, 109], [98, 0, 0], [1, 0, 101], [98, 0, 0], [1, 0, 32], [98, 0, 0], [1, 0, 116], [98, 0, 0], [1, 0, 111], [98, 0, 0], [1, 0, 32], [98, 0, 0], [1, 0, 86], [98, 0, 0], [1, 0, 78], [98, 0, 0], [1, 0, 67], [98, 0, 0], [1, 0, 84], [98, 0, 0], [1, 0, 70], [98, 0, 0], [1, 0, 50], [98, 0, 0], [1, 0, 48], [98, 0, 0], [1, 0, 50], [98, 0, 0], [1, 0, 50], [98, 0, 0], [1, 0, 33], [98, 0, 0], [1, 0, 10], [98, 0, 0], [1, 0, 105], [98, 0, 0], [1, 0, 110], [98, 0, 0], [1, 0, 112], [98, 0, 0], [1, 0, 117], [98, 0, 0], [1, 0, 116], [98, 0, 0], [1, 0, 32], [98, 0, 0], [1, 0, 102], [98, 0, 0], [1, 0, 108], [98, 0, 0], [1, 0, 97], [98, 0, 0], [1, 0, 103], [98, 0, 0], [1, 0, 58], [98, 0, 0], [1, 0, 10], [98, 0, 0], [1, 19, 73], [1, 3, 0], [1, 1, 43], [1, 2, 1], [97, 0, 0], [5, 0, 0], [8, 1, 2], [14, 1, 3], [1, 0, 0], [5, 0, 0], [0, 0, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 6, 0], [6, 0, 0], [7, 6, 0], [2, 0, 6], [10, 0, 5], [2, 6, 0], [6, 0, 0], [7, 6, 0], [2, 0, 6], [10, 0, 5], [2, 6, 0], [6, 0, 0], [7, 6, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 7, 0], [6, 0, 0], [7, 7, 0], [2, 0, 7], [10, 0, 5], [2, 7, 0], [6, 0, 0], [7, 7, 0], [2, 0, 7], [10, 0, 5], [2, 7, 0], [6, 0, 0], [7, 7, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 8, 0], [6, 0, 0], [7, 8, 0], [2, 0, 8], [10, 0, 5], [2, 8, 0], [6, 0, 0], [7, 8, 0], [2, 0, 8], [10, 0, 5], [2, 8, 0], [6, 0, 0], [7, 8, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 9, 0], [6, 0, 0], [7, 9, 0], [2, 0, 9], [10, 0, 5], [2, 9, 0], [6, 0, 0], [7, 9, 0], [2, 0, 9], [10, 0, 5], [2, 9, 0], [6, 0, 0], [7, 9, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 10, 0], [6, 0, 0], [7, 10, 0], [2, 0, 10], [10, 0, 5], [2, 10, 0], [6, 0, 0], [7, 10, 0], [2, 0, 10], [10, 0, 5], [2, 10, 0], [6, 0, 0], [7, 10, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 11, 0], [6, 0, 0], [7, 11, 0], [2, 0, 11], [10, 0, 5], [2, 11, 0], [6, 0, 0], [7, 11, 0], [2, 0, 11], [10, 0, 5], [2, 11, 0], [6, 0, 0], [7, 11, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 12, 0], [6, 0, 0], [7, 12, 0], [2, 0, 12], [10, 0, 5], [2, 12, 0], [6, 0, 0], [7, 12, 0], [2, 0, 12], [10, 0, 5], [2, 12, 0], [6, 0, 0], [7, 12, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 13, 0], [6, 0, 0], [7, 13, 0], [2, 0, 13], [10, 0, 5], [2, 13, 0], [6, 0, 0], [7, 13, 0], [2, 0, 13], [10, 0, 5], [2, 13, 0], [6, 0, 0], [7, 13, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 14, 0], [6, 0, 0], [7, 14, 0], [2, 0, 14], [10, 0, 5], [2, 14, 0], [6, 0, 0], [7, 14, 0], [2, 0, 14], [10, 0, 5], [2, 14, 0], [6, 0, 0], [7, 14, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 15, 0], [6, 0, 0], [7, 15, 0], [2, 0, 15], [10, 0, 5], [2, 15, 0], [6, 0, 0], [7, 15, 0], [2, 0, 15], [10, 0, 5], [2, 15, 0], [6, 0, 0], [7, 15, 0], [0, 0, 0], [6, 0, 0], [1, 5, 256], [10, 0, 5], [2, 16, 0], [6, 0, 0], [7, 16, 0], [2, 0, 16], [10, 0, 5], [2, 16, 0], [6, 0, 0], [7, 16, 0], [2, 0, 16], [10, 0, 5], [2, 16, 0], [6, 0, 0], [7, 16, 0], [0, 0, 0], [5, 6, 0], [5, 7, 0], [5, 8, 0], [5, 9, 0], [5, 10, 0], [5, 11, 0], [5, 12, 0], [5, 13, 0], [5, 14, 0], [5, 15, 0], [5, 16, 0], [6, 1, 0], [6, 2, 0], [1, 20, 284], [1, 0, 340], [12, 0, 0], [1, 0, 3906065887], [1, 19, 387], [1, 20, 339], [14, 1, 0], [1, 0, 4125344020], [14, 2, 0], [6, 1, 0], [6, 2, 0], [1, 20, 295], [1, 0, 340], [12, 0, 0], [1, 0, 579781142], [1, 19, 387], [1, 20, 339], [14, 1, 0], [1, 0, 2312395361], [14, 2, 0], [6, 1, 0], [6, 2, 0], [1, 20, 306], [1, 0, 340], [12, 0, 0], [1, 0, 1700499305], [1, 19, 387], [1, 20, 339], [14, 1, 0], [1, 0, 612671610], [14, 2, 0], [6, 1, 0], [6, 2, 0], [1, 20, 317], [1, 0, 340], [12, 0, 0], [1, 0, 3655723000], [1, 19, 387], [1, 20, 339], [14, 1, 0], [1, 0, 977540402], [14, 2, 0], [6, 1, 0], [6, 2, 0], [1, 20, 328], [1, 0, 340], [12, 0, 0], [1, 0, 2443935368], [1, 19, 387], [1, 20, 339], [14, 1, 0], [1, 0, 1778148540], [14, 2, 0], [6, 1, 0], [1, 0, 8206181], [14, 1, 0], [1, 0, 393], [12, 0, 0], [99, 0, 0], [1, 3, 2654435769], [1, 4, 613452], [1, 5, 34589], [1, 6, 108471], [1, 7, 1230791], [1, 8, 0], [1, 17, 16], [1, 18, 32], [1, 19, 352], [1, 10, 0], [1, 11, 32], [1, 12, 1], [7, 8, 3], [2, 0, 2], [10, 0, 17], [7, 0, 4], [2, 14, 0], [2, 0, 2], [7, 0, 8], [2, 15, 0], [2, 0, 2], [9, 0, 18], [7, 0, 5], [2, 16, 0], [2, 0, 14], [11, 0, 15], [11, 0, 16], [7, 1, 0], [2, 0, 1], [10, 0, 17], [7, 0, 6], [2, 14, 0], [2, 0, 1], [7, 0, 8], [2, 15, 0], [2, 0, 1], [9, 0, 18], [7, 0, 7], [2, 16, 0], [2, 0, 14], [11, 0, 15], [11, 0, 16], [7, 2, 0], [8, 11, 12], [14, 11, 10], [12, 20, 0], [0, 0, 0], [1, 0, 110], [98, 0, 0], [1, 0, 111], [98, 0, 0], [12, 20, 0], [0, 0, 0], [1, 0, 121], [98, 0, 0], [1, 0, 101], [98, 0, 0], [1, 0, 115], [98, 0, 0], [12, 20, 0]]
f=[]
for i in range(0,len(op),1):
if op[i][0] not in f:
f.append(op[i][0])
print(f)
for i in range(0,len(op)):

adr=op[i][0]
Lnum=op[i][1]
Rnum=op[i][2]
if adr==0:
print("%s: "%hex(i)+f"nop")
elif adr==1:
print("%s: "%hex(i)+f"mov r[{Lnum}],{hex(Rnum)}")
elif adr==2:
print("%s: "%hex(i)+f"mov r[{Lnum}],r[{Rnum}]")
elif adr==5:
print("%s: "%hex(i)+f"push r[{Lnum}]")
elif adr==6:
print("%s: "%hex(i)+f"pop r[{Lnum}]")
elif adr==7:
print("%s: "%hex(i)+f"add r[{Lnum}],r[{Rnum}]")
elif adr==8:
print("%s: "%hex(i)+f"sub r[{Lnum}],r[{Rnum}]")
elif adr==9:
print("%s: "%hex(i)+f"div r[{Lnum}],r[{Rnum}]")
elif adr==10:
print("%s: "%hex(i)+f"mul r[{Lnum}],r[{Rnum}]")
elif adr==11:
print("%s: "%hex(i)+f"xor r[{Lnum}],r[{Rnum}]")
elif adr==12:
print("%s: "%hex(i)+f"jmp r[{Lnum}]")
elif adr==14:
print("%s: "%hex(i)+f"cmp r[{Lnum}],r[{Rnum}] -- jnz r[19]")
elif adr==0x61:
print("%s: "%hex(i)+f"getchar(r[{Lnum}])")
elif adr==0x62:
print("%s: "%hex(i)+f'putchar(r[{Lnum})]')
elif adr==0x63:
print("%s: "%hex(i)+f"exit()")

得到:

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
0x0: nop
0x1: nop
0x2: mov r[0],0x57
0x3: putchar(r[0)]
0x4: mov r[0],0x65
0x5: putchar(r[0)]
0x6: mov r[0],0x6c
0x7: putchar(r[0)]
0x8: mov r[0],0x63
0x9: putchar(r[0)]
0xa: mov r[0],0x6f
0xb: putchar(r[0)]
0xc: mov r[0],0x6d
0xd: putchar(r[0)]
0xe: mov r[0],0x65
0xf: putchar(r[0)]
0x10: mov r[0],0x20
0x11: putchar(r[0)]
0x12: mov r[0],0x74
0x13: putchar(r[0)]
0x14: mov r[0],0x6f
0x15: putchar(r[0)]
0x16: mov r[0],0x20
0x17: putchar(r[0)]
0x18: mov r[0],0x56
0x19: putchar(r[0)]
0x1a: mov r[0],0x4e
0x1b: putchar(r[0)]
0x1c: mov r[0],0x43
0x1d: putchar(r[0)]
0x1e: mov r[0],0x54
0x1f: putchar(r[0)]
0x20: mov r[0],0x46
0x21: putchar(r[0)]
0x22: mov r[0],0x32
0x23: putchar(r[0)]
0x24: mov r[0],0x30
0x25: putchar(r[0)]
0x26: mov r[0],0x32
0x27: putchar(r[0)]
0x28: mov r[0],0x32
0x29: putchar(r[0)]
0x2a: mov r[0],0x21
0x2b: putchar(r[0)]
0x2c: mov r[0],0xa
0x2d: putchar(r[0)]
0x2e: mov r[0],0x69
0x2f: putchar(r[0)]
0x30: mov r[0],0x6e
0x31: putchar(r[0)]
0x32: mov r[0],0x70
0x33: putchar(r[0)]
0x34: mov r[0],0x75
0x35: putchar(r[0)]
0x36: mov r[0],0x74
0x37: putchar(r[0)]
0x38: mov r[0],0x20
0x39: putchar(r[0)]
0x3a: mov r[0],0x66
0x3b: putchar(r[0)]
0x3c: mov r[0],0x6c
0x3d: putchar(r[0)]
0x3e: mov r[0],0x61
0x3f: putchar(r[0)]
0x40: mov r[0],0x67
0x41: putchar(r[0)]
0x42: mov r[0],0x3a
0x43: putchar(r[0)]
0x44: mov r[0],0xa
0x45: putchar(r[0)] //输出函数,下面要输入了
0x46: mov r[19],0x49
0x47: mov r[3],0x0
0x48: mov r[1],0x2b //循环43次,知道了字符串长度
0x49: mov r[2],0x1
0x4a: getchar(r[0])//获取输入
0x4b: push r[0]
0x4c: sub r[1],r[2] //循环递减
0x4d: cmp r[1],r[3] -- jnz r[19]
0x4e: mov r[0],0x0
0x4f: push r[0] //多push⼀个0,44个byte转成11个int
0x50: nop
0x51: nop // 检验flag
0x52: pop r[0]
0x53: mov r[5],0x100 // 2的8次⽅,⽤于代替位移运算
0x54: mul r[0],r[5] // r0=r0*256 -> << 8
0x55: mov r[6],r[0] // r6=r0
0x56: pop r[0] // 将输⼊从末尾取出来
0x57: add r[6],r[0] // 加上之前的
0x58: mov r[0],r[6]
0x59: mul r[0],r[5]
0x5a: mov r[6],r[0] // 再次位移后放到r6
0x5b: pop r[0]
0x5c: add r[6],r[0]
0x5d: mov r[0],r[6]
0x5e: mul r[0],r[5]
0x5f: mov r[6],r[0]
0x60: pop r[0]
0x61: add r[6],r[0]
0x62: nop //用nop分割,下面是重复上面的
0x63: pop r[0]
0x64: mov r[5],0x100
0x65: mul r[0],r[5]
0x66: mov r[7],r[0]
0x67: pop r[0]
0x68: add r[7],r[0]
0x69: mov r[0],r[7]
0x6a: mul r[0],r[5]
0x6b: mov r[7],r[0]
0x6c: pop r[0]
0x6d: add r[7],r[0]
0x6e: mov r[0],r[7]
0x6f: mul r[0],r[5]
0x70: mov r[7],r[0]
0x71: pop r[0]
0x72: add r[7],r[0]
0x73: nop
0x74: pop r[0]
0x75: mov r[5],0x100
0x76: mul r[0],r[5]
0x77: mov r[8],r[0]
0x78: pop r[0]
0x79: add r[8],r[0]
0x7a: mov r[0],r[8]
0x7b: mul r[0],r[5]
0x7c: mov r[8],r[0]
0x7d: pop r[0]
0x7e: add r[8],r[0]
0x7f: mov r[0],r[8]
0x80: mul r[0],r[5]
0x81: mov r[8],r[0]
0x82: pop r[0]
0x83: add r[8],r[0]
0x84: nop
0x85: pop r[0]
0x86: mov r[5],0x100
0x87: mul r[0],r[5]
0x88: mov r[9],r[0]
0x89: pop r[0]
0x8a: add r[9],r[0]
0x8b: mov r[0],r[9]
0x8c: mul r[0],r[5]
0x8d: mov r[9],r[0]
0x8e: pop r[0]
0x8f: add r[9],r[0]
0x90: mov r[0],r[9]
0x91: mul r[0],r[5]
0x92: mov r[9],r[0]
0x93: pop r[0]
0x94: add r[9],r[0]
0x95: nop
0x96: pop r[0]
0x97: mov r[5],0x100
0x98: mul r[0],r[5]
0x99: mov r[10],r[0]
0x9a: pop r[0]
0x9b: add r[10],r[0]
0x9c: mov r[0],r[10]
0x9d: mul r[0],r[5]
0x9e: mov r[10],r[0]
0x9f: pop r[0]
0xa0: add r[10],r[0]
0xa1: mov r[0],r[10]
0xa2: mul r[0],r[5]
0xa3: mov r[10],r[0]
0xa4: pop r[0]
0xa5: add r[10],r[0]
0xa6: nop
0xa7: pop r[0]
0xa8: mov r[5],0x100
0xa9: mul r[0],r[5]
0xaa: mov r[11],r[0]
0xab: pop r[0]
0xac: add r[11],r[0]
0xad: mov r[0],r[11]
0xae: mul r[0],r[5]
0xaf: mov r[11],r[0]
0xb0: pop r[0]
0xb1: add r[11],r[0]
0xb2: mov r[0],r[11]
0xb3: mul r[0],r[5]
0xb4: mov r[11],r[0]
0xb5: pop r[0]
0xb6: add r[11],r[0]
0xb7: nop
0xb8: pop r[0]
0xb9: mov r[5],0x100
0xba: mul r[0],r[5]
0xbb: mov r[12],r[0]
0xbc: pop r[0]
0xbd: add r[12],r[0]
0xbe: mov r[0],r[12]
0xbf: mul r[0],r[5]
0xc0: mov r[12],r[0]
0xc1: pop r[0]
0xc2: add r[12],r[0]
0xc3: mov r[0],r[12]
0xc4: mul r[0],r[5]
0xc5: mov r[12],r[0]
0xc6: pop r[0]
0xc7: add r[12],r[0]
0xc8: nop
0xc9: pop r[0]
0xca: mov r[5],0x100
0xcb: mul r[0],r[5]
0xcc: mov r[13],r[0]
0xcd: pop r[0]
0xce: add r[13],r[0]
0xcf: mov r[0],r[13]
0xd0: mul r[0],r[5]
0xd1: mov r[13],r[0]
0xd2: pop r[0]
0xd3: add r[13],r[0]
0xd4: mov r[0],r[13]
0xd5: mul r[0],r[5]
0xd6: mov r[13],r[0]
0xd7: pop r[0]
0xd8: add r[13],r[0]
0xd9: nop
0xda: pop r[0]
0xdb: mov r[5],0x100
0xdc: mul r[0],r[5]
0xdd: mov r[14],r[0]
0xde: pop r[0]
0xdf: add r[14],r[0]
0xe0: mov r[0],r[14]
0xe1: mul r[0],r[5]
0xe2: mov r[14],r[0]
0xe3: pop r[0]
0xe4: add r[14],r[0]
0xe5: mov r[0],r[14]
0xe6: mul r[0],r[5]
0xe7: mov r[14],r[0]
0xe8: pop r[0]
0xe9: add r[14],r[0]
0xea: nop
0xeb: pop r[0]
0xec: mov r[5],0x100
0xed: mul r[0],r[5]
0xee: mov r[15],r[0]
0xef: pop r[0]
0xf0: add r[15],r[0]
0xf1: mov r[0],r[15]
0xf2: mul r[0],r[5]
0xf3: mov r[15],r[0]
0xf4: pop r[0]
0xf5: add r[15],r[0]
0xf6: mov r[0],r[15]
0xf7: mul r[0],r[5]
0xf8: mov r[15],r[0]
0xf9: pop r[0]
0xfa: add r[15],r[0]
0xfb: nop
0xfc: pop r[0]
0xfd: mov r[5],0x100
0xfe: mul r[0],r[5]
0xff: mov r[16],r[0]
0x100: pop r[0]
0x101: add r[16],r[0]
0x102: mov r[0],r[16]
0x103: mul r[0],r[5]
0x104: mov r[16],r[0]
0x105: pop r[0]
0x106: add r[16],r[0]
0x107: mov r[0],r[16]
0x108: mul r[0],r[5]
0x109: mov r[16],r[0]
0x10a: pop r[0]
0x10b: add r[16],r[0]
0x10c: nop
0x10d: push r[6]
0x10e: push r[7]
0x10f: push r[8]
0x110: push r[9]
0x111: push r[10]
0x112: push r[11]
0x113: push r[12]
0x114: push r[13]
0x115: push r[14]
0x116: push r[15]
0x117: push r[16] //十个值在寄存器中,此时全部转化为了uint32 将他们全部压栈
0x118: pop r[1]
0x119: pop r[2] //调用两个参数
0x11a: mov r[20],0x11c
0x11b: mov r[0],0x154
0x11c: jmp r[0]
0x11d: mov r[0],0xe8d1d5df // 对⽐结果
0x11e: mov r[19],0x183 // 错误输出的地址
0x11f: mov r[20],0x153 // 返回地址,直接结束
0x120: cmp r[1],r[0] -- jnz r[19] // ⽐较,不同就到错误输出
0x121: mov r[0],0xf5e3c114
0x122: cmp r[2],r[0] -- jnz r[19] // ⽐较,不同就到错误输出
0x123: pop r[1] ---------------------------第⼆轮加密和比较以此类推
0x124: pop r[2]
0x125: mov r[20],0x127
0x126: mov r[0],0x154
0x127: jmp r[0]
0x128: mov r[0],0x228ec216
0x129: mov r[19],0x183
0x12a: mov r[20],0x153
0x12b: cmp r[1],r[0] -- jnz r[19]
0x12c: mov r[0],0x89d45a61
0x12d: cmp r[2],r[0] -- jnz r[19]
0x12e: pop r[1]
0x12f: pop r[2]
0x130: mov r[20],0x132
0x131: mov r[0],0x154
0x132: jmp r[0]
0x133: mov r[0],0x655b8f69
0x134: mov r[19],0x183
0x135: mov r[20],0x153
0x136: cmp r[1],r[0] -- jnz r[19]
0x137: mov r[0],0x2484a07a
0x138: cmp r[2],r[0] -- jnz r[19]
0x139: pop r[1]
0x13a: pop r[2]
0x13b: mov r[20],0x13d
0x13c: mov r[0],0x154
0x13d: jmp r[0]
0x13e: mov r[0],0xd9e5e7f8
0x13f: mov r[19],0x183
0x140: mov r[20],0x153
0x141: cmp r[1],r[0] -- jnz r[19]
0x142: mov r[0],0x3a441532
0x143: cmp r[2],r[0] -- jnz r[19]
0x144: pop r[1]
0x145: pop r[2]
0x146: mov r[20],0x148
0x147: mov r[0],0x154
0x148: jmp r[0]
0x149: mov r[0],0x91ab7e88
0x14a: mov r[19],0x183
0x14b: mov r[20],0x153
0x14c: cmp r[1],r[0] -- jnz r[19]
0x14d: mov r[0],0x69fc64bc
0x14e: cmp r[2],r[0] -- jnz r[19]
0x14f: pop r[1]
0x150: mov r[0],0x7d3765
0x151: cmp r[1],r[0] -- jnz r[19]
0x152: mov r[0],0x189
0x153: jmp r[0]
0x154: exit()
0x155: mov r[3],0x9e3779b9 //delta,太经典了
0x156: mov r[4],0x95c4c //key1
0x157: mov r[5],0x871d //key2
0x158: mov r[6],0x1a7b7 //key3
0x159: mov r[7],0x12c7c7 //key4
0x15a: mov r[8],0x0 // sum
0x15b: mov r[17],0x10 // 常量16 ⽤于位移4
0x15c: mov r[18],0x20 // 常量32 ⽤于位移5
0x15d: mov r[19],0x160
0x15e: mov r[10],0x0 //⽤来对⽐次数
0x15f: mov r[11],0x20 //循环次数32次 加密轮数
0x160: mov r[12],0x1 // 跳转回这⾥的下⼀⾏
0x161: add r[8],r[3] // sum += delta
0x162: mov r[0],r[2]
0x163: mul r[0],r[17]
0x164: add r[0],r[4]
0x165: mov r[14],r[0]
0x166: mov r[0],r[2]
0x167: add r[0],r[8]
0x168: mov r[15],r[0]
0x169: mov r[0],r[2]
0x16a: div r[0],r[18]
0x16b: add r[0],r[5]
0x16c: mov r[16],r[0]
0x16d: mov r[0],r[14]
0x16e: xor r[0],r[15]
0x16f: xor r[0],r[16]
0x170: add r[1],r[0]
0x171: mov r[0],r[1]
0x172: mul r[0],r[17]
0x173: add r[0],r[6]
0x174: mov r[14],r[0]
0x175: mov r[0],r[1]
0x176: add r[0],r[8]
0x177: mov r[15],r[0]
0x178: mov r[0],r[1]
0x179: div r[0],r[18]
0x17a: add r[0],r[7]
0x17b: mov r[16],r[0]
0x17c: mov r[0],r[14]
0x17d: xor r[0],r[15]
0x17e: xor r[0],r[16]
0x17f: add r[2],r[0]
0x180: sub r[11],r[12]
0x181: cmp r[11],r[10] -- jnz r[19]
0x182: jmp r[20] // jmp r20 函数返回
0x183: nop
0x184: mov r[0],0x6e
0x185: putchar(r[0)]
0x186: mov r[0],0x6f
0x187: putchar(r[0)]
0x188: jmp r[20]
0x189: nop
0x18a: mov r[0],0x79
0x18b: putchar(r[0)]

这个delta一出来,应该是个tea加密,key也有了,我们解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdint.h>
void decrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i<32; i++) { /* basic cycle start */
v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
sum -= delta;
} /* end cycle */
v[0]=v0; v[1]=v1;
}
int main()
{
uint32_t v[12] = {0xe8d1d5df, 0xf5e3c114, 0x228ec216, 0x89d45a61, 0x655b8f69, 0x2484a07a, 0xd9e5e7f8, 0x3a441532, 0x91ab7e88, 0x69fc64bc, 0x7d3765, 0x00};
uint32_t k[4] = {0x95c4c, 0x871d, 0x1a7b7, 0x12c7c7};
for (int i = 0; i < 5; ++i) {
decrypt(v+i*2, k);
}
printf("%s", (char*)v);
}

得到flag:VNCTF{ecd63ae5-8945-4ac4-b5a5-34fc3ade81e7}

从这道题,还学会了稍微恢复一下vm,即创造结构体。

1
if ( HIDWORD(a1) >= 0x15uLL )//我们能推测出寄存器个数

还可以推测栈的大小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct func
{
void *call;
vm *ptr;
};
struct REG
{
_DWORD R[21];
};
struct vm
{
REG reg;
_DWORD Memory[1000];
_DWORD rip;
_DWORD index;
void *data;
func *func[100];
_QWORD isExit;
};

从而创建结构体,然后更好的分析。

未完待续

wasm

WebAssembly是一种全新的Web编程语言,但是与JavaScript不同,它不是一种让你直接手动编写的语言,而是C / C ++,Rust,C#和TypeScript等不断增加的上层语言的编译目标。

wasm是基于堆栈的虚拟机的二进制指令格式

  • wat2wasm:从WebAssembly文本格式转换为 WebAssembly二进制格式
  • wasm2watwat2wasm的逆函数,从二进制格式转换回文本格式(也称为.wat)
  • wasm-objdump:显示有关wasm二进制文件的信息。与objdump类似。
  • wasm-interp:使用基于堆栈的解释器解码并运行WebAssembly二进制文件
  • wasm-decompile:将wasm二进制文件反编译为可读的类似C的语法。
  • wat- desugar:解析规范解释程序支持的.wat文本格式(S表达式,平面语法或混合格式)并打印“规范”平面格式
  • wasm2c:将WebAssembly二进制文件转换为C源代码和标头
  • wasm-strip:删除WebAssembly二进制文件的部分
  • wasm-validate:验证WebAssembly二进制格式的文件
  • wast2json:将wasm spec测试格式的文件转换为JSON文件和关联的wasm二进制文件
  • wasm-opcodecnt:计算指令的操作码使用量
  • spectest-interp:读取Spectest JSON文件,然后在解释器中运行其测

这种类型的题,主要是看处理阶段比较难办,分为两种方法

第一种就是静态分析

我们需要先下载wabt包,然后make一下,之后再进行对wasm文件的反编译

1
wasm2c xorwasm.wasm -o xorwasm.c

然后得到还原的c文件和h头文件,之后将wasm-rt.h和wasm-rt-impl.h头⽂件移动到我们反编译出来的.c和.h⽂件夹下,采用gcc编译

1
gcc -c xorwasm.c -o xorwasm.o

得到的文件虽然不能执行,但可以静态分析。

第二种是动态分析

如果给了html文件,我们可以在google中直接调试,我们先在终端中起个指令:

1
python -m http.server -b localhost

然后就能分析了,打开网址,f12中的source,可以下断点

下完断点就刷新,发现断在了下断点的地方,然后进行调试:F8执⾏(等价于IDA的F9),F10单步步过,F11单步步⼊ ,右侧还有stack中有memory可以看。

OLLVM

控制流平坦化

如果不把ollvm给恢复,那么就很麻烦了,这个ollvm浅层的理解就是将几个跳转转换成很多switch,再搞很多分支,这样就显得很麻烦看起来,我们一般先对这些进行去除控制流平坦化,我们采用deplat.py文件进行去除,这个python文件运行是基于angr环境的。

操作:

先将文件放在deflat-master/flat_control_flow目录下,然后更改deplat文件的第十二行,换成文件路径。

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
#!/usr/bin/env python3

import sys
sys.path.append("..")

import argparse
import angr
import pyvex
import claripy
import struct
from collections import defaultdict
sys.path.append('./normal12')//此处要更改
import am_graph
from util import *

import logging
logging.getLogger('angr.state_plugins.symbolic_memory').setLevel(logging.ERROR)
# logging.getLogger('angr.sim_manager').setLevel(logging.DEBUG)


def get_relevant_nop_nodes(supergraph, pre_dispatcher_node, prologue_node, retn_node):
# relevant_nodes = list(supergraph.predecessors(pre_dispatcher_node))
relevant_nodes = []
nop_nodes = []
for node in supergraph.nodes():
if supergraph.has_edge(node, pre_dispatcher_node) and node.size > 8:
# XXX: use node.size is faster than to create a block
relevant_nodes.append(node)
continue

进入ida找到main函数起始位置。

1
python deflat.py -f normal12 --addr 0x401040

使用上面命令,如果终端中出现success就行了,得到的文件很美妙!

socket

第一次减这样类型的题,而且这道题还很复杂。

给了两个文件,一个login一个check,很烦,先看login

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
void __fastcall __noreturn sub_401DB1(int a1, _QWORD *a2, __int64 a3, __int64 a4, int a5, int a6)
{
int v6; // edx
int v7; // ecx
int v8; // er8
int v9; // er9
__int64 v10; // rax
__int64 v11; // rax
char v12; // [rsp+0h] [rbp-810h]
unsigned int clientfd; // [rsp+10h] [rbp-800h]
int v14; // [rsp+14h] [rbp-7FCh]
__int64 v15; // [rsp+18h] [rbp-7F8h]
_QWORD server_addr[2]; // [rsp+20h] [rbp-7F0h] BYREF
__int64 v17[126]; // [rsp+30h] [rbp-7E0h] BYREF
u32 uaddr2[2]; // [rsp+420h] [rbp-3F0h] BYREF
__int64 v19; // [rsp+428h] [rbp-3E8h]
char v20[984]; // [rsp+430h] [rbp-3E0h] BYREF
unsigned __int64 v21; // [rsp+808h] [rbp-8h]

v12 = (char)a2;
v21 = __readfsqword(0x28u);
memset(v17, 0, 1000);
*(_QWORD *)uaddr2 = 0LL;
v19 = 0LL;
memset(v20, 0, sizeof(v20));
if ( a1 != 2 )
{
printf((unsigned int)"Usage: %s <IP Address>\n", *a2, (unsigned int)v20, 0, a5, a6, (char)a2);
sub_410400(1LL);
}
v15 = sub_454A70(a2[1], a2, v20);
if ( !v15 )
sub_410400(1LL);
clientfd = socket(2LL, 1LL, 0LL);
if ( clientfd == -1 )
sub_410400(1LL);
server_addr[0] = 2LL;
server_addr[1] = 0LL;
*(_DWORD *)((char *)server_addr + 2) = (unsigned __int16)sub_454A60((unsigned __int16)dword_4DA120);// 端口1234
HIDWORD(server_addr[0]) = ***(_DWORD ***)(v15 + 24);// ip
if ( (unsigned int)connect(clientfd, server_addr, 16LL) == -1 )// connect请求
sub_410400(1LL);
while ( 1 )
{
v14 = sub_454550(clientfd, v17, 1000LL, 0LL);
if ( v14 < 0 )
break;
*((_BYTE *)v17 + v14) = 0;
printf((unsigned int)"%s", (unsigned int)v17 + 1, v6, v7, v8, v9, v12);
if ( LOBYTE(v17[0]) == '0' )
{
sub_450F60(clientfd); // 退出
sub_410400(0LL);
}
if ( LOBYTE(v17[0]) == '2' )
{
v10 = sub_4011B0(a52096ad53036a5);
send(clientfd, a52096ad53036a5, v10, 0LL);// 发送过去hex字符串
}
scanf(uaddr2); // 输入
v11 = sub_4011B0(uaddr2);
send(clientfd, uaddr2, v11, 0LL); // 发送输入
}
sub_410400(1LL);
}

这是一个socket发送字符串的程序

socket编程是一门技术,它主要是在网络通信中经常用到,我的理解是用户在tcp/ip的基础上通过socket进行信息交互

image-20220329202342794

一般socket使用时先传送端口再传送ip,在发送connect请求

1
2
3
int socket(int domain, int type, int protocol);
int listen(int sockfd, int backlog);
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

connect函数反编译后:

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
unsigned __int64 __fastcall connect(int a1, struct sockaddr *a2, int a3)
{
unsigned __int64 result; // rax
unsigned __int64 v4; // rax
unsigned int v5; // er8
unsigned int fd; // [rsp+8h] [rbp-10h]

if ( __readfsdword(0x18u) )
{
sub_47CDF0();
v4 = sys_connect(a1, a2, a3);
if ( v4 > 0xFFFFFFFFFFFFF000LL )
{
__writefsdword(0xFFFFFFB0, -(int)v4);
LODWORD(v4) = -1;
}
fd = v4;
sub_47CE50(v5);
return fd;
}
else
{
result = sys_connect(a1, a2, a3);
if ( result > 0xFFFFFFFFFFFFF000LL )
{
__writefsdword(0xFFFFFFB0, -(int)result);
return 0xFFFFFFFFLL;
}
}
return result;
}

限定了我们第一个发过去的必须是2,如果不是就退出,我们查看发送的东西

image-20220329202855655

这个0x52很明显是aes的INV_SBOX,这个还是能看出来的。

看完login再看server的check

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
__int64 sub_405DA7()
{
int v0; // edx
int v1; // ecx
int v2; // er8
int v3; // er9
__int64 result; // rax
int v5; // [rsp+Ch] [rbp-44h] BYREF
int v6; // [rsp+10h] [rbp-40h] BYREF
unsigned int listenfd; // [rsp+14h] [rbp-3Ch]
unsigned int v8; // [rsp+18h] [rbp-38h]
int v9; // [rsp+1Ch] [rbp-34h]
_QWORD v10[2]; // [rsp+20h] [rbp-30h] BYREF
struct sockaddr clientaddr; // [rsp+30h] [rbp-20h] BYREF
unsigned __int64 v12; // [rsp+48h] [rbp-8h]

v12 = __readfsqword(0x28u);
listenfd = sub_55C220(2LL, 1LL, 0LL);
if ( listenfd == -1 )
exit(1);
v6 = 2;
sub_55C1F0(listenfd, 1LL, 2LL, &v6, 4LL);
v10[0] = 2LL;
v10[1] = 0LL;
WORD1(v10[0]) = sub_55CCC0((unsigned __int16)dword_609150);// 端口1234
HIDWORD(v10[0]) = sub_55CCB0(0LL);
if ( (unsigned int)sub_55C010(listenfd, v10, 16LL) == -1 )
exit(1);
if ( (unsigned int)sub_55C040(listenfd, 100LL) == -1 )
exit(1);
sub_4FDD90("\n----------------Welcome----------------");
v5 = 16;
while ( 1 )
{
v8 = accept(listenfd, &clientaddr, &v5);
if ( !v8 )
break;
if ( v8 == -1 )
exit(1);
v9 = fork(); // 创建子进程来处理接收到的内容
if ( v9 <= 0 )
{
if ( !v9 )
{
sub_559590(0, (unsigned int)&clientaddr, v0, v1, v2, v3);// 函数看不懂
close(listenfd);
sub_405F6A(v8, *(_QWORD *)&clientaddr.sa_family, *(_QWORD *)&clientaddr.sa_data[6]);// 这个是重点
exit(0);
}
exit(0);
}
close(v8);
}
result = 0LL;
if ( __readfsqword(0x28u) != v12 )
sub_55CC60();
return result;
}

经典fork函数

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
__int64 fork()
{
unsigned int v0; // ebp
_BOOL4 v1; // er12
unsigned __int64 v2; // rax
__int64 v3; // r9
unsigned int v4; // er13
__int64 i; // rbp
_QWORD *v6; // rax

v0 = __readfsdword(0x18u);
v1 = v0 != 0;
sub_571900(0LL, v0 != 0);
if ( v0 )
{
sub_507EF0();
if ( sub_50D8B0 )
sub_50D8B0();
}
v2 = sys_clone(0x1200011uLL, 0LL, 0LL, (void *)(__readfsqword(0x10u) + 720));
if ( v2 > 0xFFFFFFFFFFFFF000LL )
{
v4 = -1;
__writefsdword(0xFFFFFFC0, -(int)v2);
}
else
{
v4 = v2;
if ( !(_DWORD)v2 )
{
if ( qword_610A40 )
*(_QWORD *)qword_610A40 += 4LL;
*(__m128i *)(v3 + 728) = _mm_unpacklo_epi64(
(__m128i)(unsigned __int64)(v3 + 736),
(__m128i)(unsigned __int64)(v3 + 736));
if ( v0 )
{
if ( sub_50DA20 )
sub_50DA20();
for ( i = sub_507EB0(); i != sub_507EC0(); i = sub_507ED0(i) )
{
if ( (BYTE1(*(_DWORD *)sub_507EE0(i)) & 0x80u) == 0 )
{
v6 = *(_QWORD **)(sub_507EE0(i) + 136);
*v6 = 0LL;
v6[1] = 0LL;
}
}
sub_507FB0();
}
qword_60A660 = 0LL;
xmmword_60A650 = 0LL;
xmmword_60A640 = 0LL;
LODWORD(xmmword_60A650) = 1;
sub_571900(1LL, v1);
return v4;
}
}
if ( v0 )
{
if ( sub_50D960 )
sub_50D960();
sub_507F50();
}
sub_571900(2LL, v0 != 0);
return v4;
}

我们直接看主函数

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
unsigned __int64 __fastcall sub_405F6A(unsigned int connfd, __int64 a2, __int64 a3)
{
__int64 v3; // rax
__int64 *v4; // rsi
__int64 v5; // rax
__int64 v7; // rax
__int64 v8; // rax
unsigned __int64 result; // rax
int v12; // [rsp+28h] [rbp-898h]
int len; // [rsp+28h] [rbp-898h]
int lena; // [rsp+28h] [rbp-898h]
int v15; // [rsp+2Ch] [rbp-894h]
char token[32]; // [rsp+30h] [rbp-890h] BYREF
char psd[32]; // [rsp+50h] [rbp-870h] BYREF
char v18[48]; // [rsp+70h] [rbp-850h] BYREF
char v19[64]; // [rsp+A0h] [rbp-820h] BYREF
__int64 psd_1[126]; // [rsp+E0h] [rbp-7E0h] BYREF
__int64 token_1[125]; // [rsp+4D0h] [rbp-3F0h] BYREF
unsigned __int64 v22; // [rsp+8B8h] [rbp-8h]

v22 = __readfsqword(0x28u);
memset(psd_1, 0, 1000);
memset(token_1, 0, sizeof(token_1));
strcpy(token, "Please enter the token: "); // 输入token
strcpy(psd, "Please input the password: "); // 输入密码
strcpy(v19, "Login successful.\nNow, you can enter flag to verify: ");
strcpy(v18, "Forbidden, wrong token or password.\n");
send(connfd, "1", 1uLL, 0);
v3 = sub_401118((__int64)token);
send(connfd, token, v3, 0);
v4 = token_1;
v12 = sub_55C070(connfd, token_1, 1000LL, 0LL);// 接收token,应该是长度
if ( v12 >= 0 )
{
*((_BYTE *)token_1 + v12) = 0;
send(connfd, "1", 1uLL, 0);
v5 = sub_401118((__int64)psd);
send(connfd, psd, v5, 0);
v4 = psd_1;
len = sub_55C070(connfd, psd_1, 1000LL, 0LL);// 接受psd的
if ( len >= 0 )
{
*((_BYTE *)psd_1 + len) = 0;
if ( rsa((__int64)token_1) && (unsigned int)pswcheck((__int64)psd_1) )// psdcheck
{
send(connfd, "2", 1uLL, 0);
v7 = sub_401118((__int64)v19);
send(connfd, v19, v7, 0);
v4 = (__int64 *)INV_SBOX;
lena = sub_55C070(connfd, INV_SBOX, 1000LL, 0LL);// 接受发送过来的INV_SBOX
if ( lena >= 0 )
{
INV_SBOX[lena] = 0;
sub_4058DB((__int64)INV_SBOX); // hex字符串转换成值
v15 = fork();
if ( v15 <= 0 )
{
if ( !v15 )
{
check(connfd, a2, a3, token_1, psd_1);
exit(0);
}
exit(0);
}
close(connfd);
}
}
else
{
send(connfd, "0", 1uLL, 0);
v8 = sub_401118((__int64)v18);
v4 = (__int64 *)v18;
send(connfd, v18, v8, 0);
}
}
}
close(connfd);
result = __readfsqword(0x28u) ^ v22;
if ( result )
sub_55CC60(connfd, v4);
return result;
}

sub_55C070传入的三个参数分别是connfd,客户端的ip和端口,要输入两个东西,要进行三个函数的逆向

第一个checkrsa:

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
_BOOL8 __fastcall sub_405A10(__int64 a1)
{
__int64 v1; // rax
_BOOL8 result; // rax
char v3[16]; // [rsp+10h] [rbp-310h] BYREF
char v4[16]; // [rsp+20h] [rbp-300h] BYREF
char v5[16]; // [rsp+30h] [rbp-2F0h] BYREF
char v6[26]; // [rsp+40h] [rbp-2E0h] BYREF
char v7[70]; // [rsp+5Ah] [rbp-2C6h] BYREF
char v8[632]; // [rsp+A0h] [rbp-280h] BYREF
unsigned __int64 v9; // [rsp+318h] [rbp-8h]

v9 = __readfsqword(0x28u);
strcpy(
v8,
"13123058934861171416713230498081453101147538789122070079961388806126697916963123413431108069961369055630747412550900"
"23940271082784791796087035865396294828238135174112188452839936976453044650993624026229024830522655211710058472661625"
"52929639711415105186785526790332203152463777462705158539879031845129488013974521045545898037256190760663399689993089"
"10127885089547678968793196148780382182445270838659078189316664538631875879022325427220682805580410213245364855569367"
"70291915788136708567728312473287462156937990127266216202578060866957754654833327476605875578644949127700234991859897"
"1841605936268030140638579388226573929");
strcpy(&v7[6], "By reading we enrich the mind, by conversation we polish it.");
strcpy(v7, "10001"); // e的值
sub_406990(v3, v8, 10LL);
v1 = sub_4057A9(&v7[6]);
sub_406990(v4, v1, 16LL);
sub_406990(v5, v7, 16LL);
sub_406990(v6, a1, 10LL);
sub_4069B0(v6, v6, v5, v3);
result = (unsigned int)sub_406910(v6, v4) == 0;
if ( __readfsqword(0x28u) != v9 )
sub_55CC60();
return result;
}

这里要注意,m转换成16进制要是小端序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from gmpy2 import*
from libnum import*
from Crypto.Util.number import long_to_bytes
import gmpy2
e=0x10001
p=98197216341757567488149177586991336976901080454854408243068885480633972200382596026756300968618883148721598031574296054706280190113587145906781375704611841087782526897314537785060868780928063942914187241017272444601926795083433477673935377466676026146695321415853502288291409333200661670651818749836420808033
q=133639826298015917901017908376475546339925646165363264658181838203059432536492968144231040597990919971381628901127402671873954769629458944972912180415794436700950304720548263026421362847590283353425105178540468631051824814390421486132775876582962969734956410033443729557703719598998956317920674659744121941513
n=p*q
m=0x2e7469206873696c6f70206577206e6f697461737265766e6f63207962202c646e696d2065687420686369726e6520657720676e6964616572207942
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
flag=pow(m,int(d),n)
print(flag)
#n=13123058934861171416713230498081453101147538789122070079961388806126697916963123413431108069961369055630747412550900239402710827847917960870358653962948282381351741121884528399369764530446509936240262290248305226552117100584726616255292963971141510518678552679033220315246377746270515853987903184512948801397452104554589803725619076066339968999308910127885089547678968793196148780382182445270838659078189316664538631875879022325427220682805580410213245364855569367702919157881367085677283124732874621569379901272662162025780608669577546548333274766058755786449491277002349918598971841605936268030140638579388226573929

第二个函数是一个矩阵:

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
__int64 __fastcall sub_405BDE(__int64 a1)
{
__int64 result; // rax
int i; // [rsp+10h] [rbp-80h]
int j; // [rsp+14h] [rbp-7Ch]
unsigned int v4; // [rsp+18h] [rbp-78h]
int k; // [rsp+1Ch] [rbp-74h]
__int64 v6[4]; // [rsp+20h] [rbp-70h]
int v7; // [rsp+40h] [rbp-50h]
__int64 v8; // [rsp+50h] [rbp-40h]
__int64 v9; // [rsp+58h] [rbp-38h]
__int64 v10; // [rsp+60h] [rbp-30h]
__int64 v11; // [rsp+68h] [rbp-28h]
int v12; // [rsp+70h] [rbp-20h]
unsigned __int64 v13; // [rsp+78h] [rbp-18h]

v13 = __readfsqword(0x28u);
v6[0] = 0xA34C0F7A2E25DB71LL;
v6[1] = 0x7AA91B6E29AA226ALL;
v6[2] = 0x56AA0EF0802F278ALL;
v6[3] = 0x9AF6F2A9005859F7LL;
v7 = -918021042;
v8 = 0xFCF1BE5355A297A3LL; // 这里的对比函数没有删除
v9 = 0xE2E91314526B79F9LL;
v10 = 0x275708561F8E512DLL;
v11 = 0x75778252D0D405A7LL;
v12 = -313878245;
sub_4058DB(a1);
for ( i = 0; i <= 5; ++i )
{
for ( j = 0; j <= 5; ++j )
{
v4 = 0;
for ( k = 0; k <= 5; ++k )
v4 += *((unsigned __int8 *)v6 + 6 * i + k) * *(unsigned __int8 *)(6 * k + j + a1);// 矩阵相乘
if ( v4 % 0x101 != (int)sub_4F1880() % 255 )
{
result = 0LL;
goto LABEL_13;
}
}
}
result = 1LL;
LABEL_13:
if ( __readfsqword(0x28u) != v13 )
sub_55CC60();
return result;
}

矩阵 * 我们要求的 == random() % 255,而这个random%255已经存在,听师傅说好像没删。
我们采用z3来搞:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from z3 import*
s = Solver()
flag = [Int('flag%d'%i) for i in range(36)]
g=0
arr2 = [0xA3, 0x97, 0xA2, 0x55, 0x53, 0xBE, 0xF1, 0xFC, 0xF9, 0x79, 0x6B, 0x52,0x14, 0x13, 0xE9, 0xE2, 0x2D, 0x51, 0x8E, 0x1F, 0x56, 0x08, 0x57, 0x27, 0xA7, 0x05, 0xD4, 0xD0, 0x52, 0x82,0x77, 0x75, 0x1B, 0x99, 0x4A, 0xED]
arr1 = [0x71, 0xDB, 0x25, 0x2E, 0x7A, 0x0F,0x4C, 0xA3, 0x6A, 0x22, 0xAA, 0x29, 0x6E, 0x1B, 0xA9, 0x7A, 0x8A, 0x27,0x2F, 0x80, 0xF0, 0x0E, 0xAA, 0x56,0xF7, 0x59, 0x58, 0x00, 0xA9, 0xF2, 0xF6, 0x9A, 0x4E, 0x1C, 0x48, 0xC9]
for i in range(6):
for j in range(6):
data = 0
for k in range(6):
data += arr1[i * 6 + k] * flag[6 * k + j]
s.add(data % 257 == arr2[g])
g += 1

if s.check() == sat: #检查机制,如果有解就输出,无解就错误
m = s.model()
res = []
for i in range(36):
res.append(chr(m[flag[i]].as_long()))
s=''.join(res)
print(s)
else:
print("nope")

或者采用syj师傅的sage脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
arr1 = [[0x71, 0xDB, 0x25, 0x2E, 0x7A, 0x0F], 
[0x4C, 0xA3, 0x6A, 0x22, 0xAA, 0x29],
[0x6E, 0x1B, 0xA9, 0x7A, 0x8A, 0x27],
[0x2F, 0x80, 0xF0, 0x0E, 0xAA, 0x56],
[0xF7, 0x59, 0x58, 0x00, 0xA9, 0xF2],
[0xF6, 0x9A, 0x4E, 0x1C, 0x48, 0xC9]]

dst = [[0xA3, 0x97, 0xA2, 0x55, 0x53, 0xBE],
[0xF1, 0xFC, 0xF9, 0x79, 0x6B, 0x52],
[0x14, 0x13, 0xE9, 0xE2, 0x2D, 0x51],
[0x8E, 0x1F, 0x56, 0x08, 0x57, 0x27],
[0xA7, 0x05, 0xD4, 0xD0, 0x52, 0x82],
[0x77, 0x75, 0x1B, 0x99, 0x4A, 0xED]]

arr1 = Matrix(Zmod(257), arr1)
dst = Matrix(Zmod(257), dst)
A = arr1.solve_right(dst)
print(A)

得到矩阵再转换成16进制5132d202c32d95b9f978d514e3294220513b15623482b4c02e9afde8bad5ec07486a5488

得到password

最后check分析,展示一下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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
unsigned __int64 __fastcall sub_4055C0(__int64 roundkeys, __int64 flag, __int64 a3, __int64 a4)
{
__int64 *v4; // rsi
int v5; // er8
int v6; // er9
unsigned __int64 result; // rax
int i; // [rsp+28h] [rbp-38h]
int j; // [rsp+28h] [rbp-38h]
int m; // [rsp+28h] [rbp-38h]
int k; // [rsp+2Ch] [rbp-34h]
__int64 v13[5]; // [rsp+30h] [rbp-30h] BYREF
unsigned __int64 v14; // [rsp+58h] [rbp-8h]
__int64 savedregs; // [rsp+60h] [rbp+0h] BYREF

v14 = __readfsqword(0x28u);
v13[0] = 0LL;
v13[1] = 0LL;
sub_404C1A(roundkeys, flag, a4); // flag的前16字节异或
sub_40554A(roundkeys, v13, flag); // 行列置换
sub_404F60(roundkeys, v13, roundkeys); // 轮密钥
for ( i = 1; ; ++i )
{
sub_404FF4(roundkeys, v13); // s盒字节代换
sub_405078(roundkeys, (__int64)v13); // 行移位
if ( i == 10 )
break;
sub_4053C8(roundkeys, v13); // 列混合
sub_404F60(roundkeys, v13, 16 * i + roundkeys);// 轮密钥加
}
v4 = v13;
sub_404F60(roundkeys, v13, roundkeys + 160);
for ( j = 0; j <= 3; ++j )
{
for ( k = 0; k <= 3; ++k )
*((_BYTE *)&savedregs + 4 * j + k - 32) = *((_BYTE *)&savedregs + 4 * k + j - 48);
}
for ( m = 0; m <= 15; ++m )
{
v4 = (__int64 *)"%02x";
roundkeys = a3 + 2 * m;
sub_4FC580(roundkeys, (unsigned int)"%02x", *((unsigned __int8 *)&v13[2] + m), roundkeys, v5, v6);
}
result = __readfsqword(0x28u) ^ v14;
if ( result )
sub_55CC60(roundkeys, v4);
return result;
}

这个第一次见还真不好搞出来是个aes

行列置换:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
__int64 __fastcall sub_40554A(__int64 a1, __int64 a2, __int64 a3)
{
__int64 result; // rax
int i; // [rsp+20h] [rbp-8h]
int j; // [rsp+24h] [rbp-4h]

for ( i = 0; i <= 3; ++i )
{
for ( j = 0; j <= 3; ++j )
{
result = i;
*(_BYTE *)(a2 + 4LL * j + i) = *(_BYTE *)(4 * i + j + a3);
}
}
return result;
}

轮密钥:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
__int64 __fastcall sub_404F60(__int64 a1, __int64 a2, __int64 a3)
{
__int64 result; // rax
int i; // [rsp+20h] [rbp-8h]
int j; // [rsp+24h] [rbp-4h]

for ( i = 0; i <= 3; ++i )
{
for ( j = 0; j <= 3; ++j )
{
result = j;
*(_BYTE *)(a2 + 4LL * i + j) ^= *(_BYTE *)(4 * j + i + a3);
}
}
return result;
}

行移位:

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
bool __fastcall sub_405078(__int64 a1, __int64 a2)
{
int v2; // eax
bool result; // al
int i; // [rsp+10h] [rbp-10h]
int j; // [rsp+14h] [rbp-Ch]
int v6; // [rsp+18h] [rbp-8h]
char v7; // [rsp+1Ch] [rbp-4h]

for ( i = 1; i <= 3; ++i )
{
v6 = 0;
while ( 1 )
{
v2 = v6++;
result = i > v2;
if ( !result )
break;
v7 = *(_BYTE *)(4LL * i + a2);
for ( j = 1; j <= 3; ++j )
*(_BYTE *)(a2 + 4LL * i + j - 1) = *(_BYTE *)(a2 + 4LL * i + j);
*(_BYTE *)(a2 + 4LL * i + j - 1) = v7;
}
}
return result;
}

S盒替换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
__int64 __fastcall sub_404FF4(__int64 a1, __int64 a2)
{
__int64 result; // rax
int i; // [rsp+18h] [rbp-8h]
int j; // [rsp+1Ch] [rbp-4h]

for ( i = 0; i <= 3; ++i )
{
for ( j = 0; j <= 3; ++j )
{
result = j;
*(_BYTE *)(a2 + 4LL * i + j) = INV_SBOX[*(unsigned __int8 *)(a2 + 4LL * i + j)];
}
}
return result;
}

列混合:

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
unsigned __int64 __fastcall sub_4053C8(__int64 a1, __int64 a2)
{
unsigned __int64 result; // rax
__int64 v3; // [rsp+0h] [rbp-40h]
__int64 v4; // [rsp+8h] [rbp-38h]
int i; // [rsp+14h] [rbp-2Ch]
int m; // [rsp+14h] [rbp-2Ch]
int j; // [rsp+18h] [rbp-28h]
int n; // [rsp+18h] [rbp-28h]
int k; // [rsp+1Ch] [rbp-24h]
__int64 v10; // [rsp+20h] [rbp-20h]
__int64 v11; // [rsp+28h] [rbp-18h]
unsigned __int64 v12; // [rsp+38h] [rbp-8h]
__int64 savedregs; // [rsp+40h] [rbp+0h] BYREF

v4 = a1;
v3 = a2;
v12 = __readfsqword(0x28u);
v10 = 0LL;
v11 = 0LL;
for ( i = 0; i <= 3; ++i )
{
for ( j = 0; j <= 3; ++j )
{
for ( k = 0; k <= 3; ++k )
{
a2 = *(unsigned __int8 *)(v3 + 4LL * k + j);
a1 = v4;
*((_BYTE *)&savedregs + 4 * i + j - 32) ^= sub_405158(v4, a2, byte_5A4030[4 * i + k]);
}
}
}
for ( m = 0; m <= 3; ++m )
{
for ( n = 0; n <= 3; ++n )
*(_BYTE *)(4LL * m + v3 + n) = *((_BYTE *)&savedregs + 4 * m + n - 32);
}
result = __readfsqword(0x28u) ^ v12;
if ( result )
sub_55CC60(a1, a2);
return result;
}

轮密钥加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
__int64 __fastcall sub_404F60(__int64 a1, __int64 a2, __int64 a3)
{
__int64 result; // rax
int i; // [rsp+20h] [rbp-8h]
int j; // [rsp+24h] [rbp-4h]

for ( i = 0; i <= 3; ++i )
{
for ( j = 0; j <= 3; ++j )
{
result = j;
*(_BYTE *)(a2 + 4LL * i + j) ^= *(_BYTE *)(4 * j + i + a3);
}
}
return result;
}

给出aes(256)解密脚本:

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
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

#define AES_BLOCK_SIZE 16
#define AES_ROUNDS 10 // 12, 14
#define AES_ROUND_KEY_SIZE 176 // AES-128 has 10 rounds, and there is a AddRoundKey before first round. (10+1)x16=176.

/*
* round constants
*/
static uint8_t RC[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};

/*
* Sbox
*/
static uint8_t SBOX[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};

/*
* Inverse Sboxs
*/
static uint8_t INV_SBOX[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d};

void output_mem16(uint8_t* data)
{
int i;
for (i = 0; i < 16; ++i )
{
printf("%x ", *(data+i));
}
printf("\n");
}

static inline uint8_t mul2(uint8_t a)
{
return (a&0x80) ? ((a<<1)^0x1b) : (a<<1);
}

/*
0 1 2 3 《0
4 5 6 7 《1
8 9 10 11 《2
12 13 14 15 《3
*/
static void shift_rows(uint8_t *state) {
uint8_t temp;
// row1: 下标为1的行左移1
temp = *(state+4);
*(state+4) = *(state+5);
*(state+5) = *(state+6);
*(state+6) = *(state+7);
*(state+7) = temp;
// row2: 下标为2的行左移2
temp = *(state+8);
*(state+8) = *(state+10);
*(state+10) = temp;
temp = *(state+9);
*(state+9) = *(state+11);
*(state+11) = temp;
// row3: 下标为3的行左移3
temp = *(state+15);
*(state+15) = *(state+14);
*(state+14) = *(state+13);
*(state+13) = *(state+12);
*(state+12) = temp;
}

void aes_key_schedule_128(const uint8_t *key, uint8_t *roundkeys) {

uint8_t temp[4];
uint8_t *last4bytes; // point to the last 4 bytes of one round
uint8_t *lastround;
uint8_t i;

for (i = 0; i < 16; ++i) {
*roundkeys++ = *key++;
}

last4bytes = roundkeys-4;
for (i = 0; i < AES_ROUNDS; ++i) {
// k0-k3 for next round
temp[3] = SBOX[*last4bytes++];
temp[0] = SBOX[*last4bytes++];
temp[1] = SBOX[*last4bytes++];
temp[2] = SBOX[*last4bytes++];
temp[0] ^= RC[i];
lastround = roundkeys-16;
*roundkeys++ = temp[0] ^ *lastround++;
*roundkeys++ = temp[1] ^ *lastround++;
*roundkeys++ = temp[2] ^ *lastround++;
*roundkeys++ = temp[3] ^ *lastround++;
// k4-k7 for next round
*roundkeys++ = *last4bytes++ ^ *lastround++;
*roundkeys++ = *last4bytes++ ^ *lastround++;
*roundkeys++ = *last4bytes++ ^ *lastround++;
*roundkeys++ = *last4bytes++ ^ *lastround++;
// k8-k11 for next round
*roundkeys++ = *last4bytes++ ^ *lastround++;
*roundkeys++ = *last4bytes++ ^ *lastround++;
*roundkeys++ = *last4bytes++ ^ *lastround++;
*roundkeys++ = *last4bytes++ ^ *lastround++;
// k12-k15 for next round
*roundkeys++ = *last4bytes++ ^ *lastround++;
*roundkeys++ = *last4bytes++ ^ *lastround++;
*roundkeys++ = *last4bytes++ ^ *lastround++;
*roundkeys++ = *last4bytes++ ^ *lastround++;
}
}

/**
* 列混合要用到的矩阵
*/
static const int colM[4][4] = { {2, 3, 1, 1},{1, 2, 3, 1},{1, 1, 2, 3},{3, 1, 1, 2 }};

static int GFMul2(int s) {
int result = s << 1;
int a7 = result & 0x00000100;

if(a7 != 0) {
result = result & 0x000000ff;
result = result ^ 0x1b;
}

return result;
}

static int GFMul3(int s) {
return GFMul2(s) ^ s;
}

static int GFMul4(int s) {
return GFMul2(GFMul2(s));
}

static int GFMul8(int s) {
return GFMul2(GFMul4(s));
}

static int GFMul9(int s) {
return GFMul8(s) ^ s;
}

static int GFMul11(int s) {
return GFMul9(s) ^ GFMul2(s);
}

static int GFMul12(int s) {
return GFMul8(s) ^ GFMul4(s);
}

static int GFMul13(int s) {
return GFMul12(s) ^ s;
}

static int GFMul14(int s) {
return GFMul12(s) ^ GFMul2(s);
}

/**
* GF上的二元运算
*/
static int GFMul(int n, int s) {
int result;

if(n == 1)
result = s;
else if(n == 2)
result = GFMul2(s);
else if(n == 3)
result = GFMul3(s);
else if(n == 0x9)
result = GFMul9(s);
else if(n == 0xb)//11
result = GFMul11(s);
else if(n == 0xd)//13
result = GFMul13(s);
else if(n == 0xe)//14
result = GFMul14(s);

return result;
}

void mixColumns(uint8_t array[4][4]) {

uint8_t tempArray[4][4];

for(int i = 0; i < 4; i++)
for(int j = 0; j < 4; j++)
tempArray[i][j] = array[i][j];

for(int i = 0; i < 4; i++)
for(int j = 0; j < 4; j++){
array[i][j] = GFMul(colM[i][0],tempArray[0][j]) ^ GFMul(colM[i][1],tempArray[1][j])
^ GFMul(colM[i][2],tempArray[2][j]) ^ GFMul(colM[i][3], tempArray[3][j]);
}
}

void aes_encrypt_128(const uint8_t *roundkeys, uint8_t *plaintext, uint8_t *ciphertext, uint8_t*iv)
{

uint8_t tmp[16];
uint8_t i, j, m, n;

//output_mem16(plaintext);
//和iv的16字节先进行异或
for ( i = 0; i < AES_BLOCK_SIZE; ++i )
{
*(plaintext+i) = *(plaintext+i) ^ *iv++;
}
//output_mem16(plaintext);

//矩阵转置
for ( i = 0; i <= 3; ++i )
{
for ( j = 0; j <= 3; ++j )
{
tmp[4 * j + i] = plaintext[4 * i + j];
}
}
//output_mem16(tmp);

//first AddRoundKey
for ( i = 0; i <= 3; ++i )
{
for ( j = 0; j <= 3; ++j )
{
tmp[4 * i + j] ^= roundkeys[4 * j + i];
}
}
//output_mem16(tmp);

// 9 rounds
for (j = 1; j < AES_ROUNDS; ++j)
{

// SubBytes
for (i = 0; i < AES_BLOCK_SIZE; ++i) {
*(tmp+i) = INV_SBOX[*(tmp+i)];
}

//shift_rows
shift_rows(tmp);

//MixColumns
mixColumns(tmp);

// AddRoundKey
for ( m = 0; m <= 3; ++m )
{
for ( n = 0; n <= 3; ++n )
{
tmp[4 * m + n] ^= roundkeys[16*j + 4 * n + m];
}
}
}

// last round
//output_mem16(tmp);
for (i = 0; i < AES_BLOCK_SIZE; ++i) {
*(ciphertext+i) = INV_SBOX[*(tmp+i)];
}
//output_mem16(ciphertext);
shift_rows(ciphertext);
//output_mem16(ciphertext);
for ( m = 0; m <= 3; ++m )
{
for ( n = 0; n <= 3; ++n )
{
ciphertext[4 * m + n] ^= roundkeys[16*j + 4 * n + m];
}
}

//output_mem16(ciphertext);
for ( m = 0; m <= 3; ++m ) //转置
{
for ( n = 0; n <= 3; ++n )
{
tmp[4 * n + m] = ciphertext[4 * m + n];
}
}

for ( i = 0; i < 16; ++i )
{
ciphertext[i] = tmp[i];
}
//output_mem16(ciphertext);
}

/**
* 逆列混合用到的矩阵
*/
static const int deColM[4][4] = {{0xe, 0xb, 0xd, 0x9},{0x9, 0xe, 0xb, 0xd},{0xd, 0x9, 0xe, 0xb},{0xb, 0xd, 0x9, 0xe}};

/**
* 逆列混合
*/
void deMixColumns(uint8_t array[4][4]) {
uint8_t tempArray[4][4];

for(int i = 0; i < 4; i++)
for(int j = 0; j < 4; j++)
tempArray[i][j] = array[i][j];

for(int i = 0; i < 4; i++)
for(int j = 0; j < 4; j++){
array[i][j] = GFMul(deColM[i][0],tempArray[0][j]) ^ GFMul(deColM[i][1],tempArray[1][j])
^ GFMul(deColM[i][2],tempArray[2][j]) ^ GFMul(deColM[i][3], tempArray[3][j]);
}
}

/*
0 1 2 3
5 6 7 4 4 5 6 7
10 11 8 9 8 9 10 11
15 12 13 14 12 13 14 15
*/
static void inv_shift_rows(uint8_t *state) {
uint8_t temp;
// row1
temp = *(state+4);
*(state+4) = *(state+7);
*(state+7) = *(state+6);
*(state+6) = *(state+5);
*(state+5) = temp;
// row2
temp = *(state+10);
*(state+10) = *(state+8);
*(state+8) = temp;
temp = *(state+11);
*(state+11) = *(state+9);
*(state+9) = temp;
// row3
temp = *(state+12);
*(state+12) = *(state+13);
*(state+13) = *(state+14);
*(state+14) = *(state+15);
*(state+15) = temp;
}

void aes_decrypt_128(const uint8_t *roundkeys, const uint8_t *ciphertext, uint8_t *plaintext, uint8_t*iv)
{

uint8_t tmp[16];
uint8_t t, u, v, m, n;
uint8_t i, j;

for ( m = 0; m <= 3; ++m ) //转置
{
for ( n = 0; n <= 3; ++n )
{
tmp[4 * n + m] = ciphertext[4 * m + n];
}
}
for ( m = 0; m <= 3; ++m )
{
for ( n = 0; n <= 3; ++n )
{
tmp[4 * m + n] ^= roundkeys[160 + 4 * n + m];
}
}
inv_shift_rows(tmp);
for (i = 0; i < AES_BLOCK_SIZE; ++i) {
*(plaintext+i) = SBOX[*(tmp+i)];
}

for (j = 9; j > 0; --j) {
// Inverse AddRoundKey
for ( m = 0; m <= 3; ++m )
{
for ( n = 0; n <= 3; ++n )
{
plaintext[4 * m + n] ^= roundkeys[16*j + 4 * n + m];
}
}
deMixColumns(plaintext);

// Inverse ShiftRows
inv_shift_rows(plaintext);

// Inverse SubBytes
for (i = 0; i < AES_BLOCK_SIZE; ++i) {
*(plaintext+i) = SBOX[*(plaintext+i)];
}
}

// last AddRoundKey
for ( i = 0; i <= 3; ++i )
{
for ( j = 0; j <= 3; ++j )
{
plaintext[4 * i + j] ^= roundkeys[4 * j + i];
}
}
for ( i = 0; i <= 3; ++i )
{
for ( j = 0; j <= 3; ++j )
{
tmp[4 * j + i] = plaintext[4 * i + j];
}
}
for ( i = 0; i < AES_BLOCK_SIZE; ++i )
{
*(plaintext+i) = *(tmp+i) ^ *iv++;
}
//output_mem16(plaintext);
}

int main(int argc, char *argv[])
{

uint8_t i, r;

uint8_t key[] =
{
50, 48, 7, 54, 106, 55, 120, 49, 72, 57, 66, 57, 20, 49, 213, 50
};
uint8_t iv1[16] = {98, 54, 249, 56, 66, 48, 195, 49, 106, 53, 72, 56, 52, 53, 84, 52};
uint8_t iv2[16] = {41, 52, 81, 54, 21, 57, 210, 56, 210, 57, 32, 49, 185, 50, 46, 48};
//uint8_t plaintext[] = {0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, 0x37, 0x37};//加密
uint8_t ciphertext1[AES_BLOCK_SIZE] = {254, 249, 231, 62, 246, 161, 35, 204, 87, 97, 193, 21, 119, 251, 156, 187};
uint8_t ciphertext2[AES_BLOCK_SIZE] = {202, 47, 177, 232, 79, 217, 7, 216, 12, 107, 234, 207, 232, 66, 162, 250};
uint8_t dec_data[AES_BLOCK_SIZE];
uint8_t roundkeys[AES_ROUND_KEY_SIZE];

// key schedule
aes_key_schedule_128(key, roundkeys);
printf("Round Keys:\n");
for ( r = 0; r <= AES_ROUNDS; r++ )
{
for (i = 0; i < AES_BLOCK_SIZE; i++) {
printf("%2x ", roundkeys[r*AES_BLOCK_SIZE+i]);
}
printf("\n");
}
printf("\n");

/*
//测试加密
aes_encrypt_128(roundkeys, plaintext, ciphertext, iv);
printf("Cipher data:\n");
for (i = 0; i < AES_BLOCK_SIZE; i++)
{
printf("%2x ", ciphertext[i]);
}
putchar(10);
*/

aes_decrypt_128(roundkeys, ciphertext1, dec_data, iv1);
printf("Decrypt data:\n");
for (i = 0; i < AES_BLOCK_SIZE; i++)
{
printf("%c", dec_data[i]);
}
aes_decrypt_128(roundkeys, ciphertext2, dec_data, iv2);
for (i = 0; i < AES_BLOCK_SIZE; i++)
{
printf("%c", dec_data[i]);
}
return 0;
}

得到:7026271d7bb5d404d63a72b88e6b4d63