0%

友情链接

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

joyVBS-pcb2024

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

# 定义正则表达式,用于匹配符合条件的数字和运算符序列
pattern = re.compile(r"\s[0-9+\-/*]+\s")

# 读取文件并进行匹配和转换
with open("chall.vbs", "r") as file:
content = file.read()
matches = pattern.findall(content)
decoded_text = ''.join(chr(int(eval(match.strip()))) for match in matches)
print(decoded_text, end="")

然后是一个vbs脚本,改成msgbox可以输出

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
MsgBox "VBScript, often abbreviated as VBS, is an event-driven programming language developed by Microsoft, primarily used for scripting in the Windows environment."
MsgBox "It is based on the Visual Basic programming language and is designed to be simple and easy to use, especially for those familiar with the BASIC programming language."
MsgBox "And for me, it is the first programming language that I've leart"
MsgBox "Hackers! Have fun with this VBS challenge!"
flag = InputBox("Enter the FLAG:", "Hack for fun")
wefbuwiue = "NalvN3hKExBtALBtInPtNHTnKJ80L3JtqxTboRA/MbF3LnT0L2zHL2SlqnPtJLAnFbIlL2SnFT8lpzFzA2JHrRTiNmT9"

qwfe = 9+2+2+1

Function Base64Decode(base64EncodedString)
Dim xml, elem
Set xml = CreateObject("MSXML2.DOMDocument")
Set elem = xml.createElement("tmp")
elem.dataType = "bin.base64"
elem.text = base64EncodedString
Dim stream
Set stream = CreateObject("ADODB.Stream")
stream.Type = 1 'Binary
stream.Open
stream.Write elem.nodeTypedValue
stream.Position = 0
stream.Type = 2 'Text
stream.Charset = "utf-8"
Base64Decode = stream.ReadText
stream.Close
End Function
Function Caesar(str,offset)
Dim length,char,i
Caesar = ""
length = Len(str)
For i = 1 To length
char = Mid(str,i,1)
If char >= "A" And char <= "Z" Then
char = Asc("A") + (Asc(char) - Asc("A") + offset) Mod 26
Caesar = Caesar & Chr(char)
ElseIf char >= "a" And char <= "z" Then
char = Asc("a") + (Asc(char) - Asc("a") + offset) Mod 26
Caesar = Caesar & Chr(char)
Else
Caesar = Caesar & char
End If
Next
End Function

If flag = Base64Decode(Caesar(wefbuwiue, 26-qwfe)) Then
MsgBox "Congratulations! Correct FLAG!"
Else
MsgBox "Wrong flag."
End If

RE5-pcb2024

Xtea,但是用了一些异常处理函数使得每次的delta均不相同

可以动调记录sum的变化值

然后在trace里面把sum的值手动记录下来

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
import re
str = open("C:\\Users\\22101\\Downloads\\trace4.txt","r").read()

def hex_to_decimal_little_endian(hex_str):
# 去掉空格
hex_str = hex_str.replace(" ", "")

# 将16进制字符串按照每2个字符为一个字节拆分并翻转字节顺序
reversed_hex_str = ''.join([hex_str[i:i+2] for i in range(0, len(hex_str), 2)][::-1])

# 将翻转后的16进制字符串转为10进制
decimal_value = int(reversed_hex_str, 16)

return decimal_value

regex = r"Stack\[000029E8\]:0019FE70: .*"
data = []
matches = re.findall(regex, str)
print(len(matches))
for match in matches:
hex_str = match[len("Stack[000029E8]:0019FE70: "):-1]
# data.append(int(match[:-1], 16))
data.append(hex_to_decimal_little_endian(hex_str))
data2 = []
for i in range(len(data)-1):
if data[i+1] == data[i]:
continue
data2.append(data[i])
print(hex(data[i]))
data2.append(0x873fc)
print(data2)
print(len(data2))

