羊城杯 re wp

题的质量还是可以,有些题因为遇到一些问题,没解出来。花时间来写wp一是巩固一些知识点,还有让更多的人可以互相学习。

BabySmc

看题目就知道代码肯定被smc处理过了,所以直接动调就ok,也没有反调试。

先看前面部分。

看看base64加密过程

密文和比较。

解密脚本

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

import base64

t=[]
encstr = 'H>oQn6aqLr{DH6odhdm0dMe`MBo?lRglHtGPOdobDlknejmGI|ghDb<4'
xor = [0xa6, 0xa3, 0xa9, 0xac]
for i in range(len(encstr)):
t.append(ord(encstr[i]) ^ xor[i % 4])
t[-1]=0xE4#由于最后一个是4,是补的,直接改为表中的一个就行。
base1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

base = [0xE4, 0xC4, 0xE7, 0xC7, 0xE6, 0xC6, 0xE1, 0xC1, 0xE0, 0xC0,
0xE3, 0xC3, 0xE2, 0xC2, 0xED, 0xCD, 0xEC, 0xCC, 0xEF, 0xCF,
0xEE, 0xCE, 0xE9, 0xC9, 0xE8, 0xC8, 0xEB, 0xCB, 0xEA, 0xCA,
0xF5, 0xD5, 0xF4, 0xD4, 0xF7, 0xD7, 0xF6, 0xD6, 0xF1, 0xD1,
0xF0, 0xD0, 0xF3, 0xD3, 0xF2, 0xD2, 0xFD, 0xDD, 0xFC, 0xDC,
0xFF, 0xDF, 0x95, 0x9C, 0x9D, 0x92, 0x93, 0x90, 0x91, 0x96,
0x97, 0x94, 0x8A, 0x8E]
ans = ''
for i in t:
ans += base1[base.index(i)]
print(ans)
print(base64.b64decode(ans))
#SangFor{XSAYT0u5DQhaxveIR50X1U13M-pZK5A0}

DeltX

这道题,流程很乱,通过动调看内存会使分析变的简单。但是也有坑,就是flag的大小写的问题,多试吧。

前面部分。

中间数据处理。

脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

#include<stdio.h>

int main()
{
int a,b;

for(a=0;a<=0xffff;a++)
{
b=0;
b=(a-0x9393)&0xffff;
if(a*b== 0xE5FD104)
{
printf("%X %X",a,b);

}
}
}

解出所有数据,拼接起来得到,SangFor{2C7BD2BF862564BAED0B6B6EA94F15BC},但是不对,然后又一组一组的试,看看哪出了问题,发现是某一组大小写问题,得到SangFor{2C7BD2BF862564baED0B6B6EA94F15BC}

EasyVM

elf文件,代码也被加密了,也有自解密函数。

先看看main函数

然后vm内部就只有自己去慢慢调试分析大概逻辑了。

大概有3中方式加密,前32个字符是异或,然后后面4个是一些运算的加密,后面8个字符又分为两组进行同一种运算方式方式加密。

写了个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
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

#include<stdio.h>

