本文主要是介绍VM虚拟机逆向---[羊城杯 2021]Babyvm 复现【详解】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 前言
- 题目分析
- 汇编脚本
- 分析汇编
- exp
- 后言
前言
无
题目分析
&unk_804B0C0里面是opcode,sub_1C8里面有个mprotect,用了一个SMC加密。
我使用的是动态调试,因为是ELF文件,链接一下linux,进行动调,断点下在第九行就可以了,之后F7进入,sub_80487A8里面
选中,函数起始处一直到第一个retn的所有内容用U重定义下,然后C转换成代码就可以了。
这样就得到各个指令的实现了,接下来就是根据代码写脚本
汇编脚本
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]i = 0
while opcode[i] != 0x99:match opcode[i]:case 0x71:print(f"{i} push %d" % (opcode[i+1]))i += 5case 0x41:print(f"{i} add reg[1] reg[2]")i += 1case 0x42:print(f"{i} sub reg[1] reg[4]")i += 1case 0x43:print(f"{i} mul reg[1] reg[3]")i += 1case 0x37:print(f"{i} mov reg[1] reg[5]")i += 1case 0x38:print(f"{i} xor reg[1] reg[4]")i += 1case 0x39:print(f"{i} xor reg[1] reg[5]")i += 1case 0x35:print(f"{i} mov reg[5] reg[1]")i += 1case 0xF7:print(f"{i} add reg[9] reg[1]")i += 1case 0x44:print(f"{i} div reg[1] reg[5]")i += 1case 0x80:int_val = int.from_bytes(bytes(opcode[i + 2:i + 6]), 'little')print(f"{i} mov reg[?] {int_val}")i += 6case 0x77:print(f"{i} xor reg[1] reg[9]")i += 1case 0x53:print(f"{i} put reg[3]")i += 2case 0x22:print(f"{i} shr reg[1] reg[2]")i += 1case 0x23:print(f"{i} shl reg[1] reg[2]")i += 1case 0x76:print(f"{i} pop reg[3]")i += 5case 0x54:print(f"{i} get")i += 2case 0x30:print(f"{i} or reg[1] reg[2]")i += 1case 0x31:print(f"{i} and reg[1] reg[2]")i += 1case 0x32:print(f"{i} mov reg[3] %d" % (opcode[i+1]))i += 2case 0x09:print(f"{i} mov reg[1] 0x6FEBF967")i += 1case 0x10:print(f"{i} mov reg[9] reg[1]")i += 1case 0x33:print(f"{i} mov reg[4] reg[1]")i += 1case 0x34:print(f"{i} mov reg[2] %d" % (opcode[i+1]))i += 2case 0xFE:print(f"{i} mov reg[1] reg[9]")i += 1case 0x11:print(f"{i} print reg[1]")i += 1case 0xA0:print(f"{i} cmp reg[1] 0x6FEBF967")i += 1case 0xA1:print(f"{i} cmp len 44")i += 1case 0xB1:print(f"{i} mov reg[9] v[0]")i += 1case 0xB2:print(f"{i} mov reg[9] v[1]")i += 1case 0xA4:print(f"{i} mov v[%d] reg[1]" % (opcode[i + 1]))i += 4case 0xB3:print(f"{i} mov reg[9] v[2]")i += 1case 0xB4:print(f"{i} mov reg[9] v[3]")i += 1case 0xC1:print(f"{i} mov reg[1] s[%d]" % (opcode[i + 1]))i += 2case 0xC7:print(f"{i} cmp d[0] reg[1]")i += 1case 0xC8:print(f"{i} cmp d[1] reg[1]")i += 1case 0xC2:print(f"{i} cmp %d reg[1]" % (opcode[i+1]))i += 5
打印出来:
0 cmp len 44
1 mov reg[1] s[0]
3 mov reg[9] v[0]
4 xor reg[1] reg[9]
5 cmp 74 reg[1]
10 mov reg[1] s[1]
12 mov reg[9] v[1]
13 xor reg[1] reg[9]
14 cmp 25 reg[1]
19 mov reg[1] s[2]
21 mov reg[9] v[3]
22 xor reg[1] reg[9]
23 cmp 221 reg[1]
28 mov reg[1] s[3]
30 mov reg[9] v[2]
31 xor reg[1] reg[9]
32 cmp 15 reg[1]
37 mov reg[1] s[4]
39 mov reg[9] v[1]
40 xor reg[1] reg[9]
41 cmp 27 reg[1]
46 mov reg[1] s[5]
48 mov reg[9] v[3]
49 xor reg[1] reg[9]
50 cmp 137 reg[1]
55 mov reg[1] s[6]
57 mov reg[9] v[0]
58 xor reg[1] reg[9]
59 cmp 25 reg[1]
64 mov reg[1] s[7]
66 mov reg[9] v[2]
67 xor reg[1] reg[9]
68 cmp 84 reg[1]
73 mov reg[1] s[8]
75 mov reg[9] v[0]
76 xor reg[1] reg[9]
77 cmp 79 reg[1]
82 mov reg[1] s[9]
84 mov reg[9] v[0]
85 xor reg[1] reg[9]
86 cmp 78 reg[1]
91 mov reg[1] s[10]
93 mov reg[9] v[2]
94 xor reg[1] reg[9]
95 cmp 85 reg[1]
100 mov reg[1] s[11]
102 mov reg[9] v[2]
103 xor reg[1] reg[9]
104 cmp 86 reg[1]
109 mov reg[1] s[12]
111 mov reg[9] v[3]
112 xor reg[1] reg[9]
113 cmp 142 reg[1]
118 mov reg[1] s[13]
120 mov reg[9] v[1]
121 xor reg[1] reg[9]
122 cmp 73 reg[1]
127 mov reg[1] s[14]
129 mov reg[9] v[2]
130 xor reg[1] reg[9]
131 cmp 14 reg[1]
136 mov reg[1] s[15]
138 mov reg[9] v[0]
139 xor reg[1] reg[9]
140 cmp 75 reg[1]
145 mov reg[1] s[16]
147 mov reg[9] v[2]
148 xor reg[1] reg[9]
149 cmp 6 reg[1]
154 mov reg[1] s[17]
156 mov reg[9] v[2]
157 xor reg[1] reg[9]
158 cmp 84 reg[1]
163 mov reg[1] s[18]
165 mov reg[9] v[1]
166 xor reg[1] reg[9]
167 cmp 26 reg[1]
172 mov reg[1] s[19]
174 mov reg[9] v[0]
175 xor reg[1] reg[9]
176 cmp 66 reg[1]
181 mov reg[1] s[20]
183 mov reg[9] v[2]
184 xor reg[1] reg[9]
185 cmp 83 reg[1]
190 mov reg[1] s[21]
192 mov reg[9] v[0]
193 xor reg[1] reg[9]
194 cmp 31 reg[1]
199 mov reg[1] s[22]
201 mov reg[9] v[2]
202 xor reg[1] reg[9]
203 cmp 82 reg[1]
208 mov reg[1] s[23]
210 mov reg[9] v[3]
211 xor reg[1] reg[9]
212 cmp 219 reg[1]
217 mov reg[1] s[24]
219 mov reg[9] v[0]
220 xor reg[1] reg[9]
221 cmp 25 reg[1]
226 mov reg[1] s[25]
228 mov reg[9] v[3]
229 xor reg[1] reg[9]
230 cmp 217 reg[1]
235 mov reg[1] s[26]
237 mov reg[9] v[0]
238 xor reg[1] reg[9]
239 cmp 25 reg[1]
244 mov reg[1] s[27]
246 mov reg[9] v[2]
247 xor reg[1] reg[9]
248 cmp 85 reg[1]
253 mov reg[1] s[28]
255 mov reg[9] v[1]
256 xor reg[1] reg[9]
257 cmp 25 reg[1]
262 mov reg[1] s[29]
264 mov reg[9] v[2]
265 xor reg[1] reg[9]
266 cmp 0 reg[1]
271 mov reg[1] s[30]
273 mov reg[9] v[0]
274 xor reg[1] reg[9]
275 cmp 75 reg[1]
280 mov reg[1] s[31]
282 mov reg[9] v[1]
283 xor reg[1] reg[9]
284 cmp 30 reg[1]
289 mov reg[1] s[32]
291 mov reg[?] 24
297 shl reg[1] reg[2]
298 mov reg[9] reg[1]
299 mov reg[1] s[33]
301 mov reg[?] 16
307 shl reg[1] reg[2]
308 add reg[9] reg[1]
309 mov reg[1] s[34]
311 mov reg[?] 8
317 shl reg[1] reg[2]
318 add reg[9] reg[1]
319 mov reg[1] s[35]
321 add reg[9] reg[1]
322 mov reg[1] reg[9]
323 mov reg[?] 5
329 shr reg[1] reg[2]
330 xor reg[1] reg[9]
331 mov reg[9] reg[1]
332 mov reg[?] 7
338 shl reg[1] reg[2]
339 mov reg[?] 2565961507
345 and reg[1] reg[2]
346 xor reg[1] reg[9]
347 mov reg[9] reg[1]
348 mov reg[?] 24
354 shl reg[1] reg[2]
355 mov reg[?] 904182048
361 and reg[1] reg[2]
362 xor reg[1] reg[9]
363 mov reg[9] reg[1]
364 mov reg[?] 18
370 shr reg[1] reg[2]
371 xor reg[1] reg[9]
372 cmp reg[1] 0x6FEBF967
373 mov reg[1] s[36]
375 mov reg[?] 24
381 shl reg[1] reg[2]
382 mov reg[9] reg[1]
383 mov reg[1] s[37]
385 mov reg[?] 16
391 shl reg[1] reg[2]
392 add reg[9] reg[1]
393 mov reg[1] s[38]
395 mov reg[?] 8
401 shl reg[1] reg[2]
402 add reg[9] reg[1]
403 mov reg[1] s[39]
405 add reg[9] reg[1]
406 mov reg[1] reg[9]
407 mov reg[3] 32
409 mul reg[1] reg[3]
410 mov reg[4] reg[1]
411 xor reg[1] reg[9]
412 mov reg[?] 17
418 shr reg[1] reg[2]
419 mov reg[5] reg[1]
420 mov reg[1] reg[5]
421 xor reg[1] reg[4]
422 xor reg[1] reg[9]
423 mov reg[?] 13
429 shl reg[1] reg[2]
430 xor reg[1] reg[9]
431 xor reg[1] reg[4]
432 xor reg[1] reg[5]
433 mov reg[9] reg[1]
434 mov reg[3] 32
436 mul reg[1] reg[3]
437 mov reg[4] reg[1]
438 xor reg[1] reg[9]
439 mov reg[?] 17
445 shr reg[1] reg[2]
446 mov reg[5] reg[1]
447 mov reg[1] reg[5]
448 xor reg[1] reg[4]
449 xor reg[1] reg[9]
450 mov reg[?] 13
456 shl reg[1] reg[2]
457 xor reg[1] reg[9]
458 xor reg[1] reg[4]
459 xor reg[1] reg[5]
460 cmp d[0] reg[1]
461 mov reg[1] s[40]
463 mov reg[?] 24
469 shl reg[1] reg[2]
470 mov reg[9] reg[1]
471 mov reg[1] s[41]
473 mov reg[?] 16
479 shl reg[1] reg[2]
480 add reg[9] reg[1]
481 mov reg[1] s[42]
483 mov reg[?] 8
489 shl reg[1] reg[2]
490 add reg[9] reg[1]
491 mov reg[1] s[43]
493 add reg[9] reg[1]
494 mov reg[1] reg[9]
495 mov reg[3] 32
497 mul reg[1] reg[3]
498 mov reg[4] reg[1]
499 xor reg[1] reg[9]
500 mov reg[?] 17
506 shr reg[1] reg[2]
507 mov reg[5] reg[1]
508 mov reg[1] reg[5]
509 xor reg[1] reg[4]
510 xor reg[1] reg[9]
511 mov reg[?] 13
517 shl reg[1] reg[2]
518 xor reg[1] reg[9]
519 xor reg[1] reg[4]
520 xor reg[1] reg[5]
521 mov reg[9] reg[1]
522 mov reg[3] 32
524 mul reg[1] reg[3]
525 mov reg[4] reg[1]
526 xor reg[1] reg[9]
527 mov reg[?] 17
533 shr reg[1] reg[2]
534 mov reg[5] reg[1]
535 mov reg[1] reg[5]
536 xor reg[1] reg[4]
537 xor reg[1] reg[9]
538 mov reg[?] 13
544 shl reg[1] reg[2]
545 xor reg[1] reg[9]
546 xor reg[1] reg[4]
547 xor reg[1] reg[5]
548 cmp d[1] reg[1]
分析汇编
前三十二个字节就是取 数据 异或得出来的;
后 十二个字节就很复杂了,可以考虑直接爆破。
exp
前三十二个:
print(chr(0x7b ^ 74) + chr(0x2f ^ 25) + chr(0xe8 ^ 221) + chr(0x37 ^ 15) + chr(0x2f ^ 27) + chr(0xe8 ^ 137) + chr(0x7b ^ 25) + chr(0x37 ^ 84) + chr(0x7b ^ 79) + chr(0x7b ^ 78) + chr(0x37 ^ 85) + chr(0x37 ^ 86) + chr(0xe8 ^ 142) + chr(0x2f ^ 73) + chr(0x37 ^ 14) + chr(0x7b ^ 75) + chr(0x37 ^ 6) + chr(0x37 ^ 84) + chr(0x2f ^ 26) + chr(0x7b ^ 66) + chr(0x37 ^ 83) + chr(0x7b ^ 31) + chr(0x37 ^ 82) + chr(0xe8 ^ 219) + chr(0x7b ^ 25) + chr(0xe8 ^ 217) + chr(0x7b ^ 25) + chr(0x37 ^ 85) + chr(0x2f ^ 25) + chr(0x37 ^ 0) + chr(0x7b ^ 75) + chr(0x2f ^ 30))
得到:16584abc45baff901c59dde3b1bb6701
后十二个:
第 33 34 35 36
start = 0x20202020while start <= 0xffffffff:s = startreg9 = ss >>= 5s ^= reg9reg9 = ss <<= 7s &= 2565961507s ^= reg9reg9 = ss <<= 24s &= 904182048s ^= reg9reg9 = ss >>= 18s ^= reg9if s == 1877735783:print(start)exit(0)else:start += 1
爆破后结果是:1630680372 转换为ascii码 ‘a254’
第 37 38 39 40
#include <cstdio>int main(){unsigned int record, reg1, reg2, reg3, reg4, reg5, reg6, unknown2;for(unsigned int unknown2=0x20202020;unknown2<0xffffffff;unknown2+=1){record = unknown2;reg1 = unknown2;reg3 = 32;reg1 *= reg3;reg4 = reg1;reg1 ^= unknown2;reg2 = 17;reg1 >>= reg2;reg6 = reg1;reg1 = reg6;reg1 ^= reg4;reg1 ^= unknown2;reg2 = 13;reg1 <<= reg2;reg1 ^= unknown2;reg1 ^= reg4;reg1 ^= reg6;unknown2 = reg1;reg3 = 32;reg1 *= reg3;reg4 = reg1;reg1 ^= unknown2;reg2 = 17;reg1 >>= reg2;reg6 = reg1;reg1 = reg6;reg1 ^= reg4;reg1 ^= unknown2;reg2 = 13;reg1 <<= reg2;reg1 ^= unknown2;reg1 ^= reg4;reg1 ^= reg6;unknown2 = record;if(reg1 == 0x0CF1304DC){printf("%u\n", record);break;}}
}
运行结果:1647326819 转换成ascii: b06c
第41 42 43 44
#include <cstdio>int main(){unsigned int record, reg1, reg2, reg3, reg4, reg5, reg6, unknown2;for(unsigned int unknown2=0x20202020;unknown2<0xffffffff;unknown2+=1){record = unknown2;reg1 = unknown2;reg3 = 32;reg1 *= reg3;reg4 = reg1;reg1 ^= unknown2;reg2 = 17;reg1 >>= reg2;reg6 = reg1;reg1 = reg6;reg1 ^= reg4;reg1 ^= unknown2;reg2 = 13;reg1 <<= reg2;reg1 ^= unknown2;reg1 ^= reg4;reg1 ^= reg6;unknown2 = reg1;reg3 = 32;reg1 *= reg3;reg4 = reg1;reg1 ^= unknown2;reg2 = 17;reg1 >>= reg2;reg6 = reg1;reg1 = reg6;reg1 ^= reg4;reg1 ^= unknown2;reg2 = 13;reg1 <<= reg2;reg1 ^= unknown2;reg1 ^= reg4;reg1 ^= reg6;unknown2 = record;if(reg1 == 0x283B8E84){printf("%u\n", record);break;}}
}
运行结果:1684222515 转换成ascii码:dc23
全部拼接起来就是:16584abc45baff901c59dde3b1bb6701a254b06cdc23
后言
这里最后面爆破卡了好久,最后俩个爆破脚本是大佬的,一直想着用python,应该早点想到要限制数据的大小的,unsigned int 通常表示非负整数,最大到0xFFFFFFFF。。。一直没留意,爆破不出东西来。傻了。
来来回回写了大概五六题vm逆向,渐渐明白为什么没有人写详解了(wp点开全都只有exp),,,写怎么推导指令,,,还是多练,就明白了,()。
这篇关于VM虚拟机逆向---[羊城杯 2021]Babyvm 复现【详解】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!