0%

2024强网杯决赛 Re 部分 WP

PVB

题目内容:parse the payload

样本估计是bvp47

https://www.pangulab.cn/files/The_Bvp47_a_top-tier_backdoor_of_us_nsa_equation_group.zh-cn.pdf

根据下面这篇文章解出payload

https://www.qianxin.com/news/detail?news_id=6484

解payload的exp

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
#include<bits/stdc++.h>
#include"defs.h"
using namespace std;
unsigned char src_buf[8394] = {

};
int __cdecl _869e0233_decode_(_BYTE *a1, int a2, char *a3, _DWORD *a4)
{
_BYTE *v4; // ebx
unsigned int v5; // edi
char *v6; // edx
unsigned int v7; // eax
int v8; // ecx
unsigned __int8 *v9; // ebx
unsigned __int8 *v10; // ebx
int v11; // ecx
int v12; // eax
unsigned int v13; // edi
int v14; // ecx
int v15; // eax
unsigned __int8 v16; // al
int v17; // ecx
unsigned __int8 *v18; // ecx
int v19; // eax
int v20; // eax
int v21; // eax
int v22; // edi
int v23; // eax
int v24; // edx
int v25; // ecx
char *v26; // eax
unsigned __int8 v27; // al
int v28; // ecx
unsigned __int16 v29; // ax
int v30; // eax
int v31; // eax
int v32; // ecx
int v33; // eax
char *v34; // ecx
unsigned __int16 v35; // ax
char *v36; // ecx
int v37; // ecx
unsigned __int8 v38; // al
int result; // eax
unsigned int v40; // [esp+0h] [ebp-24h]
unsigned int v41; // [esp+4h] [ebp-20h]
char *v42; // [esp+8h] [ebp-1Ch]
_BYTE *v43; // [esp+Ch] [ebp-18h]
unsigned int v44; // [esp+10h] [ebp-14h]
unsigned int v45; // [esp+14h] [ebp-10h]

v4 = a1;
v43 = &a1[a2];
*a4 = 0;
LOBYTE(v5) = *a1;
v6 = a3;
if ( *a1 > 0x11u )
{
v7 = (unsigned __int8)*a1 - 17;
v4 = a1 + 1;
if ( v7 <= 3 )
goto LABEL_3;
v24 = 0;
do
{
a3[v24] = a1[v24 + 1];
++v24;
--v7;
}
while ( v7 );
v25 = (unsigned __int8)v5 - 17;
v6 = &a3[v25];
v18 = &a1[v25 + 1];
goto LABEL_29;
}
LABEL_12:
v5 = (unsigned __int8)v5;
v10 = v4 + 1;
if ( (unsigned __int8)v5 <= 0xFu )
{
if ( !(_BYTE)v5 )
{
v16 = *v10;
v17 = 15;
if ( !*v10 )
{
do
{
++v10;
v5 += 255;
v16 = *v10;
}
while ( !*v10 );
v17 = v5 + 15;
}
++v10;
v5 = v17 + v16;
}
v18 = v10 + 4;
*(_DWORD *)v6 = *(_DWORD *)v10;
v42 = v6 + 4;
v45 = v5 - 1;
if ( v5 == 1 )
{
v6 += 4;
}
else
{
v19 = 0;
if ( v45 <= 3 )
{
do
{
v6[v19 + 4] = v10[v19 + 4];
++v19;
}
while ( v45 != v19 );
v6 = &v42[v45];
v18 += v45;
}
else
{
v41 = (v5 - 5) >> 2;
v20 = 0;
do
{
*(_DWORD *)&v6[4 * v20 + 4] = *(_DWORD *)&v10[4 * v20 + 4];
++v20;
}
while ( v20 != v41 + 1 );
v21 = 4 * v20;
v18 += v21;
v6 = &v42[v21];
v22 = v45 - 4 * v41 - 4;
if ( v45 - 4 * v41 != 4 )
{
v23 = 0;
do
{
v6[v23] = v18[v23];
++v23;
}
while ( v22 != v23 );
v6 += v22;
v18 += v22;
}
}
}
LABEL_29:
v5 = *v18;
v10 = v18 + 1;
if ( v5 <= 0xF )
{
v26 = &v6[-(v5 >> 2) - 2049 + -4 * v18[1]];
v4 = v18 + 2;
*v6 = *v26;
v6[1] = v26[1];
v6[2] = v26[2];
v6 += 3;
goto LABEL_31;
}
}
while ( 1 )
{
if ( v5 > 0x3F )
{
v11 = (int)&v6[-((v5 >> 2) & 7) - 1];
v12 = *v10;
v4 = v10 + 1;
v13 = (v5 >> 5) - 1;
v14 = v11 - 8 * v12;
goto LABEL_8;
}
if ( v5 <= 0x1F )
break;
v13 = v5 & 0x1F;
if ( !v13 )
{
v27 = *v10;
v28 = 31;
if ( !*v10 )
{
do
{
++v10;
v13 += 255;
v27 = *v10;
}
while ( !*v10 );
v28 = v13 + 31;
}
++v10;
v13 = v27 + v28;
}
v29 = *(_WORD *)v10;
v4 = v10 + 2;
v14 = (int)&v6[-(v29 >> 2) - 1];
LABEL_41:
if ( v13 > 5 && (int)&v6[-v14] > 3 )
{
*(_DWORD *)v6 = *(_DWORD *)v14;
v44 = (v13 - 6) >> 2;
v40 = v13 - 2;
v30 = 0;
do
{
*(_DWORD *)&v6[4 * v30 + 4] = *(_DWORD *)(v14 + 4 * v30 + 4);
++v30;
}
while ( v30 != v44 + 1 );
v31 = 4 * v30;
v6 += v31 + 4;
v32 = v31 + v14 + 4;
if ( v40 - 4 * v44 != 4 )
{
v33 = 0;
do
{
v6[v33] = *(_BYTE *)(v32 + v33);
++v33;
}
while ( v33 != v40 - 4 * v44 - 4 );
v6 += v33;
}
LABEL_31:
v7 = *(v4 - 2) & 3;
if ( (*(v4 - 2) & 3) == 0 )
goto LABEL_11;
goto LABEL_3;
}
LABEL_8:
*v6 = *(_BYTE *)v14;
v6[1] = *(_BYTE *)(v14 + 1);
v15 = 0;
do
{
v6[v15 + 2] = *(_BYTE *)(v14 + v15 + 2);
++v15;
}
while ( v15 != v13 );
v6 += v15 + 2;
v7 = *(v4 - 2) & 3;
if ( (*(v4 - 2) & 3) == 0 )
{
LABEL_11:
LOBYTE(v5) = *v4;
goto LABEL_12;
}
LABEL_3:
v8 = 0;
do
{
v6[v8] = v4[v8];
++v8;
}
while ( v8 != v7 );
v9 = &v4[v8];
v6 += v8;
v5 = *v9;
v10 = v9 + 1;
}
if ( v5 <= 0xF )
{
v37 = *v10;
v4 = v10 + 1;
*v6 = v6[-(v5 >> 2) - 1 + -4 * v37];
v6[1] = v6[-(v5 >> 2) + -4 * v37];
v6 += 2;
goto LABEL_31;
}
v34 = &v6[-2048 * (v5 & 8)];
v13 = v5 & 7;
if ( !v13 )
{
while ( 1 )
{
v38 = *v10;
if ( *v10 )
break;
v13 += 255;
++v10;
}
++v10;
v13 += v38 + 7;
}
v35 = *(_WORD *)v10;
v4 = v10 + 2;
v36 = &v34[-(v35 >> 2)];
if ( v36 != v6 )
{
v14 = (int)(v36 - 0x4000);
goto LABEL_41;
}
*a4 = v6 - a3;
result = 0;
if ( v4 != v43 )
return v4 < v43 ? -8 : -4;
return result;
}
char *__cdecl _4743c911_xor_(char *a1, unsigned int a2)
{
int v2; // ebx
unsigned int i; // edx
char v4; // cl

if ( a2 )
{
v2 = 0;
for ( i = 0; i < a2; ++i )
{
v4 = v2 ^ a1[i] ^ 0x47;
v2 += (unsigned __int8)a1[i];
a1[i] = i ^ v4;
}
}
return a1;
}
char dst_buf[0x5618];
int main(){
int src_size = 0x20CA;
int dst_size = 0x5618;
memset(dst_buf,0,dst_size);
_4743c911_xor_((char *)src_buf,src_size);
_869e0233_decode_(src_buf,src_size,dst_buf,(uint32_t *)&dst_size);
FILE * dp = fopen("sec_0","wb");
fwrite(dst_buf,dst_size,1,dp);
fclose(dp);

}