int main()
{
int 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};
int i=0;
while ( 1 )
{
if ( opcode[i] == 0x71 )
{
printf("table[6] -= 4\n");
printf("*table[6] = 0x%x\n",opcode[i+1]);
i += 5;
}
if ( opcode[i] == 0x41 )
{
printf("table[1] += table[2]\n");
++i;
}
if ( opcode[i] == 0x42 )
{
printf("table[1] -= table[4];\n");
++i;
}
if ( opcode[i] == 0x43 )
{
printf("table[1] *= table[3];\n");
++i;
}
if ( opcode[i] == 0x37 )
{

printf("table[1] = table[5];\n");
++i;
}
if ( opcode[i] == 0x38 )
{
printf("table[1] ^= table[4];\n");
++i;
}
if ( opcode[i] == 0x39 )
{
printf("table[1] ^= table[5];\n");
++i;
}
if ( opcode[i] == 0x35 )
{
printf("table[5] = table[1];\n");
++i;
}
if ( opcode[i] == 0xF7 )
{
printf("table[9] += table[1];\n");
++i;
}
if ( opcode[i] == 0x44 )
{
printf("table[1] /= table[5];\n");
++i;
}
if ( opcode[i] == 0x80 )
{
printf("table[2] = 0x%x\n",*((unsigned int*)(&opcode[i+2])));
i += 6;
}
if ( opcode[i] == 0x77 )
{
printf("table[1] ^= table[9];\n");
++i;
}
if ( opcode[i] == 0x53 )
{
printf("(sub_8048580)(*table[3]);\n");
i += 2;
}
if ( opcode[i] == 0x22 )
{
printf("table[1] >>= table[2];\n");
++i;
}
if ( opcode[i] == 0x23 )
{
printf("table[1] <<= table[2];\n");
++i;
}
if ( opcode[i] == 0x99 )
{
printf("out\n");
break;
}

if ( opcode[i] == 0x76 )
{
printf("table[3] = *table[6];\n");
printf("*table[6] = 0;\n");
printf("table[6] += 4;\n");
i += 5;
}
if ( opcode[i] == 0x54 )
{
printf("v6 = table[3];\n");
printf("*v6 = sub_8048520();\n");
i += 2;
}
if ( opcode[i] == 0x30 )
{
printf("table[1] |= table[2];\n");
++i;
}
if ( opcode[i] == 0x31 )
{
printf("table[1] &= table[2];\n");
++i;
}
if ( opcode[i] == 0x32 )
{
printf("table[3] = 0x%x\n",opcode[i+1]) ;
i += 2;
}
if ( opcode[i] == 9 )
{
printf("table[1] = 1877735783;\n");
++i;
}
if ( opcode[i] == 0x10 )
{
printf("table[9] = table[1];\n");
++i;
}
if ( opcode[i] == 0x33 )
{
printf("table[4] = table[1]\n");
++i;
}
if ( opcode[i] == 0x34 )
{
printf("table[2] = 0x%x;",opcode[i+1]);
i += 2;
}
if ( opcode[i] == 0xFE )
{
printf("table[1] = table[9];\n");
++i;
}
if ( opcode[i] == 0x11 )
{
printf("(sub_8048510)(&unk_8049340, table[1])\n");
++i;
}
if ( opcode[i] == 0xA0 )
{
printf("if ( table[1] != 1877735783 )\nexit\n\n");
++i;
}
if ( opcode[i] == 0xA1 )
{
printf("read\n");
++i;
}
if ( opcode[i] == 0xB1 )
{
printf("table[9] = xor[0]\n");
++i;
}
if ( opcode[i] == 0xB2 )
{
printf("table[9] = xor[1];\n");
++i;
}
if ( opcode[i] == 0xA4 )
{
printf("xor[*(table[8] + 1)] = table[1];\n");
i += 4;
}
if ( opcode[i] == 0xB3 )
{
printf("table[9] = xor[2];\n");
++i;
}
if ( opcode[i] == 0xB4 )
{
printf("table[9] = xor[3];\n");
++i;
}
if ( opcode[i] == 0xC1 )
{
printf("table[1] = flag[%d];\n",opcode[i+1]);
i += 2;
}
if ( opcode[i] == 0xC7 )
{
printf("dword_804B060 != table[1]\n\n");
++i;
}
if ( opcode[i] == 0xC8 )
{
printf("dword_804B064 != table[1]\n\n");
++i;
}
if ( opcode[i] == 0xC2 )
{
printf("if ( %d != table[1] )\n\n",opcode[i+1]);
i+= 5;
}
}
}

前面32个字符如下结构,就是一个异或

1
2
3
4
5

table[1] = flag[0];
table[9] = xor[0]
table[1] ^= table[9];
if ( 74 != table[1] )
1
2
3
4
5
6
7
8
9
10
11
12
13
14

#里面的数据都是从opcode提出来的。
index=[0xb1,0xb2,0xb4,0xb3,0xb2,0xb4,0xb1,0xb3,0xb1,0xb1,0xb3,0xb3,0xb4,0xb2,0xb3,0xb1,0xb3,0xb3,0xb2,0xb1,0xb3,0xb1,0xb3,0xb4,0xb1,0xb4,0xb1,0xb3,0xb2,0xb3,0xb1,0xb2]
table={0xb1:0x7b,0xb2:0x2f,0xb3:0x37,0xb4:0xe8}

