我复现所看的Wp来自:

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

如果想看Wp 请看上面这篇文章,写得很好,我只是将它的方法记录下来,并且我也有很多地方都没有能够成功的找出flag。看我的只会浪费你的时间。【真的】

5121-babyre

这个题,我分析不来…看了Wp后:

一个5251的编码:

flag{1594826307}

babyopcode

这个是一个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

对于上面的flag[32]不要大惊小怪:

说白了就是先用的flag[0]的数据然后存储到了flag[32]的位置

从比较的地方也能看出来是对flag[32+i]地址上的值来比较

image-20231116131957744

但是我们不知道a1[1]的值是多少哇。因为我们看上面的代码容易知道ebx的值是没用进行变化的。所以我们动态调试的看一下其中的值是多少。

image-20231116133853867

首先看是dw类型的

image-20231116134110290

最后写exp:

1
2
3
4
5
6
7
enc = [0xBB, 0x80, 0xB2, 0x9E, 0x82, 0xDC, 0x9E, 0xB2, 0xDE, 0x8C,
0x9E, 0x94]

enc = [((~i)^0x12)&0xff & 0xff for i in enc]

for i in range(len(enc)):
print(chr(enc[i]),end='')

或者在线:

image-20231116134319716

easyopcode

和babyopcode基本一样:

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
opcode = [0xF5, 0xF1, 0xE1, 0x00, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4,
0x20, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x01, 0x00, 0x00, 0x00,
0xF7, 0xF1, 0xE4, 0x21, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x00,
0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x20, 0x00, 0x00, 0x00,
0xF1, 0xE1, 0x0E, 0x00, 0x00, 0x00, 0xF6, 0xF1, 0xE4, 0x2E,
0x00, 0x00, 0x00, 0xF1, 0xE1, 0x02, 0x00, 0x00, 0x00, 0xFB,
0xF1, 0xE4, 0x22, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00,
0x00, 0x00, 0xF6, 0xF1, 0xE4, 0x2E, 0x00, 0x00, 0x00, 0xF1,
0xE1, 0x03, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x23, 0x00,
0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00, 0x00, 0x00, 0xF6, 0xF1,
0xE4, 0x2E, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x00, 0x00, 0x00,
0x00, 0xF2, 0xF1, 0xE4, 0x20, 0x00, 0x00, 0x00, 0xF1, 0xE1,
0x01, 0x00, 0x00, 0x00, 0xF7, 0xF1, 0xE4, 0x21, 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, 0x01,
0x00, 0x00, 0x00, 0xF7, 0xF1, 0xE4, 0x21, 0x00, 0x00, 0x00,
0xF1, 0xE1, 0x06, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x26,
0x00, 0x00, 0x00, 0xF1, 0xE1, 0x00, 0x00, 0x00, 0x00, 0xF2,
0xF1, 0xE4, 0x20, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x01, 0x00,
0x00, 0x00, 0xF7, 0xF1, 0xE4, 0x21, 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, 0xF6, 0xF1, 0xE4, 0x29, 0x00, 0x00, 0x00, 0xF1, 0xE1,
0x00, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x20, 0x00, 0x00,
0x00, 0xF1, 0xE1, 0x0A, 0x00, 0x00, 0x00, 0xF6, 0xF1, 0xE4,
0x2A, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0B, 0x00, 0x00, 0x00,
0xF6, 0xF1, 0xE4, 0x2B, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0C,
0x00, 0x00, 0x00, 0xF6, 0xF1, 0xE4, 0x2C, 0x00, 0x00, 0x00,
0xF1, 0xE1, 0x00, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x20,
0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0D, 0x00, 0x00, 0x00, 0xF6,
0xF1, 0xE4, 0x2D, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x0E, 0x00,
0x00, 0x00, 0xF6, 0xF1, 0xE4, 0x2E, 0x00, 0x00, 0x00, 0xF1,
0xE1, 0x0F, 0x00, 0x00, 0x00, 0xF6, 0xF1, 0xE4, 0x2F, 0x00,
0x00, 0x00, 0xF1, 0xE1, 0x10, 0x00, 0x00, 0x00, 0xF6, 0xF1,
0xE4, 0x30, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x11, 0x00, 0x00,
0x00, 0xF6, 0xF1, 0xE4, 0x31, 0x00, 0x00, 0x00, 0xF1, 0xE1,
0x00, 0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x20, 0x00, 0x00,
0x00, 0xF1, 0xE1, 0x12, 0x00, 0x00, 0x00, 0xF6, 0xF1, 0xE4,
0x32, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x13, 0x00, 0x00, 0x00,
0xF6, 0xF1, 0xE4, 0x33, 0x00, 0x00, 0x00, 0xF1, 0xE1, 0x00,
0x00, 0x00, 0x00, 0xF2, 0xF1, 0xE4, 0x20, 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^0x43')
elif opcode[i] == 0xf6:
print('xor eax ebx^0x34')
elif opcode[i] == 0xf7:
print('xor eax ebx^0x32')
elif opcode[i] == 0xf8:
print('xor eax ebx^0x23')
elif opcode[i] == 0xf9:
print('xor eax ebx^0x17')
elif opcode[i] == 0xfa:
print('xor eax ebx^0x71')
elif opcode[i] == 0xfb:
print('xor eax ebx^0x66g')
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
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
C:\Users\ASUS\Desktop\ppp\Scripts\python.exe C:\Users\ASUS\Desktop\1.py 
read flag

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

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

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

mov eax flag[14]
xor eax ebx^0x34
mov flag[46] eax

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

mov eax flag[14]
xor eax ebx^0x34
mov flag[46] eax

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

mov eax flag[14]
xor eax ebx^0x34
mov flag[46] eax

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

mov eax flag[13]
xor eax ebx^0x34
mov flag[45] eax

mov eax flag[14]
xor eax ebx^0x34
mov flag[46] eax

mov eax flag[15]
xor eax ebx^0x34
mov flag[47] eax

mov eax flag[16]
xor eax ebx^0x34
mov flag[48] eax

mov eax flag[17]
xor eax ebx^0x34
mov flag[49] eax

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

mov eax flag[18]
xor eax ebx^0x34
mov flag[50] eax

mov eax flag[19]
xor eax ebx^0x34
mov flag[51] eax

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

进程已结束,退出代码0

base64

base64换标

1
2
3
4
5
6
7
8
9
10
11
12
import base64
import string

str1 = "MTU5ZTMOMjIOYzAwZWFkMmQzYTAz0WQzMjA4NGV1NTA=" # 需要换表的字符串

string1 = "ABCDEFGHIJKLMN0PQRSTUVWXYZabcdofghijk1mnepqrstuvwxyzOl23456789+/" #IDA中看到的表
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" #IDA中看到的表
c = str.maketrans(string1,string2)
print(str1.translate(c))#只进行换表

print(base64.b64decode(str1.translate(str.maketrans(string1,string2))))#附带解密
#159e34224c00ead2d3a039d32084ee50

Block

不会

easyVM

进来首先是定义了opcode

然后就是一个为while循环来遍历opcode 然后执行代码:

+=

-=

^

主力逻辑不算难,因为大概能猜。主要就是opcde坑人,需要你在动调调试的时候去弄。它和那个不是一一对应的。

image-20231116190337745

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
opcode = [0x04, 0x0f, 0x31, 0x05, 0x03, 0x95, 0x04, 0x02, 0x59, 0x05, 0x16, 0xf5, 0x01, 0x15, 0x22, 0x01,
0x00, 0x8b, 0x05, 0x14, 0x40, 0x01, 0x0f, 0xf7, 0x04, 0x00, 0x92, 0x05, 0x0e, 0x7c, 0x04, 0x08,
0x21, 0x05, 0x02, 0xd2, 0x01, 0x1e, 0x3d, 0x01, 0x1b, 0xeb, 0x04, 0x0a, 0x27, 0x01, 0x14, 0x04,
0x01, 0x08, 0x10, 0x04, 0x10, 0x92, 0x04, 0x14, 0x59, 0x04, 0x00, 0xec, 0x01, 0x16, 0x50, 0x04,
0x15, 0xc3, 0x04, 0x06, 0xe4, 0x05, 0x03, 0xc6, 0x01, 0x00, 0x05, 0x05, 0x04, 0x03, 0x04, 0x04,
0xa9, 0x05, 0x05, 0xe6, 0x05, 0x17, 0xad, 0x04, 0x12, 0xe4, 0x05, 0x15, 0x0a, 0x05, 0x0a, 0x33,
0x01, 0x02, 0x1e, 0x05, 0x1b, 0x22, 0x01, 0x19, 0xf0, 0x01, 0x19, 0xe7, 0x04, 0x1d, 0xba, 0x05,
0x0d, 0x01, 0x05, 0x0b, 0x20, 0x05, 0x0b, 0x84, 0x01, 0x10, 0xd9, 0x01, 0x17, 0xe5, 0x01, 0x17,
0xbe, 0x04, 0x18, 0x19, 0x04, 0x0d, 0x72, 0x04, 0x13, 0x32, 0x05, 0x1e, 0x21, 0x04, 0x1e, 0xb6,
0x04, 0x0c, 0x0c, 0x01, 0x10, 0x65, 0x05, 0x08, 0xd9, 0x04, 0x13, 0x2d, 0x01, 0x0a, 0xe4, 0x01,
0x04, 0x73, 0x05, 0x09, 0xfe, 0x05, 0x0d, 0x0a, 0x04, 0x1f, 0x5f, 0x01, 0x11, 0x61, 0x01, 0x18,
0xbb, 0x04, 0x0e, 0xd4, 0x04, 0x1f, 0xb2, 0x01, 0x17, 0x24, 0x01, 0x0c, 0x19, 0x04, 0x15, 0x84,
0x05, 0x15, 0xce, 0x01, 0x1a, 0xbb, 0x04, 0x18, 0x0f, 0x05, 0x02, 0x45, 0x04, 0x1b, 0x91, 0x04,
0x14, 0x89, 0x01, 0x08, 0xca, 0x05, 0x09, 0x6e, 0x05, 0x1c, 0x2b, 0x01, 0x1e, 0xf7, 0x05, 0x1d,
0x39, 0x01, 0x1a, 0xbc, 0x05, 0x0e, 0xcd, 0x05, 0x1a, 0x4a, 0x04, 0x06, 0xdc, 0x05, 0x10, 0xd3,
0x04, 0x0b, 0x98, 0x01, 0x04, 0xc1, 0x01, 0x00, 0xce, 0x01, 0x18, 0xf7, 0x04, 0x0f, 0xc4, 0x05,
0x19, 0xf2, 0x04, 0x0f, 0x0f, 0x01, 0x04, 0x06, 0x01, 0x17, 0x0f, 0x05, 0x07, 0x65, 0x05, 0x1d,
0x16, 0x04, 0x10, 0xb9, 0x05, 0x18, 0x68, 0x01, 0x17, 0x71, 0x01, 0x13, 0x96, 0x01, 0x13, 0x1b,
0x04, 0x1d, 0xdc, 0x04, 0x18, 0x57, 0x01, 0x17, 0x8f, 0x05, 0x09, 0x49, 0x04, 0x06, 0xc0, 0x01,
0x0d, 0x9c, 0x01, 0x05, 0x97, 0x04, 0x00, 0x6b, 0x01, 0x1e, 0x1f, 0x04, 0x19, 0xab, 0x04, 0x10,
0x6a, 0x05, 0x01, 0xf1, 0x05, 0x1b, 0x65, 0x05, 0x09, 0xaa, 0x01, 0x1b, 0xb0, 0x04, 0x01, 0x12,
0x04, 0x1c, 0x4c, 0x01, 0x02, 0x9b, 0x05, 0x13, 0x0e, 0x01, 0x08, 0x82, 0x01, 0x1e, 0x07, 0x04,
0x0c, 0xb7, 0x05, 0x10, 0x6f, 0x04, 0x00, 0x72, 0x01, 0x1f, 0xad, 0x01, 0x1e, 0x07, 0x05, 0x0d,
0x92, 0x04, 0x01, 0xcd, 0x04, 0x18, 0xe8, 0x01, 0x0b, 0x43, 0x01, 0x04, 0xd7, 0x04, 0x1c, 0xb0,
0x76, 0x81, 0x1d, 0x6e, 0xad, 0x23, 0xd5, 0x63, 0xc8, 0xfe, 0x2d, 0x00, 0x3e, 0x1c, 0x1f, 0x01,
0x01, 0x00, 0x00, 0x00, 0x58, 0xe7, 0x76, 0x00, 0xa8, 0xf7, 0x76, 0x00, 0xe5, 0x23, 0xd5, 0x63,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xfd, 0x7e, 0x00, 0x70, 0xaa, 0x8d,
0x01, 0x00, 0x00, 0x00, 0xe2, 0x8e, 0xa7, 0x00, 0x94, 0xfe, 0x2d, 0x00, 0x1c, 0x53, 0x7f, 0xee,
0x04, 0xff, 0x2d, 0x00, 0x05, 0x24, 0x1f, 0x01, 0x35, 0xe1, 0xe7, 0x62, 0x00, 0x00, 0x00, 0x00,
0xd4, 0xfe, 0x2d, 0x00, 0x3d, 0x34, 0x37, 0x75, 0x00, 0xe0, 0xfd, 0x7e, 0x14, 0xff, 0x2d, 0x00,
0x02, 0x98, 0x77, 0x77, 0x00, 0xe0, 0xfd, 0x7e, 0xf7, 0x5b, 0x81, 0x77, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xfd, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7c, 0x5b, 0x77,
0x00, 0x00, 0x00, 0x00, 0xe0, 0xfe, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xcd, 0x4d, 0x7b, 0x77, 0xa3, 0x62, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0xff, 0x2d, 0x00,
0xd5, 0x97, 0x77, 0x77, 0xc6, 0x1c, 0x1f, 0x01]
pos=1

while True:
while True:
while opcode[pos-1]==1:
print("flag[",opcode[pos],"]+=",opcode[pos+1])
pos+=3
if opcode[pos-1]!=4:
break
print("flag[", opcode[pos], "]-=",opcode[pos + 1])
pos += 3
if opcode[pos-1]!=5:
break
print("flag[", opcode[pos], "]^=",opcode[pos + 1])
pos += 3

最后借用了一点点网上的Wp 然后写了代码:

输出:

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
flag[ 15 ]-= 49
flag[ 3 ]^= 149
flag[ 2 ]-= 89
flag[ 22 ]^= 245
flag[ 21 ]+= 34
flag[ 0 ]+= 139
flag[ 20 ]^= 64
flag[ 15 ]+= 247
flag[ 0 ]-= 146
flag[ 14 ]^= 124
flag[ 8 ]-= 33
flag[ 2 ]^= 210
flag[ 30 ]+= 61
flag[ 27 ]+= 235
flag[ 10 ]-= 39
flag[ 20 ]+= 4
flag[ 8 ]+= 16
flag[ 16 ]-= 146
flag[ 20 ]-= 89
flag[ 0 ]-= 236
flag[ 22 ]+= 80
flag[ 21 ]-= 195
flag[ 6 ]-= 228
flag[ 3 ]^= 198
flag[ 0 ]+= 5
flag[ 4 ]^= 3
flag[ 4 ]-= 169
flag[ 5 ]^= 230
flag[ 23 ]^= 173
flag[ 18 ]-= 228
flag[ 21 ]^= 10
flag[ 10 ]^= 51
flag[ 2 ]+= 30
flag[ 27 ]^= 34
flag[ 25 ]+= 240
flag[ 25 ]+= 231
flag[ 29 ]-= 186
flag[ 13 ]^= 1
flag[ 11 ]^= 32
flag[ 11 ]^= 132
flag[ 16 ]+= 217
flag[ 23 ]+= 229
flag[ 23 ]+= 190
flag[ 24 ]-= 25
flag[ 13 ]-= 114
flag[ 19 ]-= 50
flag[ 30 ]^= 33
flag[ 30 ]-= 182
flag[ 12 ]-= 12
flag[ 16 ]+= 101
flag[ 8 ]^= 217
flag[ 19 ]-= 45
flag[ 10 ]+= 228
flag[ 4 ]+= 115
flag[ 9 ]^= 254
flag[ 13 ]^= 10
flag[ 31 ]-= 95
flag[ 17 ]+= 97
flag[ 24 ]+= 187
flag[ 14 ]-= 212
flag[ 31 ]-= 178
flag[ 23 ]+= 36
flag[ 12 ]+= 25
flag[ 21 ]-= 132
flag[ 21 ]^= 206
flag[ 26 ]+= 187
flag[ 24 ]-= 15
flag[ 2 ]^= 69
flag[ 27 ]-= 145
flag[ 20 ]-= 137
flag[ 8 ]+= 202
flag[ 9 ]^= 110
flag[ 28 ]^= 43
flag[ 30 ]+= 247
flag[ 29 ]^= 57
flag[ 26 ]+= 188
flag[ 14 ]^= 205
flag[ 26 ]^= 74
flag[ 6 ]-= 220
flag[ 16 ]^= 211
flag[ 11 ]-= 152
flag[ 4 ]+= 193
flag[ 0 ]+= 206
flag[ 24 ]+= 247
flag[ 15 ]-= 196
flag[ 25 ]^= 242
flag[ 15 ]-= 15
flag[ 4 ]+= 6
flag[ 23 ]+= 15
flag[ 7 ]^= 101
flag[ 29 ]^= 22
flag[ 16 ]-= 185
flag[ 24 ]^= 104
flag[ 23 ]+= 113
flag[ 19 ]+= 150
flag[ 19 ]+= 27
flag[ 29 ]-= 220
flag[ 24 ]-= 87
flag[ 23 ]+= 143
flag[ 9 ]^= 73
flag[ 6 ]-= 192
flag[ 13 ]+= 156
flag[ 5 ]+= 151
flag[ 0 ]-= 107
flag[ 30 ]+= 31
flag[ 25 ]-= 171
flag[ 16 ]-= 106
flag[ 1 ]^= 241
flag[ 27 ]^= 101
flag[ 9 ]^= 170
flag[ 27 ]+= 176
flag[ 1 ]-= 18
flag[ 28 ]-= 76
flag[ 2 ]+= 155
flag[ 19 ]^= 14
flag[ 8 ]+= 130
flag[ 30 ]+= 7
flag[ 12 ]-= 183
flag[ 16 ]^= 111
flag[ 0 ]-= 114
flag[ 31 ]+= 173
flag[ 30 ]+= 7
flag[ 13 ]^= 146
flag[ 1 ]-= 205
flag[ 24 ]-= 232
flag[ 11 ]+= 67
flag[ 4 ]+= 215
flag[ 28 ]-= 176

最后flag进行比较

所以我们逆向:

需要倒叙,+变成- ;-变成+

ezbase

最后是Str1和Str2比较

image-20231116194413546

我们这里动态调试得到Str2的值

image-20231116194534699

1
2
3
4
5
6
7
8
9
flag = [0x5A, 0x6D, 0x78, 0x68, 0x5A, 0x33, 0x73, 0x7A, 0x4E, 0x48,
0x42, 0x34, 0x62, 0x7A, 0x6C, 0x56, 0x63, 0x31, 0x5A, 0x72,
0x52, 0x46, 0x64, 0x53, 0x54, 0x6E, 0x55, 0x31, 0x57, 0x46,
0x52, 0x44, 0x57, 0x46, 0x64, 0x31, 0x54, 0x48, 0x45, 0x7A,
0x51, 0x6C, 0x46, 0x46, 0x62, 0x54, 0x46, 0x72, 0x64, 0x33,
0x70, 0x76, 0x66, 0x51, 0x3D]
for i in flag:
print(chr(i),end="")
#ZmxhZ3szNHB4bzlVc1ZrRFdSTnU1WFRDWFd1THEzQlFFbTFrd3pvfQ=

base64解码:

image-20231116194600164

final

混淆,可以先看看:

https://firmianay.gitbooks.io/ctf-all-in-one/content/doc/3.2.6_instruction_confusion.html

这个题,进来就是一直跳跳跳,并且还不是jmp的跳转,是ret的跳转,我晕。

他这种调过来跳过去的不影响程序的运行但是妨碍了我们逆向来看,就是代码混淆。

这里简单的看看:

image-20231116202324844

image-20231116202352822

他每跳一下就进行一点点操作。【在我看来】

因为上面的网址说了

1
jmp {label}

可以变成

1
2
push {label}
ret

这里我们尝试将跳转该回去用jmp

1
2
3
4
JMP 的 3 种类型
短跳转(Short Jmp,只能跳转到256字节的范围内),对应机器码:EB
近跳转(Near Jmp,可跳至同一段范围内的地址),对应机器码:E9
远跳转(Far Jmp,可跳至任意地址),对应机器码: EA

尝试着用:最后EA可以

所以我们使用EA

image-20231116202629972

代码混淆的都在easy里面

然后都是68 ????C3 ==>EA ????00

这里以至于为什么是使用00 而不是90 【nop】。我也不清楚

我们用IDApython来实现【因为太多了】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import idaapi

def main():
start_addr = 0x00406000 # 起始地址
end_addr = 0x00406959 # 结束地址

while start_addr < end_addr:
# 查找指定模式的字节序列
if idaapi.get_byte(start_addr) == 0x68 and idaapi.get_byte(start_addr + 5) == 0xC3:
# 替换字节
idaapi.patch_byte(start_addr, 0xEA)
idaapi.patch_byte(start_addr + 5, 0x00)
start_addr += 6 # 移动到下一个字节
continue

start_addr += 1 # 继续搜索下一个字节

print("OK")
print("哈哈哈哈")

# 调用主函数
if __name__ == "__main__":
main()

然后就能F5了

OK算法对我来说也好难…

SigninReverse

用IDA打开就是flag

simple_flower

进来main函数

image-20231120163610182

报红

跟进push指令、

image-20231120163734655

看到一堆的push pop 没有啥用,就不管了

然后下面有一个call $+5

这句话啥意思不懂。我们就chat一下:

image-20231120163501525

可以理解到’$’的意思就是获取当前指令在内存中的位置。

对于call 指令我的理解就是call 一个地址。然后就去调用这个地址上的函数。

所以我们就能得到对应的call指令还会讲call指令的下一条指令的地址push到堆栈里面,以至于可以pop 出来返回到主函数。

然后我们在来看:题目中是call $+5。但是对于call指令来说,它本身就是要占用5个字节的。所以这里的call $ + 5 我感觉意义不大,其实就是去执行后面的句子。没有进行跳转,但是它又会push一个地址到堆栈中,在后面的ret的时候又会返回来

但是这个时候我们去看call 和 ret 指令中间代码:

image-20231120171136291

有点点豁然开朗的感觉,感觉中间的代码基本都没有任何意义。

所以我们就把中间的全部给Nop掉

image-20231121152254185

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
import idaapi

def main():
from_addr = 0x00407000 # 起始地址
end_addr = 0x0040F201 # 结束地址
size = end_addr - from_addr # 扫描数据块大小

i = 0
while i < size:
# 查找 EB 03 C3 CD 03 ,替换为 90
# jmp retn db
if idaapi.get_byte(from_addr) == 0xEB and idaapi.get_byte(from_addr + 1) == 0x03 and idaapi.get_byte(from_addr + 2) == 0xC3 \
and idaapi.get_byte(from_addr + 3) == 0xCD and idaapi.get_byte(from_addr + 4) == 0x03:
for j in range(5):
idaapi.patch_byte(from_addr, 0x90)
from_addr += 1
continue

# 查找 E8 01 00 00 00 E9 ,替换为 90
if idaapi.get_byte(from_addr) == 0xE8 and idaapi.get_byte(from_addr + 1) == 0x01 and idaapi.get_byte(from_addr + 2) == 0x00 \
and idaapi.get_byte(from_addr + 3) == 0x00 and idaapi.get_byte(from_addr + 4) == 0x00 and idaapi.get_byte(from_addr + 5) == 0xE9:
for j in range(12):
idaapi.patch_byte(from_addr, 0x90)
from_addr += 1
continue

# 查找 E8 00 00 00 00 call $+5,替换为 90
#将call 和 ret 之间的内容全部nop掉
if idaapi.get_byte(from_addr) == 0xE8 and idaapi.get_byte(from_addr + 1) == 0x00 and idaapi.get_byte(from_addr + 2) == 0x00 \
and idaapi.get_byte(from_addr + 3) == 0x00 and idaapi.get_byte(from_addr + 4) == 0x00:
for j in range(17):
idaapi.patch_byte(from_addr, 0x90)
from_addr += 1
continue

from_addr += 1
i += 1

print("\nOK")


# 调用主函数
if __name__ == "__main__":
main()

选中整个区域重新分析一下然后打包成函数:

如何选中这么大一篇的范围呢?

首先找到你要重新分析开始的位置:“ALT+L”

然后用鼠标点击你选中的位置的末尾就可以了

image-20231121142714144

得到一个这样的F5后的。

因为之前知道有很多push pop 都是没有什么作用的,所以我们尝试将他也全部nop掉

我去nop掉后发现好像没啥变化,不知道是我的问题还是本身就不会发生变化。。。

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
import idaapi

#批量修改机器码,有范围,有查找的内容和替换的内容
def main():
start_addr = 0x00407000 # 起始地址
end_addr = 0x0040F201 # 结束地址

while start_addr < end_addr:
# 查找指定模式的字节序列
if idaapi.get_byte(start_addr) == 0x50 and idaapi.get_byte(start_addr + 1) == 0x51 and idaapi.get_byte(start_addr + 2) == 0x58 and idaapi.get_byte(start_addr + 3) == 0x59:
# 替换字节
for j in range(4):
idaapi.patch_byte(start_addr, 0x90)
start_addr += 1
continue

if idaapi.get_byte(start_addr) == 0x51 and idaapi.get_byte(start_addr + 1) ==0x59:
# 替换字节
for j in range(2):
idaapi.patch_byte(start_addr, 0x90)
start_addr += 1
continue
if idaapi.get_byte(start_addr) == 0x50 and idaapi.get_byte(start_addr + 1) ==0x58:
# 替换字节
for j in range(2):
idaapi.patch_byte(start_addr, 0x90)
start_addr += 1
continue

start_addr += 1 # 继续搜索下一个字节

print("OK")
print("哈哈哈哈")


# 调用主函数
if __name__ == "__main__":
main()

虽然我上面这个代码第一段的nop掉4个但看有点点问题,因为它本身是实现了一个mov eax ,ecx。但是它交换了偶数次就不影响了。

但是我反编译出来的东西还是非常的难懂。。

可能是我弄错了吧。

这里就用大佬的IDC脚本吧

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
#include <idc.idc>

static main()
{
auto i,j,from,size;
from=0x00407000; //起始地址
size=0x0040F201-0x00407000;//扫描数据块大小

for ( i=0; i < size;i++ ) {

//查找 EB 03 C3 CD 03 ,替换90
if ((Byte(from)==0xeB)&&(Byte(from+1)==0x03)&&(Byte(from+2)==0xC3)&&(Byte(from+3)==0xCD)&&(Byte(from+4)==0x03))
{
for(j=0;j<5;j++)
{
PatchByte(from,0x90);
from++;
}
continue;
}

//查找 E8 01 00 00 00 E9 ,替换90
if ((Byte(from)==0xe8)&&(Byte(from+1)==0x01)&&(Byte(from+2)==0x00)&&(Byte(from+3)==0x00)&&(Byte(from+4)==0x00)&&(Byte(from+5)==0xE9))
{
for(j=0;j<12;j++)
{
PatchByte(from,0x90);
from++;
}
continue;
}
//查找 E8 00 00 00 00 call $+5,替换90
if ((Byte(from)==0xe8)&&(Byte(from+1)==0x00)&&(Byte(from+2)==0x00)&&(Byte(from+3)==0x00)&&(Byte(from+4)==0x00))
{
for(j=0;j<17;j++)
{
PatchByte(from,0x90);
from++;
}
continue;
}
//----------------------
//上面的是之前修改过的
//查找 51 b9 01 00 00 00 9c call $+5,替换90
//下面的第一张图
if ((Byte(from)==0x51)&&(Byte(from+1)==0xb9)&&(Byte(from+2)==0x01)&&(Byte(from+3)==0x00)&&(Byte(from+4)==0x00)&&(Byte(from+5)==0x00)&&(Byte(from+6)==0x9c))
{
for(j=0;j<21;j++)
{
PatchByte(from,0x90);
from++;
}
continue;
}
//下面的第二种图
if ((Byte(from)==0x50)&&(Byte(from+1)==0xb8)&&(Byte(from+2)==0x02)&&(Byte(from+3)==0x02)&&(Byte(from+4)==0x00)&&(Byte(from+5)==0x00)&&(Byte(from+6)==0x9c))
{
for(j=0;j<21;j++)
{
PatchByte(from,0x90);
from++;
}
continue;
}
if ((Byte(from)==0x9c)&&(Byte(from+1)==0x51)&&(Byte(from+2)==0x33)&&(Byte(from+3)==0xc1)&&(Byte(from+4)==0x33)&&(Byte(from+5)==0xc8)&&(Byte(from+6)==0x33))
{
for(j=0;j<11;j++)
{
PatchByte(from,0x90);
from++;
}
continue;
}

if ((Byte(from)==0x9d)&&(Byte(from+1)==0x50)&&(Byte(from+2)==0x58)&&(Byte(from+3)==0x52)&&(Byte(from+4)==0x5a)&&(Byte(from+5)==0x9c))
{
for(j=0;j<6;j++)
{
PatchByte(from,0x90);
from++;
}
continue;
}

if ((Byte(from)==0x53)&&(Byte(from+1)==0x5b)&&(Byte(from+2)==0x31)&&(Byte(from+3)==0xc0)&&(Byte(from+4)==0x51)&&(Byte(from+5)==0x59))
{
for(j=0;j<6;j++)
{
PatchByte(from,0x90);
from++;
}
continue;
}
//中间这一段看样子是
//------
// 去除冗余指令
//去除的 push pop
if ((Byte(from)==0x51)&&(Byte(from+1)==0x59))
{
for(j=0;j<2;j++)
{
PatchByte(from,0x90);
from++;
}
continue;
}
// 去除冗余指令
//去除的 push pop
if ((Byte(from)==0x53)&&(Byte(from+1)==0x5b))
{
for(j=0;j<2;j++)
{
PatchByte(from,0x90);
from++;
}
continue;
}
// 去除冗余指令
//去除的 push pop
if ((Byte(from)==0x52)&&(Byte(from+1)==0x5a))
{
for(j=0;j<2;j++)
{
PatchByte(from,0x90);
from++;
}
continue;
}

// 去除冗余指令
//去除的 push pop
if ((Byte(from)==0x50)&&(Byte(from+1)==0x58))
{
for(j=0;j<2;j++)
{
PatchByte(from,0x90);
from++;
}
continue;
}
// 去除冗余指令
//去除的push push pop pop
if ((Byte(from)==0x50)&&(Byte(from+1)==0x51)&&(Byte(from+2)==0x58)&&(Byte(from+3)==0x59))
{
for(j=0;j<4;j++)
{
PatchByte(from,0x90);
from++;
}
continue;
}


// 去除pushf popf
if ((Byte(from)==0x9c)||(Byte(from)==0x9d))
{
for(j=0;j<1;j++)
{
PatchByte(from,0x90);
from++;
}
continue;
}


from++;
}
Message("\n" + "OK\n");
}

最后就呈现出来的函数:

看起来就好了很多。

image-20231121150017122

这里我们重新来看看它去除冗余指令

image-20231121153645618

image-20231121154459638

好吧最后我屈服了,不想看了:

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
veryEasy:004094C4 51                            push    ecx
veryEasy:004094C5 B9 01 00 00 00 mov ecx, 1
veryEasy:004094CA 9C pushf
veryEasy:004094CB C1 E9 06 shr ecx, 6
veryEasy:004094CE 83 F1 01 xor ecx, 1
veryEasy:004094D1 83 C9 08 or ecx, 8
veryEasy:004094D4 59 pop ecx
veryEasy:004094D5 87 0C 24 xchg ecx, [esp+0E0h+pos]
veryEasy:004094D8 9D popf

veryEasy:004094D9 51 push ecx
veryEasy:004094DA B9 01 00 00 00 mov ecx, 1
veryEasy:004094DF 9C pushf
veryEasy:004094E0 C1 E9 06 shr ecx, 6
veryEasy:004094E3 83 F1 01 xor ecx, 1
veryEasy:004094E6 83 C9 08 or ecx, 8
veryEasy:004094E9 59 pop ecx
veryEasy:004094EA 87 0C 24 xchg ecx, [esp+0E0h+pos]
veryEasy:004094ED 9D popf


veryEasy:00407012 50 push eax
veryEasy:00407013 B8 02 02 00 00 mov eax, 202h
veryEasy:00407018 9C pushf
veryEasy:00407019 C1 E8 06 shr eax, 6
veryEasy:0040701C 83 F0 01 xor eax, 1
veryEasy:0040701F 83 C8 03 or eax, 3
veryEasy:00407022 58 pop eax
veryEasy:00407023 87 04 24 xchg eax, [esp+4+var_4]
veryEasy:00407026 9D

v778 = __readeflags();
__writeeflags(v778);

veryEasy:0040D9B7 9C pushf
veryEasy:0040D9B8 51 push ecx
veryEasy:0040D9B9 33 C1 xor eax, ecx
veryEasy:0040D9BB 33 C8 xor ecx, eax
veryEasy:0040D9BD 33 C1 xor eax, ecx
veryEasy:0040D9BF 91 xchg eax, ecx
veryEasy:0040D9C0 59 pop ecx
veryEasy:0040D9C1 9D popf

veryEasy:0040D9C2 9C pushf
veryEasy:0040D9C3 51 push ecx
veryEasy:0040D9C4 33 C1 xor eax, ecx
veryEasy:0040D9C6 33 C8 xor ecx, eax
veryEasy:0040D9C8 33 C1 xor eax, ecx
veryEasy:0040D9CA 91 xchg eax, ecx
veryEasy:0040D9CB 59 pop ecx
veryEasy:0040D9CC 9D popf
veryEasy:0040D9CD 9C pushf


veryEasy:0040B98D 9D popf
veryEasy:0040B98E 50 push eax
veryEasy:0040B98F 58 pop eax
veryEasy:0040B990 52 push edx
veryEasy:0040B991 5A pop edx
veryEasy:0040B992 9C pushf

veryEasy:0040BADE 53 push ebx
veryEasy:0040BADF 5B pop ebx
veryEasy:0040BAE0 31 C0 xor eax, eax
veryEasy:0040BAE2 51 push ecx
veryEasy:0040BAE3 59 pop ecx


veryEasy:004082AC 50 push eax
veryEasy:004082AD 51 push ecx
veryEasy:004082AE 58 pop eax
veryEasy:004082AF 59 pop ecx
veryEasy:004082B0 50 push eax
veryEasy:004082B1 51 push ecx
veryEasy:004082B2 58 pop eax
veryEasy:004082B3 59 pop ecx

最后放上大佬分析的内容。以上的内容都是没有作用的全部NOP掉就好了。

。。真的会又程序这么多的没有用的代码吗》。