Misc

你好,来签到的旅行者

微信公众号发送flag获得

纯黑的噩梦

docx文件本质是压缩包,改后缀为.zip打开

在word-media中可以查看word中的图片文件

第一张图片是出题人小黑子证明,第二张是所有的黑图,第三张是flag

踩踩我的图

首先是图片隐写题常见思路,binwalk一下,发现里面果然有秘密

根据题目文件夹名与提示,搜索Picsel关键词,发现符合“合二为一”“军用级加密”的软件为

SSuite Picsel Security(不得不说misc的涉猎确实广

下载软件并合并两图片得到flag

ezpcapng

pcapng文件,用wireshark打开,发现显目的GET /tmp/sql/sql4.php HTTP/1.1 条目

意识到本题考查的是sql注入,先过滤http数据包,发现很多条注入记录,考虑是sql盲注

QQ截图20231025001515

前面是一些猜解库名、表名等的注入,找到猜解flag的注入起点

ASCII码值为102的字符为f,向下检查,四个字符为flag,就是这里没错,接着向下查找,列写出最终flag

(当然有能力可以写个脚本依次提取所有字符,本人是一个个列出来的

Crypto

Matryoshka-doll

访问实例得到字符串

LJCGG6SMLBXXQZLHOBYVSVDLPJGFQ2ZQJRLVCMCZPJJGUZSYNQ3U26S2NJMTG4DILFUTAMSNPJETEWSYNMYFSV2FGVGVCPJ5

分析source.py代码逻辑

凯撒移位位数为1至25的随机数,栅栏宽度为2至10的随机数,然后是base64加密与base32加密

需要注意的是,根据函数名rail_fence也可以注意到,这里的栅栏密码是W型变种

了解以上之后,通过在线解密网站可以解出base64加密前字符串

d73-z1zja93-y4-d4c4c}y{36cczab-6326ey4aa91

枚举解密栅栏

找到符合XXXX{XXXXXXX···}格式的密文,再Caeser枚举得到flag

(吐槽一下出题人写的脚本

Pwn

签到

根据要求,在linux环境下nc ctf.qwq.cc 端口号即可获得flag

红包题!1024!

本人不怎么会根本不会pwn,把1024完成了获得shell

ls下发现flag

cat flag查看flag内容

Web

checkin

访问实例,果然又是原神,虽然不是web手,但也知道web手的核心要义是网页源代码

F12发现开发者工具快捷键被ban了,右键发现也被ban了

还好还有一招,在网址前添加view-source:查看源代码,发现flag

QQ图片20231025010640

ezphp

代码审计

发现可以数组绕过md5验证,通过Filter伪协议读取源码

需要注意读取形式选择base64编码,否则根据if(strstr($res,"flag")) die("DaMie!")会无法正常回显flag

网址后补充:

&username[]=0&password[]=1&url=php://filter/read=convert.base64-encode/resource=&target=/../../../../flag

得到源码(base64编码后)

base64解码得到flag

Reverse

321check_in

下载附件打开,发现.exe文件甚至没有办法运行,出现闪退的情况

结合题目提示,查壳发现,.exe文件应该是用exe4j打包的

下载exe4j正常运行程序,那么为什么一定要正常运行程序呢?

因为java反编译的工具不能直接反编译exe文件,需要得到class文件或者jar包

而通过exe4j打包的exe程序在exe运行时会在...jar的缓存文件

(虽然但是,我并没有找到attachment.jar

但是根据文件生成时间,在e4jD82C.tmp_dir1698213950文件夹下找到了readme.jar

用jd-gui反编译readme.jar,在主函数中发现flag

babyida

查壳,无壳32位程序,ida32打开,结合题目提示,在字符串窗口中查找flag,发现一个假的flag

题目提示学下动调秒了,于是动态调试看看,用x32dbg打开,找到Can you find the flag?关键字符串处

其实这个地方下面已经看到flag了,但别直接列写当flag了,还是得动调一下(别问我怎么知道的

接着往下分析,在00A21467处发现关键判断语句 jne babyida.A2147B

说明若上一句cmp的结果为不相等,会跳转至00A2147B,输出“wrong!”

根据上面一大堆的汇编指令大致可以看到,进行比较的字符串(即目标flag)存储在几个寄存器中

直接在00A2147B处添加断点,让程序运行到这先别跳转,然后查看寄存器的值

运行程序,F9程序停在00A2147B处,在eax中发现flag值

(一点也不baby

ez_z3

查壳,64位UPX壳,upx -d脱壳,发现居然报错了

面向搜索引擎,发现是文件加壳之后又进行了混淆,发现确实如此,区段名进行了更改

于是010editor打开文件,把文件里的XYU全部改成UPX,再upx -d,脱壳成功

拖入ida查看,分析各函数的大致作用,然后可以先用z3约束求解器解出数据,脚本如下

脚本原文链接:NSSCTF-RoundX easy_z3 | 逆向上分之路 (ctttttttt.github.io)

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
from z3 import *

a1 = [BitVec("num[%d]" % i, 32) for i in range(20)]
s = Solver()
s.add(
20 * a1[19] * 19 * a1[18]
+ 14 * a1[13]
+ 13 * a1[12]
+ 11 * a1[10] * 10 * a1[9]
+ 30 * a1[5]
+ 5 * a1[4]
+ a1[0]
+ 2 * a1[1]
- 3 * a1[2]
- 4 * a1[3]
- 7 * a1[6]
+ 8 * a1[7]
- 9 * a1[8]
- 12 * a1[11]
- 16 * a1[15] * 15 * a1[14]
- 17 * a1[16]
- 18 * a1[17] == 2582239)
s.add(
20 * a1[19] * 19 * a1[18]
+ 14 * a1[13]
+ 13 * a1[12]
+ 11 * a1[10] * 10 * a1[9]
+ 30 * a1[5]
- 7 * a1[6]
+ 8 * a1[7]
- 9 * a1[8]
+ 5 * a1[4]
+ 3 * a1[2]
+ 2 * a1[1] * a1[0]
- 4 * a1[3]
- 12 * a1[11]
- 16 * a1[15] * 15 * a1[14]
- (18 * a1[17]
+ 17 * a1[16]) == 2602741)
s.add(19 * a1[18]
+ 18 * a1[17]
+ 14 * a1[13] * 13 * a1[12]
+ 12 * a1[11] * 11 * a1[10]
+ 9 * a1[8]
+ 7 * a1[6] * 30 * a1[5]
+ a1[0]
- 2 * a1[1]
- 4 * a1[3] * 3 * a1[2]
- 5 * a1[4]
+ 8 * a1[7]
- 10 * a1[9]
- 15 * a1[14]
- 17 * a1[16] * 16 * a1[15]
- 20 * a1[19] == 2668123)
s.add(20 * a1[19] * 19 * a1[18]
+ 14 * a1[13]
+ (13 * a1[12] + 11 * a1[10] - 12 * a1[11]) * 10 * a1[9]
+ 30 * a1[5]
+ 5 * a1[4]
+ a1[0]
+ 2 * a1[1]
- 3 * a1[2]
- 4 * a1[3]
- 7 * a1[6]
+ 8 * a1[7]
- 9 * a1[8]
- 16 * a1[15] * 15 * a1[14]
- 17 * a1[16]
- 18 * a1[17] == 2520193)
s.add(
18 * a1[17]
+ 17 * a1[16]
+ 15 * a1[14]
+ 13 * a1[12] * 12 * a1[11]
+ 10 * a1[9]
+ 9 * a1[8] * 8 * a1[7]
+ 3 * a1[2] * 2 * a1[1] * a1[0]
- 4 * a1[3]
- 5 * a1[4]
- 30 * a1[5]
- 7 * a1[6]
- 11 * a1[10]
- 14 * a1[13]
- 16 * a1[15]
- 19 * a1[18]
- 20 * a1[19] == 8904587)
s.add(
18 * a1[17]
+ 7 * a1[6] * 30 * a1[5] * 5 * a1[4]
+ 4 * a1[3]
+ 8 * a1[7]
+ a1[0]
- 2 * a1[1]
- 3 * a1[2]
- 9 * a1[8]
- 11 * a1[10] * 10 * a1[9]
- 16 * a1[15] * (13 * a1[12] + 12 * a1[11] - 14 * a1[13] - 15 * a1[14])
- 17 * a1[16]
- 19 * a1[18]
- 20 * a1[19] == 1227620874)
s.add(20 * a1[19] * 19 * a1[18]
+ 17 * a1[16]
+ 14 * a1[13]
+ 13 * a1[12]
+ 12 * a1[11] * 11 * a1[10] * 10 * a1[9]
+ 7 * a1[6] * 30 * a1[5]
+ 5 * a1[4]
+ 3 * a1[2]
+ a1[0]
+ 2 * a1[1]
+ 4 * a1[3]
+ 8 * a1[7]
- 9 * a1[8]
- 16 * a1[15] * 15 * a1[14]
- 18 * a1[17] == 1836606059)
s.add(
20 * a1[19] * 19 * a1[18]
+ 16 * a1[15] * 15 * a1[14]
+ 14 * a1[13]
+ 13 * a1[12]
+ 12 * a1[11]
+ 7 * a1[6] * 30 * a1[5]
+ 5 * a1[4]
+ 2 * a1[1] * a1[0]
- 3 * a1[2]
+ 4 * a1[3]
+ 8 * a1[7]
- 9 * a1[8]
- 10 * a1[9]
- 11 * a1[10]
- 17 * a1[16]
- 18 * a1[17] == 8720560)
s.add(20 * a1[19] * 19 * a1[18]
+ 14 * a1[13]
+ 13 * a1[12]
+ 11 * a1[10] * (10 * a1[9] + 30 * a1[5] + 5 * a1[4] + 4 * a1[3] - 7 * a1[6] + 8 * a1[7] - 9 * a1[8])
+ a1[0]
+ 2 * a1[1]
- 3 * a1[2]
- 12 * a1[11]
- (16 * a1[15] - 17 * a1[16] - 18 * a1[17]) * 15 * a1[14] == 11387045)
s.add(
20 * a1[19] * 19 * a1[18]
+ 16 * a1[15] * 15 * a1[14]
+ 14 * a1[13]
+ 11 * a1[10] * 10 * a1[9]
+ 9 * a1[8]
+ 3 * a1[2]
+ a1[0]
- 2 * a1[1]
+ 4 * a1[3]
- 5 * a1[4]
- 30 * a1[5]
- 7 * a1[6]
+ 8 * a1[7]
- 12 * a1[11]
- 13 * a1[12]
- 17 * a1[16]
- 18 * a1[17] == 7660269)
s.add(20 * a1[19] * 19 * a1[18]
+ 14 * a1[13]
+ 13 * a1[12]
+ 11 * a1[10] * 10 * a1[9]
- 12 * a1[11]
+ a1[0]
+ 2 * a1[1]
- (4 * a1[3] * 3 * a1[2]
- 5 * a1[4]
- 30 * a1[5])
- 7 * a1[6]
+ 8 * a1[7]
- 9 * a1[8]
- 16 * a1[15] * 15 * a1[14]
- 17 * a1[16]
- 18 * a1[17] == 2461883)
s.add(
14 * a1[13]
+ 11 * a1[10] * 10 * a1[9]
+ 9 * a1[8] * 8 * a1[7]
+ 7 * a1[6]
+ 2 * a1[1] * a1[0]
- 4 * a1[3] * 3 * a1[2]
- 5 * a1[4]
- 30 * a1[5]
- 12 * a1[11]
- 13 * a1[12]
- 15 * a1[14]
- 17 * a1[16] * 16 * a1[15]
- 18 * a1[17]
- 19 * a1[18]
- 20 * a1[19] == -966296)

s.add(
14 * a1[13]
+ 13 * a1[12]
+ (11 * a1[10] * 10 * a1[9] + 30 * a1[5] + 5 * a1[4] + 3 * a1[2] + 4 * a1[3] - 7 * a1[6] + 8 * a1[7] - 9 * a1[8])
* 2
* a1[1]
+ a1[0]
- 12 * a1[11]
- 15 * a1[14]
- 16 * a1[15]
- 17 * a1[16]
- 18 * a1[17]
- 20 * a1[19] * 19 * a1[18] == 254500223
)
s.add(
16 * a1[15] * 15 * a1[14]
+ 14 * a1[13]
+ 11 * a1[10] * 10 * a1[9]
+ 7 * a1[6] * 30 * a1[5]
+ a1[0]
- 2 * a1[1]
- 3 * a1[2]
- 5 * a1[4] * 4 * a1[3]
+ 8 * a1[7]
- 9 * a1[8]
- 12 * a1[11]
- 13 * a1[12]
- 17 * a1[16]
- 18 * a1[17]
- 19 * a1[18]
- 20 * a1[19] == 6022286
)
s.add(
18 * a1[17]
+ 16 * a1[15]
- 17 * a1[16]
+ 14 * a1[13]
+ 12 * a1[11]
+ 11 * a1[10] * 10 * a1[9]
+ 30 * a1[5]
+ 5 * a1[4]
+ 4 * a1[3] * 3 * a1[2]
+ 2 * a1[1] * a1[0]
- 9 * a1[8] * 8 * a1[7] * 7 * a1[6]
- 13 * a1[12]
- 15 * a1[14]
- 19 * a1[18]
- 20 * a1[19] == -636956022
)
s.add(
20 * a1[19] * 19 * a1[18]
+ 13 * a1[12]
+ 12 * a1[11]
+ 11 * a1[10] * 10 * a1[9]
+ 7 * a1[6]
+ 30 * a1[5]
+ 5 * a1[4]
+ 3 * a1[2] * 2 * a1[1] * a1[0]
- 4 * a1[3]
- 9 * a1[8] * 8 * a1[7]
- 14 * a1[13]
- 15 * a1[14]
- 16 * a1[15]
- 17 * a1[16]
- 18 * a1[17] == 10631829
)
s.add(
20 * a1[19] * 19 * a1[18]
+ 16 * a1[15]
- 17 * a1[16]
- 18 * a1[17]
+ 15 * a1[14] * 14 * a1[13]
+ 13 * a1[12]
+ 11 * a1[10] * 10 * a1[9]
- 12 * a1[11]
+ 7 * a1[6]
+ (4 * a1[3] - 5 * a1[4] - 30 * a1[5]) * 3 * a1[2]
+ a1[0]
+ 2 * a1[1]
+ 8 * a1[7]
- 9 * a1[8] == 6191333
)
s.add(
14 * a1[13]
+ 10 * a1[9] * 9 * a1[8] * 8 * a1[7]
+ 5 * a1[4]
+ 4 * a1[3] * 3 * a1[2]
+ 2 * a1[1] * a1[0]
- 7 * a1[6] * 30 * a1[5]
- 11 * a1[10]
- 13 * a1[12] * 12 * a1[11]
- 16 * a1[15] * 15 * a1[14]
- 18 * a1[17] * 17 * a1[16]
- 20 * a1[19] * 19 * a1[18] == 890415359
)
s.add(
20 * a1[19]
+ 19 * a1[18]
+ 18 * a1[17]
+ 16 * a1[15]
- 17 * a1[16]
+ 12 * a1[11]
+ 11 * a1[10]
+ 10 * a1[9]
+ 9 * a1[8]
+ 30 * a1[5]
+ a1[0]
+ 4 * a1[3] * 3 * a1[2] * 2 * a1[1]
- 5 * a1[4]
- 7 * a1[6]
+ 8 * a1[7]
- 13 * a1[12]
- 14 * a1[13]
- 15 * a1[14] == 23493664
)
s.add(
20 * a1[19] * 19 * a1[18]
+ 13 * a1[12]
+ 12 * a1[11]
+ 10 * a1[9]
+ 3 * a1[2] * 2 * a1[1]
+ a1[0]
- 4 * a1[3]
- 5 * a1[4]
+ 8 * a1[7] * 7 * a1[6] * 30 * a1[5]
- 9 * a1[8]
- 11 * a1[10]
- 14 * a1[13]
- 16 * a1[15] * 15 * a1[14]
- 17 * a1[16]
- 18 * a1[17] == 1967260144
)
print(s.check())
for i in a1:
print(s.model()[i].as_long(), end=",")
#跑出来的结果是[104,97,104,97,104,97,116,104,105,115,105,115,102,97,99,107,102,108,97,103]

得到参数,写脚本得到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
#include<stdio.h>
#include<string.h>
#include<windows.h>

DWORD Get_254D0(DWORD d254D0[20])
{
int i = 0;
DWORD d25050[20] = {0X1207,0X4CA0,0X4F21,0X39,0X1A523,0X23A,0X926,0X4CA7,
0X6560,0X36,0X1A99B,0X4CA8,0X1BBE0,0X3705,0X926,0X77D3,
0X9A98,0X657B,0X18,0X0B11};
for( i ; i < 20 ; i++)
{
d254D0[i] = d25050[i];
}
}

DWORD Get_25520(DWORD d25520[20], DWORD d254D0[20],DWORD a[20])
{
for ( int i = 0; ; ++i )
{
int v2 = i;
if ( v2 >= 20 )
break;
int v3 = i;
d25520[v3] = *(a + 20 - i - 1) ^ d254D0[i];
}
}

DWORD sub_1124E(DWORD a1, DWORD a2)
{
unsigned int v3;
v3 = 1;
while ( a2 )
{
if ( (a2 & 1) != 0 )
v3 *= a1;
a1 = a1 * a1 % 1000;
a2 >>= 2;
}
return v3;
}

int main()
{
DWORD a[20] = {104,97,104,97,104,97,116,104,105,115,105,115,102,97,99,107,102,108,97,103};
DWORD d254D0[20] = {0};
DWORD d25520[20] = {0};
DWORD d25000[20] = { 0x07, 0x07, 0x07, 0x09, 0x05, 0x06, 0x07, 0x07, 0x07,
0x09, 0x07, 0x07, 0x05, 0x07, 0x07, 0x07, 0x05, 0x07,
0x09, 0x07};
DWORD Str[20];
DWORD v3;

Get_254D0(d254D0);
Get_25520(d25520,d254D0,a);

//这里用的是爆破的方法
for(DWORD p = 0 ; p < 20 ; p++)
{
for( DWORD k = 0 ; k < 127 ; k++)
{
Str[p] = k;
if( d25520[p] == sub_1124E(Str[p], d25000[p]) )
{
printf("%c",k);
break;
}

}
}

}
//T1e_z3_1s_v1r9_3asy!

base64

ida64打开,一眼看去像是base64编码格式的字符串,但直接base64解码显然不行

题目提示需要修复base64编码,还需要运行linux命令

但幸运的事发生了!

做re题的习惯性做法,先查看字符串列表,直接发现了...

这个就是base64替换的新表,上脚本,运行得到flag

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

str1 = "ZXFWtmKgDZCyrmC5B+CiVfsyXUCQVfsyZRFzDU4yX2YCD/F5Ih8="

string1 = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbn/+m1234567890"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

print(base64.b64decode(str1.translate(str.maketrans(string1,string2))))

odscript

查壳,32位无壳,运行一下发现是弹窗输入注册码,随便输提示有错误,然后再读读曹操身边的故事

输入注册码,显示结果都是以弹窗的形式,可以尝试去寻找Messagebox函数

ida打开,发现sub_4016E0和sub_401720中都有调用Messagebox函数

可以合理猜测是两个结果的弹窗,一个是显示正确,一个是显示错误

在x32dbg里这两处都下断点,随机输入注册码,发现程序停在sub_401720处,无弹窗,再F9出现错误弹窗,确定想法是对的

于是看sub_4016E0,通过IDA交叉引用看到,.text:00401617引用了该函数

来到.text:00401617

看到一些关键函数

跟进,发现是正是sub_401630调用了CString::CString函数

阅读代码,大致意思是判断a2指向的一段内存和this指向的一段内存是否相等

那么调试时停在sub_401630处F7单步即可查看里面的内容

那么问题来了

上面试过,随便输的注册码,即使在sub_401630处添加了断点,F9也是停在sub_401720处

说明上方还有跳转,直接跳过sub_401630起的正确弹窗区域,跳到sub_401720错误弹窗去了

向上查看,果然有问题

阅读最上面红框内容,知道需要满足输入的字符串长度为0x21,即33个字符

得到以上信息,就可以开始调试了,x32dbg打开

在00401630处设置断点,F9,输入随机的长度为33字符的字符串

程序停在00401630处,F7单步步入,跳转比较函数后发现flag

(或者我写wp的时候才发现00401666处已经有了