xor=[]
for i in index:
xor.append(table[i])
print(xor)
enc=[0x4a,0x19,0xdd,0xf,0x1b,0x89,0x19,0x54,0x4f,0x4e,0x55,0x56,0x8e,0x49,0xe,0x4b,0x6,0x54,0x1a,0x42,0x53,0x1f,0x52,0xdb,0x19,0xd9,0x19,0x55,0x19,0x0,0x4b,0x1e]
for i in range(len(enc)):
print(chr(enc[i]^xor[i]),end='')
#16584abc45baff901c59dde3b1bb6701

后4个字符逻辑如下

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

table[1] = flag[32];
table[2] = 0x18
table[1] <<= table[2];
table[9] = table[1];
table[1] = flag[33];
table[2] = 0x10
table[1] <<= table[2];
table[9] += table[1];
table[1] = flag[34];
table[2] = 0x8
table[1] <<= table[2];
table[9] += table[1];
table[1] = flag[35];
table[9] += table[1];
table[1] = table[9];
table[2] = 0x5
table[1] >>= table[2];
table[1] ^= table[9];
table[9] = table[1];
table[2] = 0x7
table[1] <<= table[2];
table[2] = 0x98f17723
table[1] &= table[2];
table[1] ^= table[9];
table[9] = table[1];
table[2] = 0x18
table[1] <<= table[2];
table[2] = 0x35e4b920
table[1] &= table[2];
table[1] ^= table[9];
table[9] = table[1];
table[2] = 0x12
table[1] >>= table[2];
table[1] ^= table[9];
if ( table[1] != 1877735783 )
exit

需要特别注意的是里面的0x80对应的指令,比赛时就是在这花了很多时间,还好一步步调,最后找到了。

解法可以考虑爆破,4个字符,也不是很多。

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

str="abcdefghijklmnopqrstuvwxyz0123456789"

for a in str:
for b in str:
for c in str:
for d in str:
table=[0]*10
table[1] = ord(a)
table[2] = 0x18
table[1] <<= table[2]
table[9] = table[1]
table[1] =ord(b)
table[2] = 0x10
table[1] <<= table[2]
table[9] += table[1]
table[1] = ord(c)
table[2] = 0x8
table[1] <<= table[2]
table[9] += table[1]
table[1] = ord(d)
table[9] = (table[9]+table[1])&0xffffffff

table[1] = table[9]
table[2] = 0x5
table[1] >>= table[2]
table[1] ^= table[9]
table[9] = table[1]
table[2] = 0x7
table[1] <<= table[2]
table[2] = 0x98f17723
table[1] &= table[2]
table[1] ^= table[9]
table[9] = table[1]
table[2] = 0x18
table[1] <<= table[2]
table[2] = 0x35e4b920
table[1] &= table[2]
table[1] ^= table[9]
table[9] = table[1]
table[2] = 0x12
table[1] >>= table[2]
table[1] ^= table[9]
if(table[1]&0xffffffff==1877735783):
print(a,b,c,d)
break
#a 2 5 4

后面8个字符,加密过程也有坑,就是*和<<会产生溢出。也是考虑爆破解。

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

str="abcdefghijklmnopqrstuvwxyz0123456789"

for a in str:
for b in str:
for c in str:
for d in str:
table=[0]*10
table[1] = ord(a)
table[2] = 0x18
table[1] <<= table[2]
table[9] = table[1]
table[1] =ord(b)
table[2] = 0x10
table[1] <<= table[2]
table[9] += table[1]
table[1] = ord(c)
table[2] = 0x8
table[1] <<= table[2]
table[9] += table[1]
table[1] = ord(d)
table[9] += table[1]

table[1] = table[9]
table[3] = 0x20
table[1] = (table[1] *table[3])&0xffffffff
table[4] = table[1]
table[1] ^= table[9]
table[2] = 0x11
table[1] >>= table[2]
table[5] = table[1]
table[1] = table[5]
table[1] ^= table[4]
table[1] ^= table[9]
table[2] = 0xd
table[1]= (table[1] <<table[2])&0xffffffff
table[1] ^= table[9]
table[1] ^= table[4]
table[1] ^= table[5]
table[9] = table[1]
table[3] = 0x20
table[1] = (table[1] *table[3])&0xffffffff
table[4] = table[1]
table[1] ^= table[9]
table[2] = 0x11
table[1] >>= table[2]
table[5] = table[1]
table[1] = table[5]
table[1] ^= table[4]
table[1] ^= table[9]
table[2] = 0xd
table[1] =(table[1] <<table[2])&0xffffffff
table[1] ^= table[9]
table[1] ^= table[4]
table[1] ^= table[5]