然后逆回去即可

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
#include<bits/stdc++.h>
#include"../defs.h"
using namespace std;
_DWORD key[4] = {2,2,3,3};
unsigned int input[9] = {
0x33323130, 0x37363534, 0x33323130, 0x37363534, 0x33323130, 0x37363534, 0x33323130, 0x37363534,
};
unsigned int Destination2[8] = {
0x5E487035, 0x0DC30FB7, 0x73E48B63, 0x20CDF292, 0x46C3CD6F, 0x1F2DB262, 0x73D8C2E6, 0x1222FCB8
};
unsigned int out[8] = {
0x0EA2063F8 ,0x8F66F252, 0x902A72EF, 0x411FDA74, 0x19590D4D, 0xCAE74317, 0x63870F3F, 0xD753AE61
};
unsigned int key1[32] = {
38, 7757, 28995, 31432, 40287, 52084, 60449, 92734, 103184, 133796, 139649, 167749, 168891, 169172, 189709, 205630, 214575, 240860, 243857, 258537, 279513, 311404, 333059, 358965, 377422, 378745, 407626, 409866, 419591, 451869, 454315, 454905
};
unsigned int key2[32] = {
840, 19427, 36334, 57571, 81182, 93799, 106255, 107122, 136655, 143533, 171756, 189643, 221240, 241824, 254036, 285147, 292725, 309791, 317420,
346824, 359103, 372608, 396996, 408645, 420974, 428150, 430481, 449745, 471859, 485995, 512923, 514025};
unsigned int key3[32] = {
21652, 30056, 54393, 82249, 87847, 112619, 126716, 139929, 144612, 161315, 176575, 192517, 195264, 222639, 251510, 269514, 286187, 289339, 301158, 324662, 324901, 329087, 331891, 360828, 363851, 374186, 394719, 416112, 432132, 443706, 469689, 483650
};
unsigned int key4[32] = {
624, 7689, 35258, 48088, 72255, 84491, 115740, 139376, 154995, 180722, 193422, 217745, 232667, 255441, 262252, 274314, 277879, 303070, 303189, 321936, 347986, 367606, 383940, 389908, 407432, 411009, 426055, 451586, 466044, 495316, 521846, 553980
};
int __cdecl encrypt(unsigned int *a1, _DWORD *a2)
{
int result; // eax
unsigned int i; // [esp+64h] [ebp-28h]
int v4; // [esp+68h] [ebp-24h]
unsigned int v5; // [esp+6Ch] [ebp-20h]
unsigned int v6; // [esp+70h] [ebp-1Ch]

v6 = *a1;
v5 = a1[1];
v4 = 0;
printf("%x\n",v6);
printf("%x\n",v5);
for ( i = 0; i < 0x20; ++i )
{
// v4 -= 0x61C88647;
v4 = key1[i];
v6 += (a2[1] + (v5 >> 5)) ^ (v4 + v5) ^ (*a2 + 16 * v5);
v5 += (a2[3] + (v6 >> 5)) ^ (v4 + v6) ^ (a2[2] + 16 * v6);
printf("%x\n",v6);
printf("%x\n",v5);
printf("%x\n",v4);
}
*a1 = v6;
// printf("%d\n",v4);
result = 4;
a1[1] = v5;
return result;
}

int __cdecl decrypt(unsigned int *a1, _DWORD *a2,_DWORD *a3)
{
int result; // eax
unsigned int i; // [esp+64h] [ebp-28h]
int v4; // [esp+68h] [ebp-24h]
unsigned int v5; // [esp+6Ch] [ebp-20h]
unsigned int v6; // [esp+70h] [ebp-1Ch]

v6 = *a1;
v5 = a1[1];
v4 = a3[31];
// printf("%x\n",v6);
// printf("%x\n",v5);
// printf("%x\n",v4);?
for ( i = 0; i < 0x20; ++i )
{
v5 -= (a2[3] + (v6 >> 5)) ^ (v4 + v6) ^ (a2[2] + 16 * v6);
v6 -= (a2[1] + (v5 >> 5)) ^ (v4 + v5) ^ (*a2 + 16 * v5);
v4 =a3[30-i];
// printf("%x\n",v6);
// printf("%x\n",v5);
// printf("%x\n",v4);
}
*a1 = v6;
result = 4;
a1[1] = v5;
printf("%x\n",v6);
printf("%x\n",v5);
return result;
}

