尝试对虚拟机保护有更深的理解。

由于之前做vm题感觉完全不会,所以找了几道题试一试

由之前的vm简要介绍看到vm题总是给出opcode的运行方式,然后通过opcode还原出运行逻辑,最后求出flag

EzADVM

这个是个安卓vm,jadx打开,然后打开main_activity,

1
2
3
4
5
6
7
8
9
public void CheckClick(View a) {
TextView tv = this.binding.sampleText;
EditText flagText = this.binding.flagtext;
String flagstring = flagText.getText().toString();
if ("Right!".equals(stringFromJNI(flagstring))) {
tv.setText("Right!");
tv.setTextColor(-16711936);
return;
}

看到有stringFromJNI(flagstring),去找函数原型,没找到,应该在库里。

用apktool反编译出源代码。打开so文件

重点是这些:

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
now_num = 0;
i = 1;
used_char = _JNIEnv::GetStringUTFChars(in, a3, 0LL);
while ( 1 )
{
while ( 1 )
{
if ( !i++ )
{
LABEL_29:
std::string::basic_string<decltype(nullptr)>(v14, "Error!");
v7 = (const char *)sub_20F50(v14);
v13 = _JNIEnv::NewStringUTF(in, v7);
std::string::~string(v14);
return v13;
}
if ( code[i] != 0x21 )
break;
__strcpy_chk(input, used_char, 1024LL);
}
if ( code[i] == 0xFF )
goto LABEL_29;
if ( code[i] == 0x88 )
break;
switch ( code[i] )
{
case 0xA1u:
s[now_num - 1] = or_not_num & or_num;
break;
case 0xC3u:
or_num = b1 | b2;
break;
case 0xB2u:
not_1 = ~b1;
break;
case 0xE5u:
not_2 = ~b2;
break;
case 0xF1u:
b1 = input[now_num];
b2 = input[++now_num];
break;
case 0xD4u:
or_not_num = not_2 | not_1;
break;
case 0xBFu:
i_form = now_num++;
save[0] = s[i_form];
break;
case 0x99u:
now_num = 0;
break;
case 0xBBu:
s[now_num - 1] = now_num + save[0] - 1;
break;
}
}
if ( !memcmp(&last, s, 0x20uLL) )

输入用来初始化input了,所以相当于是用指令码对input加密,最后得到last

以及一开始有一个循环只有当code[i]==0先1时才会执行初始化,所以只需要匹配合理的指令即可

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
opcode = [0x01, 0x01, 0x21, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 
0xA1, 0x53, 0x57, 0x44, 0x61, 0x44, 0x64, 0xF1,
0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2,
0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4,
0xA1, 0x53, 0x57, 0x44, 0x61, 0x44, 0x64, 0xF1,
0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2,
0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4,
0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1,
0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x53, 0x57, 0x44,
0x61, 0x44, 0x64, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4,
0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1,
0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x53, 0x57, 0x44,
0x61, 0x44, 0x64, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4,
0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1,
0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x66, 0x6C, 0x61,
0x67, 0x7B, 0x59, 0x75, 0x69, 0x73, 0x61, 0x62,
0x65, 0x61, 0x75, 0x74, 0x69, 0x66, 0x75, 0x6C,
0x67, 0x69, 0x72, 0x6C, 0x7D, 0xF1, 0xC3, 0xB2,
0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4,
0xA1, 0x66, 0x6C, 0x61, 0x67, 0x7B, 0x59, 0x75,
0x69, 0x73, 0x61, 0x62, 0x65, 0x61, 0x75, 0x74,
0x69, 0x66, 0x75, 0x6C, 0x67, 0x69, 0x72, 0x6C,
0x7D, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1,
0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x66, 0x6C, 0x61,
0x67, 0x7B, 0x59, 0x75, 0x69, 0x73, 0x61, 0x62,
0x65, 0x61, 0x75, 0x74, 0x69, 0x66, 0x75, 0x6C,
0x67, 0x69, 0x72, 0x6C, 0x7D, 0xF1, 0xC3, 0xB2,
0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4,
0xA1, 0x53, 0x57, 0x44, 0x61, 0x44, 0x64, 0x66,
0x6C, 0x61, 0x67, 0x7B, 0x59, 0x75, 0x69, 0x73,
0x61, 0x62, 0x65, 0x61, 0x75, 0x74, 0x69, 0x66,
0x75, 0x6C, 0x67, 0x69, 0x72, 0x6C, 0x7D, 0xF1,
0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2,
0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4,
0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x53,
0x57, 0x44, 0x61, 0x44, 0x64, 0x66, 0x6C, 0x61,
0x67, 0x7B, 0x59, 0x75, 0x69, 0x73, 0x61, 0x62,
0x65, 0x61, 0x75, 0x74, 0x69, 0x66, 0x75, 0x6C,
0x67, 0x69, 0x72, 0x6C, 0x7D, 0xF1, 0xC3, 0xB2,
0xE5, 0xD4, 0xA1, 0x66, 0x6C, 0x61, 0x67, 0x7B,
0x59, 0x75, 0x69, 0x73, 0x61, 0x62, 0x65, 0x61,
0x75, 0x74, 0x69, 0x66, 0x75, 0x6C, 0x67, 0x69,
0x72, 0x6C, 0x7D, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4,
0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1,
0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2,
0xE5, 0xD4, 0xA1, 0xF1, 0xC3, 0xB2, 0xE5, 0xD4,
0xA1, 0x53, 0x57, 0x44, 0x61, 0x44, 0x64, 0xF1,
0xC3, 0xB2, 0xE5, 0xD4, 0xA1, 0x99, 0xBF, 0xBB,
0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB,
0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB,
0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB,
0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB,
0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0x66, 0x6C,
0x61, 0x67, 0x7B, 0x59, 0x75, 0x69, 0x73, 0x61,
0x62, 0x65, 0x61, 0x75, 0x74, 0x69, 0x66, 0x75,
0x6C, 0x67, 0x69, 0x72, 0x6C, 0x7D, 0xBF, 0xBB,
0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB,
0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB, 0xBF, 0xBB,
0xBF, 0xBB, 0x53, 0x57, 0x44, 0x44, 0xBF, 0xBB,
0xBF, 0xBB, 0x99, 0x53, 0x57, 0x44, 0x44, 0x53,
0x57, 0x44, 0x44, 0x88, 0xFF, 0x53, 0x57, 0x44,
0x44, 0x00, 0x00]
i = 0

for code in opcode:
match code:
case 0xa1:
print("last[now_num - 1] = or_not_num & or_num" )
case 0xc3:
print("or_num = b1 | b2")
case 0xb2:
print("not_1 = ~b1")
case 0xe5:
print("not_2 = ~b2")
case 0xf1:
print("b1 = input[now_num]")
print("now_num += 1")
print("b2 = input[now_num]")
case 0xd4:
print("or_not_num = not_2 | not_1")
case 0xbf:
print("save = last[now_num]")
print("now_num+=1")
case 0x99:
print("now_num = 0")
case 0xbb:
print("last[now_num-1] = now_num + save - 1")

大致是

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
last = [0]*100
now_num = 0

b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num
b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num

b1 = input[now_num]
now_num += 1
b2 = input[now_num]
or_num = b1 | b2
not_1 = ~b1
not_2 = ~b2
or_not_num = not_2 | not_1
last[now_num - 1] = or_not_num & or_num


now_num = 0


save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1

save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1

save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1

save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
save = last[now_num]
now_num+=1
last[now_num-1] = now_num + save - 1
now_num = 0

然后化简逆向:

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
from prism import *
last = [0x1D, 0x01, 0x12, 0x1A, 0x16, 0x42, 0x39, 0x0F,
0x38, 0x09, 0x13, 0x31, 0x28, 0x38, 0x67, 0x6E,
0x1B, 0x61, 0x7C, 0x24, 0x1F, 0x47, 0x44, 0x81,
0x6A, 0x2C, 0x6D, 0x2B, 0x2C, 0x2D, 0x6A, 0x9C]

# last = [0]*100
# now_num = 0
# for i in range(32):
# b1 = input[now_num]
# now_num += 1
# b2 = input[now_num]
# or_num = b1 | b2
# not_1 = ~b1
# not_2 = ~b2
# or_not_num = not_2 | not_1
# last[now_num - 1] = or_not_num & or_num

# now_num = 0

# for i in range(32):
# save = last[now_num]
# now_num+=1
# last[now_num-1] = now_num + save - 1



for i in range(31,0,-1):
last[i]-=i
for i in range(30,-1,-1):
last[i]^=last[i+1]

pl(last)
#NSSCTF{H@ppy_Ch1ne5_NEwY3ar!1!1}

小结:这个题和之前遇到的jvm那道题一样,都要解析指令,还原流程

羊城杯2021 babyvm

这个题一样,只是在前面加了一个动态调试

指令码大概是

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
void __cdecl sub_80487A8(_DWORD *reg)
{
_BYTE *v1; // [esp+18h] [ebp-20h]
int reg[999];
while ( 1 )
{
if ( *(_BYTE *)reg[8] == 113 )
{
reg[6] -= 4;
*(_DWORD *)reg[6] = *(_DWORD *)(reg[8] + 1);
reg[8] += 5;
}
if ( *(_BYTE *)reg[8] == 65 )
{
reg[1] += reg[2];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 66 )
{
reg[1] -= reg[4];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 67 )
{
reg[1] *= reg[3];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 55 )
{
reg[1] = reg[5];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 56 )
{
reg[1] ^= reg[4];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 57 )
{
reg[1] ^= reg[5];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 53 )
{
reg[5] = reg[1];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 0xF7 )
{
reg[9] += reg[1];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 68 )
{
reg[1] /= reg[5];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 0x80 )
{
reg[sub_804875F(reg, 1)] = *(_DWORD *)(reg[8] + 2);
reg[8] += 6;
}
if ( *(_BYTE *)reg[8] == 119 )
{
reg[1] ^= reg[9];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 83 )
{
putchar(*(char *)reg[3]);
reg[8] += 2;
}
if ( *(_BYTE *)reg[8] == 34 )
{
reg[1] >>= reg[2];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 35 )
{
reg[1] <<= reg[2];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 0x99 )
break;
if ( *(_BYTE *)reg[8] == 118 )
{
reg[3] = *(_DWORD *)reg[6];
*(_DWORD *)reg[6] = 0;
reg[6] += 4;
reg[8] += 5;
}
if ( *(_BYTE *)reg[8] == 84 )
{
v1 = (_BYTE *)reg[3];
*v1 = getchar();
reg[8] += 2;
}
if ( *(_BYTE *)reg[8] == 48 )
{
reg[1] |= reg[2];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 49 )
{
reg[1] &= reg[2];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 50 )
{
reg[3] = *(unsigned __int8 *)(reg[8] + 1);
reg[8] += 2;
}
if ( *(_BYTE *)reg[8] == 9 )
{
reg[1] = 1877735783;
++reg[8];
}
if ( *(_BYTE *)reg[8] == 16 )
{
reg[9] = reg[1];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 51 )
{
reg[4] = reg[1];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 52 )
{
reg[2] = *(unsigned __int8 *)(reg[8] + 1);
reg[8] += 2;
}
if ( *(_BYTE *)reg[8] == 0xFE )
{
reg[1] = reg[9];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 17 )
{
printf("%x\n", reg[1]);
++reg[8];
}
if ( *(_BYTE *)reg[8] == 0xA0 )
{
if ( reg[1] != 1877735783 )
exit(0);
++reg[8];
}
if ( *(_BYTE *)reg[8] == 0xA1 )
{
read(0, s, 0x2Cu);
if ( strlen(s) != 44 )
exit(0);
++reg[8];
}
if ( *(_BYTE *)reg[8] == 0xB1 )
{
reg[9] = fog[0];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 0xB2 )
{
reg[9] = fog[1];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 0xA4 )
{
fog[*(unsigned __int8 *)(reg[8] + 1)] = reg[1];
reg[8] += 4;
}
if ( *(_BYTE *)reg[8] == 0xB3 )
{
reg[9] = fog[2];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 0xB4 )
{
reg[9] = fog[3];
++reg[8];
}
if ( *(_BYTE *)reg[8] == 0xC1 )
{
reg[1] = (unsigned __int8)s[*(unsigned __int8 *)(reg[8] + 1)];
reg[8] += 2;
}
if ( *(_BYTE *)reg[8] == 0xC7 )
{
if ( exit_door[0] != reg[1] )
exit(0);
++reg[8];
}
if ( *(_BYTE *)reg[8] == 0xC8 )
{
if ( exit_door[1] != reg[1] )
exit(0);
++reg[8];
}
if ( *(_BYTE *)reg[8] == 0xC2 )
{
if ( (unsigned __int8)*(_DWORD *)(reg[8] + 1) != reg[1] )
exit(0);
reg[8] += 5;
}
}
}

然后转换写出来就好

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
flagafter = []
fog = [0x0000007B, 0x0000002F, 0x00000037, 0x000000E8]

exit_door = [0xCF1304DC, 0x283B8E84]


opcode = [0xA1, 0xC1, 0x00, 0xB1, 0x77, 0xC2, 0x4A, 0x01, 0x00, 0x00, 0xC1, 0x01, 0xB2, 0x77, 0xC2, 0x19, 0x01, 0x00, 0x00, 0xC1, 0x02, 0xB4, 0x77, 0xC2, 0xDD, 0x01, 0x00, 0x00, 0xC1, 0x03, 0xB3, 0x77, 0xC2, 0x0F, 0x01, 0x00, 0x00, 0xC1, 0x04, 0xB2, 0x77, 0xC2, 0x1B, 0x01, 0x00, 0x00, 0xC1, 0x05, 0xB4, 0x77, 0xC2, 0x89, 0x01, 0x00, 0x00, 0xC1, 0x06, 0xB1, 0x77, 0xC2, 0x19, 0x01, 0x00, 0x00, 0xC1, 0x07, 0xB3, 0x77, 0xC2, 0x54, 0x01, 0x00, 0x00, 0xC1, 0x08, 0xB1, 0x77, 0xC2, 0x4F, 0x01, 0x00, 0x00, 0xC1, 0x09, 0xB1, 0x77, 0xC2, 0x4E, 0x01, 0x00, 0x00, 0xC1, 0x0A, 0xB3, 0x77, 0xC2, 0x55, 0x01, 0x00, 0x00, 0xC1, 0x0B, 0xB3, 0x77, 0xC2, 0x56, 0x01, 0x00, 0x00, 0xC1, 0x0C, 0xB4, 0x77, 0xC2, 0x8E, 0x00, 0x00, 0x00, 0xC1, 0x0D, 0xB2, 0x77, 0xC2, 0x49, 0x00, 0x00, 0x00, 0xC1, 0x0E, 0xB3, 0x77, 0xC2, 0x0E, 0x01, 0x00, 0x00, 0xC1, 0x0F, 0xB1, 0x77, 0xC2, 0x4B, 0x01, 0x00, 0x00, 0xC1, 0x10, 0xB3, 0x77, 0xC2, 0x06, 0x01, 0x00, 0x00, 0xC1, 0x11, 0xB3, 0x77, 0xC2, 0x54, 0x01, 0x00, 0x00, 0xC1, 0x12, 0xB2, 0x77, 0xC2, 0x1A, 0x00, 0x00, 0x00, 0xC1, 0x13, 0xB1, 0x77, 0xC2, 0x42, 0x01, 0x00, 0x00, 0xC1, 0x14, 0xB3, 0x77, 0xC2, 0x53, 0x01, 0x00, 0x00, 0xC1, 0x15, 0xB1, 0x77, 0xC2, 0x1F, 0x01, 0x00, 0x00, 0xC1, 0x16, 0xB3, 0x77, 0xC2, 0x52, 0x01, 0x00, 0x00, 0xC1, 0x17, 0xB4, 0x77, 0xC2, 0xDB, 0x00, 0x00, 0x00, 0xC1, 0x18, 0xB1, 0x77, 0xC2, 0x19, 0x01, 0x00, 0x00, 0xC1, 0x19, 0xB4, 0x77, 0xC2, 0xD9, 0x00, 0x00, 0x00, 0xC1, 0x1A, 0xB1, 0x77, 0xC2, 0x19, 0x01, 0x00, 0x00, 0xC1, 0x1B, 0xB3, 0x77, 0xC2, 0x55, 0x01, 0x00, 0x00, 0xC1, 0x1C, 0xB2, 0x77, 0xC2, 0x19, 0x00, 0x00, 0x00, 0xC1, 0x1D, 0xB3, 0x77, 0xC2, 0x00, 0x01, 0x00, 0x00, 0xC1, 0x1E, 0xB1, 0x77, 0xC2, 0x4B, 0x01, 0x00, 0x00, 0xC1, 0x1F, 0xB2, 0x77, 0xC2, 0x1E, 0x00, 0x00, 0x00, 0xC1, 0x20, 0x80, 0x02, 0x18, 0x00, 0x00, 0x00, 0x23, 0x10, 0xC1, 0x21, 0x80, 0x02, 0x10, 0x00, 0x00, 0x00, 0x23, 0xF7, 0xC1, 0x22, 0x80, 0x02, 0x08, 0x00, 0x00, 0x00, 0x23, 0xF7, 0xC1, 0x23, 0xF7, 0xFE, 0x80, 0x02, 0x05, 0x00, 0x00, 0x00, 0x22, 0x77, 0x10, 0x80, 0x02, 0x07, 0x00, 0x00, 0x00, 0x23, 0x80, 0x02, 0x23, 0x77, 0xF1, 0x98, 0x31, 0x77, 0x10, 0x80, 0x02, 0x18, 0x00, 0x00, 0x00, 0x23, 0x80, 0x02, 0x20, 0xB9, 0xE4, 0x35, 0x31, 0x77, 0x10, 0x80, 0x02, 0x12, 0x00, 0x00, 0x00, 0x22, 0x77, 0xA0, 0xC1, 0x24, 0x80, 0x02, 0x18, 0x00, 0x00, 0x00, 0x23, 0x10, 0xC1, 0x25, 0x80, 0x02, 0x10, 0x00, 0x00, 0x00, 0x23, 0xF7, 0xC1, 0x26, 0x80, 0x02, 0x08, 0x00, 0x00, 0x00, 0x23, 0xF7, 0xC1, 0x27, 0xF7, 0xFE, 0x32, 0x20, 0x43, 0x33, 0x77, 0x80, 0x02, 0x11, 0x00, 0x00, 0x00, 0x22, 0x35, 0x37, 0x38, 0x77, 0x80, 0x02, 0x0D, 0x00, 0x00, 0x00, 0x23, 0x77, 0x38, 0x39, 0x10, 0x32, 0x20, 0x43, 0x33, 0x77, 0x80, 0x02, 0x11, 0x00, 0x00, 0x00, 0x22, 0x35, 0x37, 0x38, 0x77, 0x80, 0x02, 0x0D, 0x00, 0x00, 0x00, 0x23, 0x77, 0x38, 0x39, 0xC7, 0xC1, 0x28, 0x80, 0x02, 0x18, 0x00, 0x00, 0x00, 0x23, 0x10, 0xC1, 0x29, 0x80, 0x02, 0x10, 0x00, 0x00, 0x00, 0x23, 0xF7, 0xC1, 0x2A, 0x80, 0x02, 0x08, 0x00, 0x00, 0x00, 0x23, 0xF7, 0xC1, 0x2B, 0xF7, 0xFE, 0x32, 0x20, 0x43, 0x33, 0x77, 0x80, 0x02, 0x11, 0x00, 0x00, 0x00, 0x22, 0x35, 0x37, 0x38, 0x77, 0x80, 0x02, 0x0D, 0x00, 0x00, 0x00, 0x23, 0x77, 0x38, 0x39, 0x10, 0x32, 0x20, 0x43, 0x33, 0x77, 0x80, 0x02, 0x11, 0x00, 0x00, 0x00, 0x22, 0x35, 0x37, 0x38, 0x77, 0x80, 0x02, 0x0D, 0x00, 0x00, 0x00, 0x23, 0x77, 0x38, 0x39, 0xC8, 0x99]


def print_asm(reg):# 这里写成python语法方便爆破
now = 0
while True:
opcode = reg[now]
if opcode == 113:
print(f"push {reg[now+1]},{reg[now+2]},{reg[now+3]},{reg[now+4]}")
now += 5
elif opcode == 65:
print("reg1+=reg2")
now += 1
elif opcode == 66:
print("reg1-=reg4")
now += 1
elif opcode == 67:
print("reg1*=reg3")
now += 1
elif opcode == 55:
print("reg1=reg5")
now += 1
elif opcode == 56:
print("reg1^=reg4")
now += 1
elif opcode == 57:
print("reg1^=reg5")
now += 1
elif opcode == 53:
print("reg5=reg1")
now += 1
elif opcode == 0xF7:
print("reg9+=reg1")
now += 1
elif opcode == 68:
print("reg1/=reg5")
now += 1
elif opcode == 0x80:
print(f"reg{reg[now+1]}= {int.from_bytes(bytes(reg[now + 2:now + 6]), 'little')}")
now += 6
elif opcode == 0x77:
print("reg1^=reg9")
now += 1
elif opcode == 0x53:
print("pop [reg3]")
now += 2
elif opcode == 0x22:
print("reg1>>=reg2")
now += 1
elif opcode == 0x23:
print("reg1<<=reg2")
now += 1
elif opcode == 0x99:
break
elif opcode == 0x76:
print("r3 = [r6]")
print("[r6] = 0")
print("r6 += 4")
now += 5
elif opcode == 0x54:
print("read [reg3]")
now += 2
elif opcode == 0x30:
print("reg1|=reg2")
now += 1
elif opcode == 0x31:
print("reg1&=reg2")
now += 1
elif opcode == 0x32:
print(f"r3 = {reg[now+1]}")
now += 2
elif opcode == 9:
print("reg1=1877735783")
now += 1
elif opcode == 0x10:
print("reg9=reg1")
now += 1
elif opcode == 0x33:
print("reg4=reg1")
now += 1
elif opcode == 0x34:
print(f"reg2={reg[now+1]}")
now += 2
elif opcode == 0xFE:
print("reg1=reg9")
now += 1
elif opcode == 0x11:
print("printf '%x\\n', reg1")
now += 1
elif opcode == 0xA0:
print("cmp reg1=1877735783")
print("jne exit")
now += 1
elif opcode == 0xA1:
print("read 0, s, 0x2Cu")
print("cmp strlen(s), 44")
print("jne exit")
now += 1
elif opcode == 0xB1:
print(f"reg9={fog[0]}")
now += 1
elif opcode == 0xB2:
print(f"reg9={fog[1]}")
now += 1
elif opcode == 0xA4:
print(f"fog[{now}]=reg1")
now += 4
elif opcode == 0xB3:
print("reg9=fog[2]")
now += 1
elif opcode == 0xB4:
print("reg9=fog[3]")
now += 1
elif opcode == 0xC1:
print(f"reg1=s[{reg[now+1]}]")
now += 2
elif opcode == 0xC7:
print(f"cmp {exit_door[0]}, reg1")
print("jne exit")
now += 1
elif opcode == 0xC8:
print(f"cmp {exit_door[1]}, reg1")
print("jne exit")
now += 1
elif opcode == 0xC2:
print("exit if now!=r1")
now += 5


print_asm(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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
read 0, s, 0x2Cu
cmp strlen(s), 44
jne exit
reg1=s[0]
reg9=123
reg1^=reg9
exit if 74!=r1
reg1=s[1]
reg9=47
reg1^=reg9
exit if 25!=r1
reg1=s[2]
reg9=fog[3]
reg1^=reg9
exit if 221!=r1
reg1=s[3]
reg9=fog[2]
reg1^=reg9
exit if 15!=r1
reg1=s[4]
reg9=47
reg1^=reg9
exit if 27!=r1
reg1=s[5]
reg9=fog[3]
reg1^=reg9
exit if 137!=r1
reg1=s[6]
reg9=123
reg1^=reg9
exit if 25!=r1
reg1=s[7]
reg9=fog[2]
reg1^=reg9
exit if 84!=r1
reg1=s[8]
reg9=123
reg1^=reg9
exit if 79!=r1
reg1=s[9]
reg9=123
reg1^=reg9
exit if 78!=r1
reg1=s[10]
reg9=fog[2]
reg1^=reg9
exit if 85!=r1
reg1=s[11]
reg9=fog[2]
reg1^=reg9
exit if 86!=r1
reg1=s[12]
reg9=fog[3]
reg1^=reg9
exit if 142!=r1
reg1=s[13]
reg9=47
reg1^=reg9
exit if 73!=r1
reg1=s[14]
reg9=fog[2]
reg1^=reg9
exit if 14!=r1
reg1=s[15]
reg9=123
reg1^=reg9
exit if 75!=r1
reg1=s[16]
reg9=fog[2]
reg1^=reg9
exit if 6!=r1
reg1=s[17]
reg9=fog[2]
reg1^=reg9
exit if 84!=r1
reg1=s[18]
reg9=47
reg1^=reg9
exit if 26!=r1
reg1=s[19]
reg9=123
reg1^=reg9
exit if 66!=r1
reg1=s[20]
reg9=fog[2]
reg1^=reg9
exit if 83!=r1
reg1=s[21]
reg9=123
reg1^=reg9
exit if 31!=r1
reg1=s[22]
reg9=fog[2]
reg1^=reg9
exit if 82!=r1
reg1=s[23]
reg9=fog[3]
reg1^=reg9
exit if 219!=r1
reg1=s[24]
reg9=123
reg1^=reg9
exit if 25!=r1
reg1=s[25]
reg9=fog[3]
reg1^=reg9
exit if 217!=r1
reg1=s[26]
reg9=123
reg1^=reg9
exit if 25!=r1
reg1=s[27]
reg9=fog[2]
reg1^=reg9
exit if 85!=r1
reg1=s[28]
reg9=47
reg1^=reg9
exit if 25!=r1
reg1=s[29]
reg9=fog[2]
reg1^=reg9
exit if 0!=r1
reg1=s[30]
reg9=123
reg1^=reg9
exit if 75!=r1
reg1=s[31]
reg9=47
reg1^=reg9
exit if 30!=r1
reg1=s[32]
reg2= 24
reg1<<=reg2
reg9=reg1
reg1=s[33]
reg2= 16
reg1<<=reg2
reg9+=reg1
reg1=s[34]
reg2= 8
reg1<<=reg2
reg9+=reg1
reg1=s[35]
reg9+=reg1
reg1=reg9
reg2= 5
reg1>>=reg2
reg1^=reg9
reg9=reg1
reg2= 7
reg1<<=reg2
reg2= 2565961507
reg1&=reg2
reg1^=reg9
reg9=reg1
reg2= 24
reg1<<=reg2
reg2= 904182048
reg1&=reg2
reg1^=reg9
reg9=reg1
reg2= 18
reg1>>=reg2
reg1^=reg9
cmp reg1=1877735783
jne exit
reg1=s[36]
reg2= 24
reg1<<=reg2
reg9=reg1
reg1=s[37]
reg2= 16
reg1<<=reg2
reg9+=reg1
reg1=s[38]
reg2= 8
reg1<<=reg2
reg9+=reg1
reg1=s[39]
reg9+=reg1
reg1=reg9
r3 = 32
reg1*=reg3
reg4=reg1
reg1^=reg9
reg2= 17
reg1>>=reg2
reg5=reg1
reg1=reg5
reg1^=reg4
reg1^=reg9
reg2= 13
reg1<<=reg2
reg1^=reg9
reg1^=reg4
reg1^=reg5
reg9=reg1
r3 = 32
reg1*=reg3
reg4=reg1
reg1^=reg9
reg2= 17
reg1>>=reg2
reg5=reg1
reg1=reg5
reg1^=reg4
reg1^=reg9
reg2= 13
reg1<<=reg2
reg1^=reg9
reg1^=reg4
reg1^=reg5
cmp 3474130140, reg1
jne exit
reg1=s[40]
reg2= 24
reg1<<=reg2
reg9=reg1
reg1=s[41]
reg2= 16
reg1<<=reg2
reg9+=reg1
reg1=s[42]
reg2= 8
reg1<<=reg2
reg9+=reg1
reg1=s[43]
reg9+=reg1
reg1=reg9
r3 = 32
reg1*=reg3
reg4=reg1
reg1^=reg9
reg2= 17
reg1>>=reg2
reg5=reg1
reg1=reg5
reg1^=reg4
reg1^=reg9
reg2= 13
reg1<<=reg2
reg1^=reg9
reg1^=reg4
reg1^=reg5
reg9=reg1
r3 = 32
reg1*=reg3
reg4=reg1
reg1^=reg9
reg2= 17
reg1>>=reg2
reg5=reg1
reg1=reg5
reg1^=reg4
reg1^=reg9
reg2= 13
reg1<<=reg2
reg1^=reg9
reg1^=reg4
reg1^=reg5
cmp 674991748, reg1
jne exit

前面异或直接给ai破

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
fog = [0x0000007B, 0x0000002F, 0x00000037, 0x000000E8]
s = [None] * 32 # 创建一个长度为 32 的列表来存储 s 的值


# 对于每个 i,x 和 y 的值
for i, x, y in [
(0, fog[0], 74),
(1, fog[1], 25),
(2, fog[3], 221),
(3, fog[2], 15),
(4, fog[1], 27),
(5, fog[3], 137),
(6, fog[0], 25),
(7, fog[2], 84),
(8, fog[0], 79),
(9, fog[0], 78),
(10, fog[2], 85),
(11, fog[2], 86),
(12, fog[3], 142),
(13, fog[1], 73),
(14, fog[2], 14),
(15, fog[0], 75),
(16, fog[2], 6),
(17, fog[2], 84),
(18, fog[1], 26),
(19, fog[0], 66),
(20, fog[2], 83),
(21, fog[0], 31),
(22, fog[2], 82),
(23, fog[3], 219),
(24, fog[0], 25),
(25, fog[3], 217),
(26, fog[0], 25),
(27, fog[2], 85),
(28, fog[1], 25),
(29, fog[2], 0),
(30, fog[0], 75),
(31, fog[1], 30)
]:

s[i] = chr(y ^ x)
print(s)

#16584abc45baff901c59dde3b1bb6701
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
import itertools
import string

characters = string.ascii_letters + string.digits + string.punctuation + ' '
combinations = itertools.product(characters, repeat=4)

对每个组合执行给定的操作
for combination in combinations:
s = ''.join(combination)
reg = [0] * 10
reg[9] = int.from_bytes(s.encode(), 'big')
# 将字符串转换为整数,这里用big,存储就是正序,不然是小端序转换

reg[1] = reg[9]
reg[2] = 5
reg[1] >>= reg[2]
reg[1] ^= reg[9]

reg[9] = reg[1]
reg[2] = 7
reg[1] <<= reg[2]

reg[2] = 2565961507
reg[1] &= reg[2]
reg[1] ^= reg[9]

reg[9] = reg[1]
reg[2] = 24
reg[1] <<= reg[2]

reg[2] = 904182048
reg[1] &= reg[2]
reg[1] ^= reg[9]

reg[9] = reg[1]
reg[2] = 18
reg[1] >>= reg[2]
reg[1] ^= reg[9]

# 检查结果是否等于 1877735783
if reg[1] == 1877735783:
print(f"找到了满足条件的字符串:{s}")
break
# a245

第二部分有与,不可能逆出来,干脆爆破

后面两次有左移,不好用python,就用c

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

int main() {
// 所有可能的字符
char characters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ";

// 初始化寄存器
unsigned int reg[10] = { 0 };

// 对每一个组合进行检查
for (int i = 0; i < strlen(characters); i++) {
for (int j = 0; j < strlen(characters); j++) {
for (int k = 0; k < strlen(characters); k++) {
for (int l = 0; l < strlen(characters); l++) {
char s[40] = { 0 };
s[36] = characters[i];
s[37] = characters[j];
s[38] = characters[k];
s[39] = characters[l];

// 执行给定的操作
reg[1] = s[36];
reg[2] = 24;
reg[1] <<= reg[2];
reg[9] = reg[1];
reg[1] = s[37];
reg[2] = 16;
reg[1] <<= reg[2];
reg[9] += reg[1];
reg[1] = s[38];
reg[2] = 8;
reg[1] <<= reg[2];
reg[9] += reg[1];
reg[1] = s[39];
reg[9] += reg[1];

reg[1] = reg[9];
reg[3] = 32;
reg[1] *= reg[3];
reg[4] = reg[1];
reg[1] ^= reg[9];
reg[2] = 17;
reg[1] >>= reg[2];
reg[5] = reg[1];
reg[1] = reg[5];
reg[1] ^= reg[4];
reg[1] ^= reg[9];
reg[2] = 13;
reg[1] <<= reg[2];
reg[1] ^= reg[9];
reg[1] ^= reg[4];
reg[1] ^= reg[5];
reg[9] = reg[1];
reg[3] = 32;
reg[1] *= reg[3];
reg[4] = reg[1];
reg[1] ^= reg[9];
reg[2] = 17;
reg[1] >>= reg[2];
reg[5] = reg[1];
reg[1] = reg[5];
reg[1] ^= reg[4];
reg[1] ^= reg[9];
reg[2] = 13;
reg[1] <<= reg[2];
reg[1] ^= reg[9];
reg[1] ^= reg[4];
reg[1] ^= reg[5];

// 检查结果
if (reg[1] == 3474130140) {
printf("Found matching combination: %c%c%c%c\n", s[36], s[37], s[38], s[39]);
return 0;
}
}
}
}
}

printf("No matching combination found.\n");
return 0;
}
//b06c
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
#include <stdio.h>
#include <string.h>

int main() {
// 所有可能的字符
char characters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ";

// 初始化寄存器
unsigned int reg[10] = {0};

// 对每一个组合进行检查
for (int i = 0; i < strlen(characters); i++) {
for (int j = 0; j < strlen(characters); j++) {
for (int k = 0; k < strlen(characters); k++) {
for (int l = 0; l < strlen(characters); l++) {
char s[44] = {0};
s[40] = characters[i];
s[41] = characters[j];
s[42] = characters[k];
s[43] = characters[l];

// 执行给定的操作
reg[1] = s[40];
reg[2] = 24;
reg[1] <<= reg[2];
reg[9] = reg[1];
reg[1] = s[41];
reg[2] = 16;
reg[1] <<= reg[2];
reg[9] += reg[1];
reg[1] = s[42];
reg[2] = 8;
reg[1] <<= reg[2];
reg[9] += reg[1];
reg[1] = s[43];
reg[9] += reg[1];

reg[1] = reg[9];
reg[3] = 32;
reg[1] *= reg[3];
reg[4] = reg[1];
reg[1] ^= reg[9];
reg[2] = 17;
reg[1] >>= reg[2];
reg[5] = reg[1];
reg[1] = reg[5];
reg[1] ^= reg[4];
reg[1] ^= reg[9];
reg[2] = 13;
reg[1] <<= reg[2];
reg[1] ^= reg[9];
reg[1] ^= reg[4];
reg[1] ^= reg[5];
reg[9] = reg[1];
reg[3] = 32;
reg[1] *= reg[3];
reg[4] = reg[1];
reg[1] ^= reg[9];
reg[2] = 17;
reg[1] >>= reg[2];
reg[5] = reg[1];
reg[1] = reg[5];
reg[1] ^= reg[4];
reg[1] ^= reg[9];
reg[2] = 13;
reg[1] <<= reg[2];
reg[1] ^= reg[9];
reg[1] ^= reg[4];
reg[1] ^= reg[5];

// 检查结果
if (reg[1] == 674991748) {
printf("Found matching combination: %c%c%c%c\n", s[40], s[41], s[42], s[43]);
return 0;
}
}
}
}
}

printf("No matching combination found.\n");
return 0;
}

//dc23

最后合并一下flag

1
NSSCTF{16584abc45baff901c59dde3b1bb6701a254b06cdc23}

这个题最后很明显是不能直接逆向的,那就需要爆破,所以翻译opcode的时候写成python语法或者c语法就会更方便,然后注意一下爆破的时候的大端序和小端序就好了

羊城杯2023 vm_wo

这道题是我第一次遇见mac的题

一开始用ida 8.3打开,但是不能反编译,去网上看wp发现好像都能反编译,于是试了试7.7结果就可以了>_<

打开之后直接去主函数,直接拿到了last

1
[0xDF, 0xD5, 0xF1, 0xD1, 0xFF, 0xDB, 0xA1, 0xA5, 0x89, 0xBD, 0xE9, 0x95, 0xB3, 0x9D, 0xE9, 0xB3, 0x85, 0x99, 0x87, 0xBF, 0xE9, 0xB1, 0x89, 0xE9, 0x91, 0x89, 0x89, 0x8F, 0xAD]

在之前进行了myoperate这个函数,应该是encode
然后就是

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
void __fastcall myoperate(char *flag, int len)
{
__int64 i; // x20
char v4[15]; // [xsp+8h] [xbp-98h] BYREF
char v5[15]; // [xsp+18h] [xbp-88h] BYREF
char v6[15]; // [xsp+28h] [xbp-78h] BYREF
char code[16]; // [xsp+38h] [xbp-68h] BYREF
__int64 v8; // [xsp+48h] [xbp-58h]

LODWORD(i) = len;
v8 = 0x100000CFEEDFALL;
dword_100008003 = 0xBEEDBEEF;
if ( ptrace(0, 0, (caddr_t)1, 0) == -1 )
exit(0);
if ( (int)i >= 1 )
{
i = (unsigned int)i;
do
{
*(_QWORD *)code = 0x20D01011903001ALL;
*(_QWORD *)&code[7] = 0x300010201180702LL;
code[2] = *flag;
interpretBytecode(code, 15);
*(_QWORD *)v6 = 0x20D02011903001ALL;
*(_QWORD *)&v6[7] = 0x400010201180602LL;
v6[2] = vm.body[0];
interpretBytecode(v6, 15);
*(_QWORD *)v5 = 0x20D03011903001ALL;
*(_QWORD *)&v5[7] = 0x500010201180502LL;
v5[2] = vm.body[0];
interpretBytecode(v5, 15);
*(_QWORD *)v4 = 0x20D04011903001ALL;
*(_QWORD *)&v4[7] = 0x600010201180402LL;
v4[2] = vm.body[0];
interpretBytecode(v4, 15);
*flag++ = ((unsigned __int8)vm.body[0] >> 5) | (8 * vm.body[0]);
--i;
}
while ( i );
}
}

这个是opcode生成的位置,注意一共有15位同时第二位被换成了flag的值
相当于每轮对一个字符加密
所以写解密函数

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
t = [[0x1a,0x0,0xff,0x19,0x1,0x1,0xd,0x2,0x7,0x18,0x1,0x2,0x1,0x0,0x3],
[0x1a,0x0,0xff,0x19,0x1,0x2,0xd,0x2,0x6,0x18,0x1,0x2,0x1,0x0,0x4],
[0x1a,0x0,0xff,0x19,0x1,0x3,0xd,0x2,0x5,0x18,0x1,0x2,0x1,0x0,0x5],
[ 0x1a,0x0,0xff,0x19,0x1,0x4,0xd,0x2,0x4,0x18,0x1,0x2,0x1,0x0,0x6]]
# 0xff用作标志,表明这里使用了上一次加密后的这一位flag
i = 0
for b in t:
i=0
if i < 15:
while True:
# this_code = b[i]
code0 = b[i]
code1 = b[i+1]
code2 = b[i+2]
if code0 == 0:
print(f"s[{code1}], s[{code2}] = s[{code2}], s[{code1}]")
elif code0 == 1:
print(f"s[{code1}] ^= s[{code2}]")
elif code0 == 2:
print(f"s[{code1}] += {code2}")
elif code0 == 3:
print(f"s[{code1}] += s[{code2}]")
elif code0 == 4:
print(f"s[{code1}] -= {code2}")
elif code0 == 5:
print(f"s[{code1}] -= s[{code2}]")
elif code0 == 6:
print(f"s[{code1}] *= {code2}")
elif code0 == 7:
print(f"s[{code1}] *= s[{code2}]")
elif code0 == 8:
print(f"s[{code1}] //= {code2}")
elif code0 == 9:
print(f"s[{code1}] //= s[{code2}]")
elif code0 == 10:
print(f"s[{code1}] -= s[{code1}]")
elif code0 == 11:
print(f"s[{code1}] -= s[{code1}]")
elif code0 == 12:
print(f"s[{code1}] = s[{code1}] << {code2}")
elif code0 == 13:
print(f"s[{code1}] = s[0] << {code2}")
elif code0 == 14:
print(f"s[{code1}] = s[{code1}]")
elif code0 == 15:
print(f"print(s[{code1}])")
elif code0 == 16:
i -= 1
print(f"i -= 1")
print(f"print(s[{i + 16}])")
elif code0 == 17:
print(f"i = {code2} if not s[{code1}]")
elif code0 == 18:
print(f"i = {code2} if s[{code1}]")
# elif code0 == 19:
# # i = code1
# elif code0 == 20:
# # s[code1] = s[code1]
# elif code0 == 21:
# # i -= 1
# # s[0] = s[i + 16]
# elif code0 == 22:
# # s[i + 16] = code1
# elif code0 == 23:
# break
elif code0 == 24:
print(f"s[0] = byte_100008002 | byte_100008001")
elif code0 == 25:
print(f"s[{code1}] = s[0] >> {code2}")
elif code0 == 26:
print(f"s[{code1}] = {code2}")
i += 3
if i >= len(b):
break

得到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
s[0] = flag[i]
s[1] = s[0] >> 1
s[2] = s[0] << 7
s[0] = byte_100008002 | byte_100008001
s[0] ^= s[3]
# s[0] = 255
s[1] = s[0] >> 2
s[2] = s[0] << 6
s[0] = byte_100008002 | byte_100008001
s[0] ^= s[4]
# s[0] = 255
s[1] = s[0] >> 3
s[2] = s[0] << 5
s[0] = byte_100008002 | byte_100008001
s[0] ^= s[5]
# s[0] = 255
s[1] = s[0] >> 4
s[2] = s[0] << 4
s[0] = byte_100008002 | byte_100008001
s[0] ^= s[6]

但是我不理解的是byte_100008002和byte_100008001的值,不然没法或。。
去网上看了wp,看到了它们的dword_100008003和这两个值是一样的
(然后才发现那四个值在一起是个数组,前面还有3个寄存器,就是上面代码的s0,s1,s2)
就是

1
arr = 0xDEEDBEEF.to_bytes(4,'little')

相当于这个dword是s = [0,0,0xEF,0xBE,0xED,0xDE]放在这四个位置上,因为deadbeef是第四个上面放着
写一下解密脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from prism import *
last = [0xDF, 0xD5, 0xF1, 0xD1, 0xFF, 0xDB, 0xA1, 0xA5,
0x89, 0xBD, 0xE9, 0x95, 0xB3, 0x9D, 0xE9, 0xB3,
0x85, 0x99, 0x87, 0xBF, 0xE9, 0xB1, 0x89, 0xE9,
0x91, 0x89, 0x89, 0x8F, 0xAD]

def back(k):
q = []
for i in range(len(k)):
for s in range(0,128):
t = (s >> 1 | (s << 7)&0xff)^0xef
t = (t >> 2 | (t << 6)&0xff)^0xbe
t = (t >> 3 | (t << 5)&0xff)^0xed
t = (t >> 4 | (t << 4)&0xff)^0xde
t = (t >> 5 | (t << 3)&0xff)
if (t == k[i]):
q.append(s)
return q

pl(back(last))

?为什么出不来,好好好,不是deadbeef是beedbeef是吧,,6,改好之后

1
DASCTF{you_are_right_so_cool}

做完这几道题,感觉vm主要考把opcode转汇编,再把汇编转可读代码的静态分析能力,这里要分析出reg,stack的实现是哪些代码,如果能拿到opcode,就能分析出其中可能不用的case,省去一些时间

而且一般是用单字节加密,所以后面可以爆破答案,

如果用python写脚本,要注意左移时要限定范围不然会得不到正确结果

最后在第三道题,ida版本能直接影响到反编译的结果,最后用7.5版本才能正确反编译出来