if(table[1]&0xffffffff==0x283B8E84):
print(a,b,c,d)
break
# table[1] = table[9]
# table[3] = 0x20
# table[1] *= table[3]
# table[4] = table[1]
# table[1] ^= table[9]
# table[2] = 0x11
# table[1] >>= table[2]
# table[5] = table[1]
# table[1] = table[5]
# table[1] ^= table[4]
# table[1] ^= table[9]
# table[2] = 0xd
# table[1] <<= table[2]
# table[1] ^= table[9]
# table[1] ^= table[4]
# table[1] ^= table[5]
# table[9] = table[1]
# table[3] = 0x20
# table[1] *= table[3]
# table[4] = table[1]
# table[1] ^= table[9]
# table[2] = 0x11
# table[1] >>= table[2]
# table[5] = table[1]
# table[1] = table[5]
# table[1] ^= table[4]
# table[1] ^= table[9]
# table[2] = 0xd
# table[1] <<= table[2]
# table[1] ^= table[9]
# table[1] ^= table[4]
# table[1] ^= table[5]
#b06c dc23

得到SangFor{16584abc45baff901c59dde3b1bb6701a254b06cdc23}

ez_android

对apk的分析确实比较少,有点可惜,当时不知道为什么md5去网上解,没解出来,看来得多用几个网站。

拖到jeb看流程。

去看md5解密,现在网站解密又可以解出来了。。。654321

看看key怎么生成的

得到key

去看加密encode函数。

解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

enc_md5 = bytearray.fromhex('c232666f1410b3f5010dc51cec341f58')
for i in enc_md5:
print(hex(i+1).replace("0x",''),end='')
print("\n")

import base64
base1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
t='3lkHi9iZNK87qw0p6U391t92qlC5rwn5iFqyMFDl1t92qUnL6FQjqln76l-P'
base = 'TGtUnkaJD0frq61uCQYw3-FxMiRvNOB/EWjgVcpKSzbs8yHZ257X9LldIeh4APom '
ans = ''
for i in t:
ans += base1[base.index(i)]
print(ans)
print(base64.b64decode(ans))
#c33367701511b4f62ec61ded352059
#SangFor{212f4548-03d1-11ec-ab68-00155db3a27e}

safe box

Debug Blocker,这种技术还可以用来hookAPI,还是挺有意思,逆向工程核心原理中也有讲解,之前mrctf也遇到过,流程分析起还是不难,就是解的时候总是各种细节问题。。。。,后面看了师傅的wp来看看出现的问题。

浏览过整体框架可以知道,需要输入3个password。

先看看第一个,太大了 爆出来要等太久,用z3确实会快很多。

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

from z3 import *
s = Solver()
Seed = BitVec('passwd', 64)
v2 = (Seed % 0x2540BE3FF)&0xff
v3 = ((Seed % 0x2540BE3FF) >> 8) & 0xF
v4 = ((Seed % 0x2540BE3FF) >> 20) & 0xFFF
v5 = v2 + 1
v6 = ((Seed % 0x2540BE3FF) >> 12)&0xff
v7 = v3 + 1
v8 = v4 + ~v2
v9 = v4
v10 = 21 * v6
for i in range(16):
v3 += v3 ^ v8
v2 += v4 | v2 & v7
v9 += (v10 + v9) % v5
v6 += v6 / v7

s.add(v3 == 0x38006F1)
s.add(v2 == 0x7291)
s.add(v9 == 0x8B3)
s.add(v6 == 0x80)
s.add(Seed > 0, Seed <= 0xffffffff)

if s.check() == sat:
print(s.model())
else:
print('Not Found!')
#0x72335f31
#r3_1

输入完password1后就会触发一个int3异常,动调看看,注意main函数中的IsDebuggerPresent(),断点打在sub_140001270()中,也就是程序自己的异常处理函数。

然后去新exe查看该函数,0014000187F处p键

所以password2就是10个字符分5组进行xtea加密,xtea解密如下

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

#include<stdio.h>