int main(){
unsigned int data[2] = {1,2};
// encrypt(&input[0],key);
printf("%x %x\n",input[0],input[1]);
decrypt(&out[0],key,key1);
decrypt(&out[2],key,key2);
decrypt(&out[4],key,key3);
decrypt(&out[6],key,key4);
char *flag = (char *)out;

for(int i = 0;i<=31;i++){
printf("%c",*(flag+i));
}
// decrypt(&out[2],key);
// decrypt(&out[4],key);
// decrypt(&out[6],key);
// char *flag = (char *)out;

}

Rafflesia-pcb2024

1
flag{8edae458-4tf3-2ph2-9f26-1f8719ec8f8d}

入口处有几个花指令 patch完如下

image.png

TLS callBack的地方有改base表和调试检查

image.png
image.png

base64最后做了一个xor 0x18

把flag字符串base64后Xor 0x18 发现结果H@^jH和常量字符串开头很像,猜测其实根本没改过这里的Buf1

1
qmemcpy(Buf1, "H@^jHwpsH)[jH{M/\\tBBK_|-O{W.iJZ7\\)|~zaB^H+Lwv{SS|-j@\\_[Y", 4 * v3 + 1);

直接解回去

image.png

exec-pcb202

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
data = base64.b64decode(data)
# print(data[-7:-5])
while True:
if data[12:15] == b'b32':
print(data[:100])
data = base64.b32decode(data[26:-5])
continue
if data[12:15] == b'b64':
print(data[:100])
data = base64.b64decode(data[26:-5])
continue
if data[12:15] == b'b16':
print(data[:100])
data = base64.b16decode(data[26:-5])
continue
if data[12:15] == b'a85':
print(data[:100])
data = base64.a85decode(data[26:-5])
continue
if data[12:15] == b'b85':
print(data[:100])
data = base64.b85decode(data[26:-5])
continue
else:
file = open('output.txt', 'wb')
file.write(data)
print(data)
break

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

