这种题首先他会有以一个while(1)的循环,这个循环的作用就是模拟计算机去读取东西然后进行操作。

image-20231115193006807

他首先会有一个伪汇编,然后用一个if去判断,判断是哪一个指令。然后进行该指令。

例子:

image-20231115215651240

1
2
3
sub_4111BD((int)v3);	//这个函数是定义伪汇编
sub_4112EE((int)v3); //这个函数是循环读取指令
sub_411078(); //最后的比较

这三个函数就很重要

sub_4111BD

image-20231115220055735

sub_4112EE

这个是一个VM的题。Wp说很简单,但是我觉得一点都不简单。

image-20231115202322978

首先我们来分析伪汇编的内容。

sub_4111BD:

image-20231115202410534

fun1:是一个模仿mov 操作的函数

image-20231116131526308

fun2:

image-20231116131658594

是一个模仿xor的函数

fun3:

image-20231116131731429

是一个读取文件的操作。

然后我们来看循环读取指令的操作

image-20231116131908999

就是一直读取,然后遇到F4就结束。

最后看flag的判断的函数

image-20231116131957744

就是执行完上面的“加密”[循环的操作后]flag要和byte_41A000取反后的值相同。

然后就是用脚本来模拟出这些操作:将他弄成伪代码

首先我们找到要执行的代码来进行匹配的数据:

image-20231116132354723

image-20231116132404053

因为我们知道一直到F4就会停止。所以我们就提取数据一直到F4.

image-20231116132449959

借用了下面的大佬写的代码:

https://www.cnblogs.com/Only-xiaoxiao/p/16859493.html

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
opcode = [0xF5, 0xF1, 0xE1, 0x00, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,
0x20, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x01, 0x00, 0x00, 0x00,
0xF2, 0xF1, 0xE4, 0x21, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02,
0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x22, 0x00, 0x00, 0x00,
0xF1, 0xE1, 0x03, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x23,
0x00, 0x00, 0x00, 0xF1, 0xE1, 0x04, 0x00, 0x00, 0x00, 0xF2,
0xF1, 0xE4, 0x24, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x05, 0x00,
0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x25, 0x00, 0x00, 0x00, 0xF1,
0xE1, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x26, 0x00,
0x00, 0x00, 0xF1, 0xE1, 0x07, 0x00, 0x00, 0x00, 0xF2, 0xF1,
0xE4, 0x27, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x08, 0x00, 0x00,
0x00, 0xF2, 0xF1, 0xE4, 0x28, 0x00, 0x00, 0x00, 0xF1, 0xE1,
0x09, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x29, 0x00, 0x00,
0x00, 0xF1, 0xE1, 0x0A, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,
0x2A, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0B, 0x00, 0x00, 0x00,
0xF2, 0xF1, 0xE4, 0x2B, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0C,
0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x2C, 0x00, 0x00, 0x00,
0xF4]

for i in range(len(opcode)):
if opcode[i] == 0xF1:
print('mov ', end='')
if opcode[i + 1] == 0xE1:
print('eax ' + 'flag[' + str(opcode[i + 2]) + ']')
elif opcode[i + 1] == 0xE2:
print('ebx ' + 'flag[' + str(opcode[i + 2]) + ']')
elif opcode[i + 1] == 0xE3:
print('ecx ' + 'flag[' + str(opcode[i + 2]) + ']')
elif opcode[i + 1] == 0xE4:
print('flag[' + str(opcode[i + 2]) + '] ' + 'eax')
i += 13
elif opcode[i] == 0xf2:
print('xor eax ebx^0x12')

elif opcode[i] == 0xf5:
print('read 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
read flag

mov eax flag[0]
xor eax ebx^0x12
mov flag[32] eax

mov eax flag[1]
xor eax ebx^0x12
mov flag[33] eax

mov eax flag[2]
xor eax ebx^0x12
mov flag[34] eax

mov eax flag[3]
xor eax ebx^0x12
mov flag[35] eax

mov eax flag[4]
xor eax ebx^0x12
mov flag[36] eax

mov eax flag[5]
xor eax ebx^0x12
mov flag[37] eax

mov eax flag[6]
xor eax ebx^0x12
mov flag[38] eax

mov eax flag[7]
xor eax ebx^0x12
mov flag[39] eax

mov eax flag[8]
xor eax ebx^0x12
mov flag[40] eax

mov eax flag[9]
xor eax ebx^0x12
mov flag[41] eax

mov eax flag[10]
xor eax ebx^0x12
mov flag[42] eax

mov eax flag[11]
xor eax ebx^0x12
mov flag[43] eax

mov eax flag[12]
xor eax ebx^0x12
mov flag[44] eax