void decrypt(unsigned int r ,unsigned int *code ,unsigned int *key)
{
unsigned int v0,v1,i,delta=0x12345678;
unsigned int sum=delta*32;

v0=code[0];
v1=code[1];
for(i=0;i<32;i++)
{

v1-=( ((v0<<5) ^(v0>>6)) +v0 ) ^ ( sum + key[ (sum>>11)&3 ]);
sum-=delta;
v0-=( ((v1<<5) ^ (v1>>6)) +v1 ) ^ ( sum + key[sum&3] );

}
code[0]=v0;
code[1]=v1;
printf("%c%c",code[0],code[1]);
}



int main()
{
unsigned int key[4]={0x47,0x57,0x48,0x54};
unsigned int r=32;
unsigned int code[10]={0x36C128C5, 0x0C4799A63, 0x0E8013E6C, 0x0A9F49003, 0x607EF54A,0x542C2DDF, 0x558BD01C, 0x65512CA2, 0x0BE1E3D05, 0x3C467DAD};
int i;

for(i=0;i<5;i++)
{
decrypt(32,&code[i*2],key);
}

}
//S_s0_fuNny

password3,引发异常,伪随机数。

然后直接set,ip动调,得到rand()产生的数,虽然生成了32个,实际上只用了前16个。

然后看看乱序函数,通过看比较部分就行了。

问题就来了怎么逆回去,yyds的bxb师傅用了一个小技巧,rand()产生的数有两个字节,我们的字符只有一个字节,xor不会改变高字节的数,所以我们可以通过高字节的数来还原顺序,确实是比较妙,然后我是想直接自己输入假的字符串,然后得到假密文,从而知道乱序规律,然后逆回去,但是好像不可取,顺序还是乱的。

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

# fake_flag=[0x00004126,0x00002f64,0x00005074,0x00007d08,0x000015e6,0x0000378c,0x00006fbb,0x00000d6b,0x00003f2a,0x0000413c,0x00000ebc,0x000010f8,0x00005c22,0x00001751,0x00001955,0x00001327]
# fake_enc=[0x00000029,0x00005074,0x00006fbb,0x0000378c,0x00004823,0x0000413c,0x00007d08,0x00000d6b,0x00003f2a,0x00006784,0x00006df1,0x00005af1,0x00001649,0x000041bb,0x000026e9,0x000001eb,0x00004126,0x00000ebc,0x00001955,0x00001327,0x00002f64,0x000015e6,0x000010f8,0x00005c22,0x00001751,0x000018be,0x00004ae1,0x00003d6c,0x00002cd6,0x000072ae,0x00006952,0x00005f90]
# print(hex(fake_enc[22]))
# index=[]
# for i in fake_flag:
# index.append(fake_enc.index(i))
# print(index)
#这种不得行,得到的index是错误的。
enc=[0x10a7,0x3f72,0x413f,0x2f62,0x15da,0x5c10,0x174b,
0x6c6b,0x37da,0x3653,0x1204,0x1d0,0x19e3,0x349e,
0x60e2,0x40bf,0x1b1d,0x6f89,0xd5c,0x7d33,0x3785,
0xebc,0x4118,0x5027,0x190a,0x1338,0x74f7,0x4350,
0x3797,0x1dbb,0x2457,0x1f98]

enc1=[0x4118, 0x2F62, 0x5027, 0x7D33, 0x15DA, 0x3785,
0x6F89, 0x0D5C, 0x3F72, 0x413F, 0x0EBC, 0x10A7,
0x5C10, 0x174B, 0x190A, 0x1338]
rand=[0x4147, 0x2f06, 0x5017, 0x7d6c, 0x1583, 0x37ea, 0x6fdc, 0xd03, 0x3f43,
0x4156, 0xed7, 0x1094, 0x5c4f, 0x173f, 0x193a, 0x1357]
s=''
for i in range(16):
s+=chr((enc1[i]^rand[i])&0xff)
print(s)
#_d0_YoU_1ik3_t0o

拼接一下GWHT{r3_1S_s0_fuNny_d0_YoU_1ik3_t0o}

OddCode

流下太菜了的泪水,有师傅已经发了详细的wp了,https://bbs.pediy.com/thread-269328.htm,tql,tql,也该学习一下高级一点的东西了。