# output.py
a=True
d=len
G=list
g=range
s=next
R=bytes
o=input
Y=print
def l(S):
i=0
j=0
while a:
i=(i+1)%256
j=(j+S[i])%256
S[i],S[j]=S[j],S[i]
K=S[(S[i]+S[j])%256]
yield K
def N(key,O):
I=d(key)
S=G(g(256))
j=0
for i in g(256):
j=(j+S[i]+key[i%I])%256
S[i],S[j]=S[j],S[i]
z=l(S)
n=[]
for k in O:
n.append(k^s(z)+2)
return R(n)
def E(s,parts_num):
Q=d(s.decode())
S=Q//parts_num
u=Q%parts_num
W=[]
j=0
for i in g(parts_num):
T=j+S
if u>0:
T+=1
u-=1
W.append(s[j:T])
j=T
return W
if __name__=='__main__':
L=o('input the flag: >>> ').encode()
assert d(L)%2==0,'flag length should be even'
t=b'v3ry_s3cr3t_p@ssw0rd'
O=E(L,2)
U=[]
for i in O:
U.append(N(t,i).hex())
if U==['1796972c348bc4fe7a1930b833ff10a80ab281627731ab705dacacfef2e2804d74ab6bc19f60',2ea999141a8cc9e47975269340c177c726a8aa732953a66a6af183bcd9cec8464a']:
Y('Congratulations! You got the flag!')
else:
Y('Wrong flag!')

# 注意到是魔改的RC4,懒得自己改了
# 让他自己RC4回去

# O=E(L,2)
# U=[]
# O = []
# O.append(bytes.fromhex('1796972c348bc4fe7a1930b833ff10a80ab281627731ab705dacacfef2e2804d74ab6bc19f60'))
# O.append(bytes.fromhex('2ea999141a8cc9e47975269340c177c726a8aa732953a66a6af183bcd9cec8464a'))

image.png

1
flag{thEn_I_Ca5_BE_YoUR_Onl7_ExeCUti6n_So_Use_m3_t0_R0n_tH17_Ex3Cuti0n}

Reverse

serv1ce

有点混淆,jeb5直接反编译解出字符串,然后就可以找他的startService

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
package com.nobody.Serv1ce;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;

public class MyService extends Service {
private String input;
private String key;
private byte[] keyarray;
int num;

static {
System.loadLibrary("Serv1ce");
}

public MyService() {
this.key = "1liIl11lIllIIl11llII";
this.keyarray = new byte[0x40];
this.num = 9;
}

private native boolean check(String arg1, byte[] arg2, int arg3) {
}

@Override // android.app.Service
public IBinder onBind(Intent intent0) {
throw new UnsupportedOperationException("Not yet implemented");
}

@Override // android.app.Service
public void onCreate() {
++this.num;
super.onCreate();
}

@Override // android.app.Service
public void onDestroy() {
if(this.check(this.input, this.keyarray, this.num)) {
Toast.makeText(this.getApplicationContext(), "You Are Right", 1).show();
}
else {
Toast.makeText(this.getApplicationContext(), "Wrong", 1).show();
}

super.onDestroy();
}

@Override // android.app.Service
public int onStartCommand(Intent intent0, int v, int v1) {
++this.num;
for(int v2 = 0; v2 < 0x40; ++v2) {
this.keyarray[v2] = (byte)((this.key.charAt(v2 % this.key.length()) - 0x77 ^ 23) & 0xFF);
}

if(intent0 != null) {
this.input = intent0.getStringExtra("input");
Toast.makeText(this.getApplicationContext(), "Input Success", 1).show();
}

super.onStartCommand(intent0, v, v1);
return v;
}
}

image.png
exp

1
2
3
4
5
6
7
8
9
10
11
12
res = [0xB9, 0x32, 0xC2, 0xD4, 0x69, 0xD5, 0xCA, 0xFB, 0xF8, 0xFB, 0x80, 0x7C, 0xD4, 0xE5, 0x93, 0xD5, 0x1C, 0x8B, 0xF8, 0xDF, 0xDA, 0xA1, 0x11, 0xF8, 0xA1, 0x93, 0x93, 0xC2, 0x7C, 0x8B, 0x1C, 0x66, 0x01, 0x3D, 0xA3, 0x67]

key = "1liIl11lIllIIl11llII"
keyarray = [0 for i in range(0x40)]
for i in range(0x40):
keyarray[i] =((ord(key[i%len(key)])-0x77)^23)&0xff
print(keyarray)
for i in range(36):
# print(i)
for num in string.printable:
if ((ord(num)^keyarray[i])*11)&0xff == res[i]:
print(num,end='')

A_game

NJU-TJL/PacManX: 基于C++控制台(Windows平台)的一个吃豆人小游戏 (github.com)

image.png

bindiff结果

下面几个就是出题人改的跟flag有关的函数了

动调把ps脚本扣出来,里面好几层iex,运行输出一下 iex后面的部分

最内层:

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

function enenenenene {
param(
$plaintextBytes,
$keyBytes
)
# Initialize S and KSA
$S = 0..255
$j = 0
for ($i = 0; $i -lt 256; $i++) {
$j = ($j + $S[$i] + $keyBytes[$i % $keyBytes.Length]) % 256
$temp = $S[$i]
$S[$i] = $S[$j]
$S[$j] = $temp
}

# PRGA and encryption
$i = 0
$j = 0
$ciphertextBytes = @()
for ($k = 0; $k -lt $plaintextBytes.Length; $k++) {
$i = ($i + 1) % 256
$j = ($j + $S[$i]) % 256
$temp = $S[$i]
$S[$i] = $S[$j]
$S[$j] = $temp
$t = ($S[$i] + $S[$j]) % 256
$ciphertextBytes += ($plaintextBytes[$k] -bxor $S[$t])
}

# Return ciphertext as a string
return $ciphertextBytes
}
function enenenenene1 {
param(
$inputbyte
)
$key = @(0x70, 0x6f, 0x77, 0x65, 0x72)
$encryptedText = @();
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$encryptedText = enenenenene -plaintextBytes $inputbyte -keyBytes $key;
$key = enenenenene -plaintextBytes $key -keyBytes $encryptedText;
}
return $encryptedText + $key;
}
function enenenenene2 {
param(
$inputbyte
)
$key = @(0x70, 0x30, 0x77, 0x65, 0x72)
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$inputbyte[$k] = $inputbyte[$k] + $key[$k % $key.Length]
}
return $inputbyte;
}
function enenenenene3 {
param(
$inputbyte
)
$key = @(0x70, 0x30, 0x77, 0x33, 0x72)
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$inputbyte[$k] = $inputbyte[$k] * $key[$k % $key.Length]
}
return $inputbyte;
}
$registryPath = 'HKCU:\Software\PacManX'
$valueName = 'MYFLAG'
$value = Get-ItemPropertyValue $registryPath $valueName
$plaintext = @($value) | ForEach-Object {
$input = $_
$plaintext = @()
for ($i = 0; $i -lt $input.Length; $i++) {
$plaintext += [int][char]$input[$i]
}
$plaintext
}
if ($plaintext.Length -ne 36) {
Set-Content -Path "log.txt" -Value "ERROR"
exit
}
$encrypted1Text = enENenenene2 -inputbyte (enenenENene2 -inputbyte (enenenenene3 -inputbyte (Enenenenene2 -inputbyte (enenenenene2 -inputbyte (enenenenene2 -inputbyte (enenenenene1 -input $plaintext))))))
$result = @(38304, 8928, 43673, 25957 , 67260, 47152, 16656, 62832 , 19480 , 66690, 40432, 15072 , 63427 , 28558 , 54606, 47712 , 18240 , 68187 , 18256, 63954 , 48384, 14784, 60690 , 21724 , 53238 , 64176 , 9888 , 54859 , 23050 , 58368 , 46032 , 15648 , 64260 , 17899 , 52782 , 51968 , 12336 , 69377 , 27844 , 43206 , 63616)
for ($k = 0; $k -lt $result.Length; $k++) {
if ($encrypted1Text[$k] -ne $result[$k]) {
Set-Content -Path "log.txt" -Value "ERROR"
exit

}
Set-Content -Path "log.txt" -Value "RIGHT"

enenenenene 就是个rc4,加密解密一样,powershell写个解密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
# execute: powershell -executionpolicy bypass -file .\exp.ps1
function enenenenene { # rc4
param(
$plaintextBytes,
$keyBytes
)
# Initialize S and KSA
$S = 0..255
$j = 0
for ($i = 0; $i -lt 256; $i++) {
$j = ($j + $S[$i] + $keyBytes[$i % $keyBytes.Length]) % 256
$temp = $S[$i]
$S[$i] = $S[$j]
$S[$j] = $temp
}

# PRGA and encryption
$i = 0
$j = 0
$ciphertextBytes = @()
for ($k = 0; $k -lt $plaintextBytes.Length; $k++) {
$i = ($i + 1) % 256
$j = ($j + $S[$i]) % 256
$temp = $S[$i]
$S[$i] = $S[$j]
$S[$j] = $temp
$t = ($S[$i] + $S[$j]) % 256
$ciphertextBytes += ($plaintextBytes[$k] -bxor $S[$t])
}

# Return ciphertext as a string
return $ciphertextBytes
}
function enc1 {
param(
$inputbyte
)
$key = @(0x70, 0x6f, 0x77, 0x65, 0x72)
$encryptedText = @();
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$encryptedText = enenenenene -plaintextBytes $inputbyte -keyBytes $key;
$key = enenenenene -plaintextBytes $key -keyBytes $encryptedText;
}
return $encryptedText + $key;
}
function dec1 {
param(
$inputbyte
)
$initial_key = @(0x70, 0x6f, 0x77, 0x65, 0x72)
$encryptedText = $inputbyte[0..($inputbyte.Length-$initial_key.Length-1)]
$key = $inputbyte[($inputbyte.Length-$initial_key.Length)..($inputbyte.Length-1)]
# Write-Output $encryptedText
# Write-Output $key
# Write-Output $encryptedText

$key = enenenenene -plaintextBytes $key -keyBytes $encryptedText;
$plain = enenenenene -plaintextBytes $encryptedText -keyBytes $key;
return $plain;
}
function enc2 {
param(
$inputbyte
)
$key = @(0x70, 0x30, 0x77, 0x65, 0x72)
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$inputbyte[$k] = $inputbyte[$k] + $key[$k % $key.Length]
}
return $inputbyte;
}