解出来可以大概看出来是个3DES

题目里面自带了DES的加密和解密,通过mode参数1和2判断

image.png

patch把1和2都颠倒过来

就可以让原本的加密逻辑变成解密

然后这个时候输入密文即可得到明文

image.png

simple-VM

题目内容:简单的vm 最好的vm

len(input)==32

1
2
3
4
5
if ( (unsigned int)sub_7FF7DD101D30(input, _quest) )
{
sub_7FF7DD1011B0("Ultimate secret box is not only the name muahahaha");
return 0;
}

quest是第一部分虚拟机的执行流 input是输入

1
2
3
4
5
6
7
8
9
10
11
12
0x11  :  push X
0x12 : pop now_char_
0x13 : pop x ;pop y ;push x*y;
0x14 : pop x ;pop y ;push x+y;
0x15 : printf("%c",now_char_)
0x16 : push input[index]
0x17 : pop x ;pop y ;push (y >> x) & 1;
0x18 : pop x ;pop y ;push x^y;
0x19 : index++
0x1A : return ( need 0 )
0x1B : pop x ;pop y ;push x-y;
0x1C : pop x ;pop y ;push x/y;

输错一遍会把下发的VM指令改了

如果一开始什么都不知道运行了一遍就会出现对着被改的指令嗯求求不出来的情况(*^_^*)

流程大概是把输入的每个字节的8个bit分别和0/1进行判断,相同则把一个常数加到sum中,如果8个bit计算完的结果和预期值相等,则该输入字节正确。

可以暴力遍历所有的2^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
f = open("quest",'rb')
data = f.read()
data2 = data[0x110:]
input_index = 0

number = [0 for i in range(8)]
for i in range(32):
# print(i)
data = data2[i*0x43:0x43+i*0x43]
index = 0
for j in range(8):
# print((data[5+j*7]),end=" ")
number[j] = data[5+j*7]
# print(number)
# print("")
target = (data[-3])
# print((target))
for emu in range(2**8-1):
num8 = emu>>7&1
num7 = emu>>6&1
num6 = emu>>5&1
num5 = emu>>4&1
num4 = emu>>3&1
num3 = emu>>2&1
num2 = emu>>1&1
num1 = emu&1
if (number[0]*num1 + number[1]*num2 + number[2]*num3 + number[3]*num4 + number[4]*num5 + number[5]*num6 + number[6]*num7 + number[7]*num8) == target:
if emu < 0x7f and emu > 0x20:
print(chr(emu&0xff),end="")
# break
# print(hex(emu),end="")
# input_index = emu

print("")
data = "s1mpl3_VM_us3s_link3d_l1st_st4ck"
print(len(data))

image.png