function dec2 {
param(
$inputbyte
)
$key = @(0x70, 0x30, 0x77, 0x65, 0x72)
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$inputbyte[$k] = $inputbyte[$k] - $key[$k % $key.Length]
}
return $inputbyte;
}

function enc3 {
param(
$inputbyte
)
$key = @(0x70, 0x30, 0x77, 0x33, 0x72)
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$inputbyte[$k] = $inputbyte[$k] * $key[$k % $key.Length]
}
return $inputbyte;
}

function dec3 {
param(
$inputbyte
)
$key = @(0x70, 0x30, 0x77, 0x33, 0x72)
for ($k = 0; $k -lt $inputbyte.Length; $k++) {
$inputbyte[$k] = $inputbyte[$k] / $key[$k % $key.Length]
}
return $inputbyte;
}

# $registryPath = 'HKCU:\Software\PacManX'
# $valueName = 'MYFLAG'
# $value = Get-ItemPropertyValue $registryPath $valueName
# $plaintext = @($value) | ForEach-Object {
# $input = $_
# $plaintext = @()
# for ($i = 0; $i -lt $input.Length; $i++) {
# $plaintext += [int][char]$input[$i]
# }
# $plaintext
# }
# if ($plaintext.Length -ne 36) {
# Set-Content -Path "log.txt" -Value "ERROR"
# exit
# }
# $encrypted1Text = enENenenene2 -inputbyte (enenenENene2 -inputbyte (enenenenene3 -inputbyte (Enenenenene2 -inputbyte (enenenenene2 -inputbyte (enenenenene2 -inputbyte (enenenenene1 -input $plaintext))))))

Write-Host (dec1 -inputbyte (enc1 -inputbyte @(1, 2, 3, 4, 5)))
Write-Host (dec2 -inputbyte (enc2 -inputbyte @(1, 2, 3, 4, 5)))
Write-Host (dec3 -inputbyte (enc3 -inputbyte @(1, 2, 3, 4, 5)))

$result = @(38304, 8928, 43673, 25957 , 67260, 47152, 16656, 62832 , 19480 , 66690, 40432, 15072 , 63427 , 28558 , 54606, 47712 , 18240 , 68187 , 18256, 63954 , 48384, 14784, 60690 , 21724 , 53238 , 64176 , 9888 , 54859 , 23050 , 58368 , 46032 , 15648 , 64260 , 17899 , 52782 , 51968 , 12336 , 69377 , 27844 , 43206 , 63616)

$flag = dec1 -inputbyte (dec2 -inputbyte (dec2 -inputbyte (dec2 -inputbyte (dec3 -inputbyte (dec2 -inputbyte (dec2 -inputbyte $result))))))

$flag = [System.Text.Encoding]::ASCII.GetString($flag)

Write-Host $flag

flag: 73412036-7d8c-437b-9026-0c2ca1b7f79d

babyre

流程大概如下,可以根据S盒+调试确定是AES,轮数也是10

image.png

image.png

phrase函数把8bit输入和4bit索引合在一起变成12bit

image.png

check函数判断给定的12bit是否符合任一条件,即图中这一堆&v1&(v2==0),由于12bit里面有4bit索引,所以能过这个check的输入是固定的

爆破得到所有能过check的12bit输入

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
#include"defs.h" 
#include<stdio.h>
__int64 __fastcall sub_4020F7(int *a1)
{
int v1; // r8d
int v2; // ecx
int v3; // ecx
int v5; // [rsp+8h] [rbp-38h]
int v6; // [rsp+Ch] [rbp-34h]
int v7; // [rsp+10h] [rbp-30h]
int v8; // [rsp+14h] [rbp-2Ch]
int v9; // [rsp+18h] [rbp-28h]
int v10; // [rsp+1Ch] [rbp-24h]
int v11; // [rsp+20h] [rbp-20h]
int v12; // [rsp+24h] [rbp-1Ch]
int v13; // [rsp+28h] [rbp-18h]
int v14; // [rsp+2Ch] [rbp-14h]
__int64 v15; // [rsp+30h] [rbp-10h]
int i; // [rsp+38h] [rbp-8h]
unsigned int v17; // [rsp+3Ch] [rbp-4h]

v17 = 1;
for ( i = 0; i <= 0; ++i )
{
HIDWORD(v15) = a1[12 * i];
LODWORD(v15) = a1[12 * i + 1];
v14 = a1[12 * i + 2];
v13 = a1[12 * i + 3];
v12 = a1[12 * i + 4];
v11 = a1[12 * i + 5];
v10 = a1[12 * i + 6];
v9 = a1[12 * i + 7];
v8 = a1[12 * i + 8];
v7 = a1[12 * i + 9];
v6 = a1[12 * i + 10];
v5 = a1[12 * i + 11];
v1 = (unsigned __int8)v7 & (unsigned __int8)v8 & (unsigned __int8)v9 & (v11 == 0) & (v12 == 0) & (unsigned __int8)v13 & ((v14 | (unsigned int)v15 | HIDWORD(v15)) == 0) & (v10 == 0) & (v6 == 0) | (unsigned __int8)v7 & (unsigned __int8)v9 & (unsigned __int8)v11 & (v13 == 0) & (v14 == 0) & BYTE4(v15) & ((_DWORD)v15 == 0) & (v12 == 0) & (v10 == 0) & (v8 == 0) & (v6 == 0) | (unsigned __int8)v6 & (v8 == 0) & (v9 == 0) & (v10 == 0) & (unsigned __int8)v11 & (unsigned __int8)v12 & (unsigned __int8)(v14 & v15 & BYTE4(v15)) & (v13 == 0) & (v7 == 0);
v2 = (unsigned __int8)v5 & (unsigned __int8)v6 & (unsigned __int8)v8 & (unsigned __int8)v9 & (unsigned __int8)v10 & (unsigned __int8)v11 & (unsigned __int8)v12 & (v14 == 0) & (unsigned __int8)(v15 & BYTE4(v15)) & (v13 == 0) & (v7 == 0) | (v6 == 0) & (v7 == 0) & (unsigned __int8)v8 & (unsigned __int8)v9 & (unsigned __int8)v10 & (unsigned __int8)v12 & (unsigned __int8)v13 & (unsigned __int8)v15 & (HIDWORD(v15) == 0) & (v14 == 0) & (v11 == 0) & (v5 == 0) | (unsigned __int8)v5 & (v7 == 0) & (unsigned __int8)v8 & (unsigned __int8)v10 & (unsigned __int8)v12 & (unsigned __int8)v13 & (unsigned __int8)v14 & BYTE4(v15) & ((_DWORD)v15 == 0) & (v11 == 0) & (v9 == 0) & (v6 == 0) | (unsigned __int8)v5 & (unsigned __int8)v7 & (unsigned __int8)v8 & (unsigned __int8)v10 & (unsigned __int8)v11 & (unsigned __int8)v13 & (unsigned __int8)v14 & (v15 == 0) & (v12 == 0) & (v9 == 0) & (v6 == 0) | (v1 | (unsigned __int8)v6 & (unsigned __int8)v7 & (v9 == 0) & (unsigned __int8)v10 & (v12 == 0) & (unsigned __int8)v13 & (unsigned __int8)v14 & BYTE4(v15) & ((_DWORD)v15 == 0) & (v11 == 0) & (v8 == 0)) & (v5 == 0);
v3 = (unsigned __int8)v5 & (unsigned __int8)v6 & (v8 == 0) & (v9 == 0) & (unsigned __int8)v10 & (v12 == 0) & (v13 == 0) & (v14 == 0) & (unsigned __int8)(v15 & BYTE4(v15)) & (v11 == 0) & (v7 == 0) | (v6 == 0) & (v7 == 0) & (v8 == 0) & (v9 == 0) & (unsigned __int8)v10 & (v12 == 0) & (unsigned __int8)v13 & ((v14 | (unsigned int)v15 | HIDWORD(v15)) == 0) & (v11 == 0) & (v5 == 0) | (unsigned __int8)v5 & (unsigned __int8)v6 & (unsigned __int8)v7 & (v9 == 0) & (v10 == 0) & (unsigned __int8)v11 & (unsigned __int8)v12 & (v14 == 0) & (unsigned __int8)v15 & (HIDWORD(v15) == 0) & (v13 == 0) & (v8 == 0) | (unsigned __int8)v5 & (unsigned __int8)v7 & (v9 == 0) & (v10 == 0) & (unsigned __int8)v11 & ((v12 | v13 | v14 | (unsigned int)v15 | HIDWORD(v15)) == 0) & (v8 == 0) & (v6 == 0) | (unsigned __int8)v5 & (v7 == 0) & (v8 == 0) & (unsigned __int8)v9 & (unsigned __int8)v10 & (unsigned __int8)v11 & (unsigned __int8)v12 & (v14 == 0) & BYTE4(v15) & ((_DWORD)v15 == 0) & (v13 == 0) & (v6 == 0) | v2;
if ( !((unsigned __int8)v6 & (unsigned __int8)v8 & (unsigned __int8)v10 & (unsigned __int8)v12 & (v14 == 0) & (unsigned __int8)v15 & (HIDWORD(v15) == 0) & (v13 == 0) & (v11 == 0) & (v9 == 0) & (v7 == 0) & (v5 == 0) | (unsigned __int8)v5 & (unsigned __int8)v6 & (unsigned __int8)v7 & (unsigned __int8)v8 & (v10 == 0) & (v11 == 0) & (unsigned __int8)v12 & (v14 == 0) & (unsigned __int8)v15 & (HIDWORD(v15) == 0) & (v13 == 0) & (v9 == 0) | v3 | (unsigned __int8)v6 & (unsigned __int8)v7 & (unsigned __int8)v8 & (unsigned __int8)v10 & (unsigned __int8)v12 & ((v13 | v14 | (unsigned int)v15 | HIDWORD(v15)) == 0) & (v11 == 0) & (v9 == 0) & (v5 == 0)) )
v17 = 0;
}
return v17;
}
int main(){
int res[13];
int num;
for(int i=0;i<=(1<<12);i++){
res[0] = i&1;
res[1] = (i>>1)&1;
res[2] = (i>>2)&1;
res[3] = (i>>3)&1;
res[4] = (i>>4)&1;
res[5] = (i>>5)&1;
res[6] = (i>>6)&1;
res[7] = (i>>7)&1;
res[8] = (i>>8)&1;
res[9] = (i>>9)&1;
res[10] = (i>>10)&1;
res[11] = (i>>11)&1;
if(sub_4020F7(res)){
// printf("%d\n",i);
// for(int j=0;j<=11;j++){
// printf("%d ",res[j]);
// }
num = res[8];
num = (num<<1) + res[9];
num = (num<<1) + res[10];
num = (num<<1) + res[11];
printf("a[%d]=",num);
num = res[0];
num = (num<<1) + res[1];
num = (num<<1) + res[2];
num = (num<<1) + res[3];
num = (num<<1) + res[4];
num = (num<<1) + res[5];
num = (num<<1) + res[6];
num = (num<<1) + res[7];
printf("0x%x\n",num);
}
}
}
// data = [18,143,236,194,133,4,178,76,91,186,74,207,17,54,10,72]

AES key从程序里dump一份(0x405420):

1
3577402ECCA44A3F9AB72182F9B01F35

AES ECB解回去即可

image.png

加上uuid的横杠:

1
4d87ef03-77bb-491a-80f5-4620245807c4