SHCTF misc复现


题目附件:

1
2
3
4
通过百度网盘分享的文件:SHCTF
链接:https://pan.baidu.com/s/1iUFU_fOe4Xxfiipxg_bQpw?pwd=w9v1
提取码:w9v1
--来自百度网盘超级会员V3的分享

shctf2023

[WEEK1]签到题

下载附件

base解密,赛博厨子一把梭

最后flag为

1
flag{this_is_flag}

[WEEK1]Jaeger lover

题目描述:do you know Pacific Rim?提示环太平洋

下载附件

010查看图片,发现末尾有base编码

base解密

翻译一下

看图片是环太平洋风暴赤红,直接搜索风暴赤红操作系统

得到答案:

1
Tri-Sun Horizon Gate

steghide隐写

1
steghide extract -sf Typhoon.jpg -p "Tri-Sun Horizon Gate" 

得到压缩包密码:

1
.*+#1Ao/aeS

解压压缩包

一看图片就宽高有问题,宽高一把梭

得到key:

1
K34-759183-191 

outsecret隐写

最后flag为

1
flag{A1l_boys_aRe_Jaeger_L0ver!!}

[WEEK1]message

下载附件

pdu解码

最后flag为

1
flag{ba978405-b1c8-847c-8e69-f62177e4c087}

[WEEK1]也许需要一些py

题目描述:这flag怎么没大没小的捏

下载附件

010先看无后缀文件,发现是png文件,补全文件头

保存后再次查看图片

得到flag的md5值:63e62fbce22f2757f99eb7da179551d2

压缩包有提示:

1
- .... .. ... .---- ... -.-- ----- ..- -.- . -.--

摩斯解码

得到压缩包密码:THIS1SY0UKEY

解压压缩包

根据题目要求改为小写:this1sy0ukey

写一个匹配字符爆破大小写碰撞脚本

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

def md5(s):
md5 = hashlib.md5()
s = s.encode('utf-8')
md5.update(s)
return md5.hexdigest()
def check(k,s):
ind = 0
ss = ''
for i in s:
if i.isalpha():
if k[ind] == '1':
ss += i.upper()
else:

ss += i
ind += 1
else:
ss += i
return ss

ans = '63e62fbce22f2757f99eb7da179551d2'
s = 'pNg_and_Md5_SO_GreaT'.lower()

cnt = 0 #字母数量
for i in s:
if i.isalpha():
cnt += 1

for i in range(2**cnt):
k = bin(i)[2:].zfill(cnt)
out = check(k,s)
if md5(out) == ans:
print('flag{'+out+'}')
break

运行得到flag

最后flag为

1
flag{Png_AnD_md5_so_GReAt}

[WEEK1]ez-misc

下载附件

查看文本文件内容

01转二维码

扫描二维码

得到压缩包密码:

1
hit_k1sme4_4_fun

解压压缩包得到无后缀文件,010查看无后缀文件

发现是压缩包,填加后缀.zip

发现提示有二进制01数字,二进制转字符串

Kali 有个字典叫 rockyou很出名,尝试字典爆破

得到压缩包密码:palomino

解压压缩包

词频统计

最后flag为

1
flag{SHyk1sme4}

[WEEK1]请对我使用社工吧

题目描述:k1sme4的朋友考到了一所在k1sme4家附近的大学,一天,k1sme4的朋友去了学校对面的商场玩,并给k1sme4拍了一张照片,你能找到他的学校吗?

flag格式:flag{xx省xx市xx区_xx大学}

下载附件

图片上一个qq号,在qq相册中看到一张b站的图片

查看k1sme4的b站

看到评论:黄河入海,k1sme4回家!!!!!

百度搜索黄河入海口得知是山东东营

图片上发现是在万达广场,百度搜索东营的万达广场

对面就是中国石油大学

最后flag为

1
flag{山东省_东营市_东营区_中国石油大学} 

[WEEK1]可爱的派蒙捏

题目描述:派蒙藏了一些东西,你能找到他们吗

下载附件

binwalk试试

发现藏有压缩包

foremost提取

查看两个文本文件内容

文件对比

在线网址:https://text-compare.com/

最后flag为

1
flag{4ebf327905288fca947a}

[WEEK1]steganography

下载附件

使用010editor打开图片careful.jpg末尾有base64编码

base解码

得到一部分压缩包密码:

1
12ercs.....909jk

查看careful1.jpg属性

得到第二部分压缩包密码:xqwed

组合得到压缩包密码:

1
12ercsxqwed909jk

解压压缩包得到flag

最后flag为

1
flag{4d72e4f3-4d4f-4969-bc8c-a2f6f7a4292c}

[WEEK2]远在天边近在眼前

下载附件

linux解压压缩包得到flag

倒序

新学的方法:

exp:

1
print(__import__('zipfile').ZipFile('yztb.zip', 'r') .infolist()[-1].filename.replace('/', '')[::-1])

最后flag为

1
flag{TH15_l5_rE41ly_e45y_a1r1gH7?_a28415d80662}

[WEEK2]可爱的洛琪希

题目描述:把你的详细信息都交出来!

下载附件,解压压缩包发现有密码

尝试伪加密

查看文本文件内容

base解码

保存图片,查看图片属性

010查看图片发现末尾有东西

hex解码+维吉尼亚解码

最后flag为

1
flag{Roxy_daisuki!}

[WEEK2]奇怪的screenshot

下载附件

一眼 CVE-2023-28303 Win11截图漏洞

https://github.com/frankthetank-music/Acropalypse-Multi-Tool

使用前需要安装两个模块

启动软件,点击恢复工具

选择win11类型

一通操作得到新图片

保存图片重新打开,看到是百家姓编码

百家姓解码

最后flag为

1
flag{CVE-2023-28303-Win11-Snipping-t00l-is-n0t-Secure}

[WEEK2]图片里的秘密

题目描述:盲僧能出水银鞋吗?

下载附件

binwalk试试

发现藏有rar压缩包,binwalk -e 提取

得到一张图片,根据题目提示猜测是盲水印

最后flag为

1
flag{Blind_Water_Mark!}

[WEEK2]表里的码

题目描述:细狗配粗人,j_0k3r配我 )

下载附件

根据题目描述猜测是excel文件,改后缀.xlsx打开,全选发现是29x29的格子

随机选择几个格子检查一下就可以发现有些格子的字体形式是加粗的,而有些未加粗

粗的涂黑,得到二维码

扫描二维码

最后flag为

1
flag{j0k3r_1s_my_wif3}

[WEEK2]喜帖街

题目描述:喜帖街里就得有“喜帖”,ok?

下载附件

查看音频频谱

得到key,steghide隐写

ook解码

最后flag为

1
flag{w@v2txt_s0_Int3r3st1ng!}

[WEEK3]ez_usb

下载附件

发现是usb流量

工具一把梭

得到两个东西

第一个:

1
526172211a0700cf907300000d000000008008002f507424943500200080002000000002a3021b4d577f06551d33080020080000666c61672e7478747CC34ada98dA7d0200f035680325f68663724792af0b91cE86c1b46ed4b180d5a8A7C626ADb5ceb2fF8CF24104c43d7b00400700

发现是rar文件

保存下来

第二个:

1
adabb04a5e9a6c33

猜测是压缩包密码

解压压缩包,查看文本找到flag

最后flag为

1
flag{c6bd1c7bcfef89ffbf59d86ccaf97d3c}

[WEEK3]请再次对我使用社工吧

题目描述:很好的城市,很大的水域,很美的山,有山有水但没有海,爱来自山东。

你能找到我脚下这座山的名字吗?

flag格式:flag{xx省xx市/区xx市/区_xx山}

下载附件

键线索是图片中有一座类似烈士陵园,题目描述说是山东省的 那直接百度搜索山东省烈士陵园,搜到这个的时候感觉挺像

但百度地图发现旁边没有山

因为我是土生土长的泰安人,对一些新闻也比较了解,忽然就把思路转变会不会是我们新泰 的,之前看新闻报道,李林雨烈士,房浩烈士都荣归故里,带着猜测,百度地图新泰市革命 烈士陵园

发现附近是青云山 另一种思路,百度搜索房浩烈士

敖山指的是青云山

最后flag为

1
flag{山东省_泰安市_新泰市_青云山}

[WEEK3]做社工不如来签到

下载附件

内存取证,查看历史命令行

1
vol.py -f /home/kali/Desktop/neicun/challenge.raw --profile=Win7SP1x64 cmdscan

得到一串关键字符串

1
flag{this_is_your_key_to_open_some_file}

12345678作为vc容器挂载,密钥为flag{this_is_your_key_to_open_some_file}

查看挂载内容

fake_flag.txt

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
flag{just_a_fake_flagggggggg~~~~~}































































































































































































































































































encrypt-step3-CAST-128-key:1115172035abcdef

对文件夹中的进行内容处理,观察到有564个1kb的txt且里面的字符串长度都是564,考虑序号和字符串的对应关系,提取n.txt中的字符串的第n个字符:

exp:

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

directory_path = ''

result_characters = []

for i in range(1, 565):
filename = f"{i}.txt"
file_path = os.path.join(directory_path, filename)

with open(file_path, 'r') as file:
content = file.read()

if len(content) >= i:
character = content[i - 1]
result_characters.append(character)

result_string = ''.join(result_characters)

print(result_string)

运行得到

一眼zip文件啊,赛博厨子转换

解压压缩包得到

发现需要密码,提示为:username_hostname

查看系统用户名

1
vol.py -f /home/kali/Desktop/neicun/challenge.raw --profile=Win7SP1x64 printkey -K "SAM\Domains\Account\Users\Names"

查看计算机名

1
vol.py -f /home/kali/Desktop/neicun/challenge.raw --profile=Win7SP1x64 printkey -K "ControlSet001\Control\ComputerName\ComputerName"

得到压缩包密码

1
SOGREATNAME_WIN-RRI9T9SN85D

解压压缩包

得到提示结合cmdscan中存在在github上下载文件的操作,尝试在github搜索k1sme4,发现有一个encrypt.py

base58解密

对于较大的565.txt,使用file命令得到是ext3文件系统,使用mount挂载(里面东西没删干净,其实strings可以直接拿到密码):

1
2
3
file 565.txt

mount 565.txt /mnt

得到加密后的密文

1
2
Decrypt it and use it to get the flag:
\xfb"7 S:$y\xa9\xac\xd5\xf6\xae\x81^o\xda\x06 \xff\xaf9\xc7\x92

一个加密的zip文件,根据zip文件名可知密码是ip,用以下命令:

1
vol.py -f /home/kali/Desktop/neicun/challenge.raw --profile=Win7SP1x64 netscan

用ip:192.168.137.133解压压缩包,得到一张png

得到一张png,无法正常打开,拖入010发现是每四个字节逆序

写脚本恢复:

exp:

1
2
3
4
5
6
7
8
f1 = open('E:\\shegong\\ip\\keyyy.png', 'rb').read()
f1_len = len(f1)
f2 = open('E:\\shegong\\ip\\res.png', 'ab')
i = 0
while i < f1_len:
f2.write(f1[i:i+4][::-1])
i = i + 4
f2.close()

运行得到

获得第二步加密的密钥:

1
Xorrrrrrrrr_1s_s000000_fun

密文为:

1
\xfb"7 S:$y\xa9\xac\xd5\xf6\xae\x81^o\xda\x06 \xff\xaf9\xc7\x92

已知加密后的密文、加密方式和三组密钥,编写解密脚本:

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
from Crypto.Cipher import Blowfish, CAST

# 16字节密钥,必须是bytes类型
blowfish_key = b'k1s1115172035me4'

# 创建 Blowfish 解密对象
blowfish_cipher = Blowfish.new(blowfish_key, Blowfish.MODE_ECB)

# 要解密的 CAST-128 加密后的数据
cast_encrypted = b'\xfb"7 S:$y\xa9\xac\xd5\xf6\xae\x81^o\xda\x06 \xff\xaf9\xc7\x92'

# 使用 CAST-128 解密数据
cast_key = b'1115172035abcdef'
cast_cipher = CAST.new(cast_key, CAST.MODE_ECB)
xor_result = cast_cipher.decrypt(cast_encrypted)

# 定义用于异或操作的字符串
xor_key = "Xorrrrrrrrr_1s_s000000_fun"

# 将字符串转换为字节类型
xor_key_bytes = xor_key.encode("utf-8")

# 将 XOR 后的数据与异或键进行异或操作,以恢复 Blowfish 加密前的数据
blowfish_decrypted = bytes(b1 ^ b2 for b1, b2 in zip(xor_result, xor_key_bytes))

# 解密 Blowfish 加密后的数据
plaintext_bytes = blowfish_cipher.decrypt(blowfish_decrypted)

# 将字节数据转换回字符串
plaintext = plaintext_bytes.decode("utf-8")

print(f"解密后的明文: {plaintext}")

运行得到

用解得的明文作为密码再次挂载VC容器即可得到flag

最后flag为

1
flag{so0000_e4sy_forensics_And_decrypt!!!!!}

[WEEK3]尓纬玛

题目描述:恏渏怪哋②惟犸,芣確萣,侢看看,還湜恏渏怪

hint:no steganography

下载附件

扫描二维码发现不行

QRazyBox优先读纠错区,然而纠错区只有半个flag,完整flag在数据块里,涂掉纠错区,或者说涂掉错误的纠错区

就读正确的部分了

扫描二维码得到flag

最后flag为

1
flag{QRcOde_has_many_kindS_of_secre7s_NOw_y0U_knoW_l_De3b4e}

[WEEK3]strange data

题目描述:hint:

android data

adb shell getevent

https://www.kernel.org/doc/html/v4.14/input/event-codes.html

下载附件

查看文件

直接上脚本

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
import re
import matplotlib.pyplot as plt

#从getevent输出文件中读取原始数据
with open("data","r")as f:
data = f.readlines()

#创建两空列表用于存储X和y坐标
x_coordinates = []
y_coordinates = []
is_touching = False

plt.figure()
for line in data:
#使用正则表达式从每行中提取事件数据
match = re.match(r"([0-9a-f]+) ([0-9a-f]+) ([0-9a-f]+)",line)
if match:
event_type,event_code,value = map(
lambda x:int(x,16),match.groups())
if event_type == 3: #事件类型 3 代表触摸事件
if event_code == 0: #事件代码 0 代表 X 坐标
x = value
elif event_code == 1: #事件代码 1代表y 坐标
y = value
if x + y > 0 and is_touching:
x_coordinates.append(x)
y_coordinates.append(y)
elif len(x_coordinates) > 0:
plt.plot(y_coordinates,x_coordinates, marker='o',linestyle='-',markersize=2)
x_coordinates =[]
y_coordinates =[]
elif event_type == 1:
if event_code == 330: #事件代码 330 代表按压和抬起事件
if value == 0: #按压事件
is_touching = False
elif value == 1: #抬起事件
is_touching = True
elif event_type == 0:
pass
else:
print(event_type,event_code,value)
plt.show()

运行得到flag

最后flag为

1
flag{miiii1_sm4rt_p3n_1s_So_Fun!}

shctf2024

[Week1] 签到题

描述:

1
关注公众号 **山东汉任信息安全技术有限公司**回复 **SHCTF我又踏马来辣!** 得到`flag`


最后flag为SHCTF{Welc0m3_t0_SHCTF2024}

[Week1]有WiFi干嘛不用呢?

题目描述:

1
k1每次来陪睡都要连WiFi,请帮他获取该wifi密码。flag提交方式:SHCTF{WiFi密码}。

下载附件

查看may文件夹

把may中所有的数据提取出来做成字典
cat may/* > passwd.txt

删一下[]

aircrack-ng爆破

最后flag为flag{0TUMVxz0JrUSDxHG}

[Week1]真真假假_遮遮掩掩!

题目描述:

1
假的就是假的,真的就是真的,遮遮掩掩的有什么用!

下载附件

伪加密

解压压缩包

密码提示:一眼掩码爆破

解压压缩包得到

最后flag为SHCTF{C0ngr@tu1at1ons_On_Mast3r1ng_mAsk_aTT@ck5!}

[Week1]拜师之旅①

题目描述:

1
一年一度的洛琪希美照大赏开始了,正好Nanian233下周要去拜师pngMaster, 参加入门考试. 就拿这个先练练手吧

下载附件

010查看文件

png文件,缺少文件头补上即可

保存打开文件

宽高一把梭

最后flag为SHCTF{ohhh_rooooxy!}

[Week1]Rasterizing Traffic

题目描述:

1
Man! What can I say!!!  

下载附件

ctf-natA一把梭

查看图片

光栅
利用Raster-Terminator-main工具

需要修改下脚本内容,二维改为三维
z[:, i::x, :] = img[:, i::x, :]改为z[:, i::x] = img[:, i::x]

运行脚本

查看文件

最后flag为SHCTF{1111z_tr@ff1c_aNaLys13}

[Week1]Quarantine

题目描述:

1
shenghuo2发来的文件被隔离了,也许通过一些取证技术可以在提取到的数据文件中发现什么信息.......

下载附件

Windows defender的隔离文件,rc4解密
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
#!/usr/bin/env python3

from Crypto.Cipher import ARC4



key = [

0x1E, 0x87, 0x78, 0x1B, 0x8D, 0xBA, 0xA8, 0x44, 0xCE, 0x69, 0x70, 0x2C, 0x0C,

0x78, 0xB7, 0x86, 0xA3, 0xF6, 0x23, 0xB7, 0x38, 0xF5, 0xED, 0xF9, 0xAF, 0x83,

0x53, 0x0F, 0xB3, 0xFC, 0x54, 0xFA, 0xA2, 0x1E, 0xB9, 0xCF, 0x13, 0x31, 0xFD,

0x0F, 0x0D, 0xA9, 0x54, 0xF6, 0x87, 0xCB, 0x9E, 0x18, 0x27, 0x96, 0x97, 0x90,

0x0E, 0x53, 0xFB, 0x31, 0x7C, 0x9C, 0xBC, 0xE4, 0x8E, 0x23, 0xD0, 0x53, 0x71,

0xEC, 0xC1, 0x59, 0x51, 0xB8, 0xF3, 0x64, 0x9D, 0x7C, 0xA3, 0x3E, 0xD6, 0x8D,

0xC9, 0x04, 0x7E, 0x82, 0xC9, 0xBA, 0xAD, 0x97, 0x99, 0xD0, 0xD4, 0x58, 0xCB,

0x84, 0x7C, 0xA9, 0xFF, 0xBE, 0x3C, 0x8A, 0x77, 0x52, 0x33, 0x55, 0x7D, 0xDE,

0x13, 0xA8, 0xB1, 0x40, 0x87, 0xCC, 0x1B, 0xC8, 0xF1, 0x0F, 0x6E, 0xCD, 0xD0,

0x83, 0xA9, 0x59, 0xCF, 0xF8, 0x4A, 0x9D, 0x1D, 0x50, 0x75, 0x5E, 0x3E, 0x19,

0x18, 0x18, 0xAF, 0x23, 0xE2, 0x29, 0x35, 0x58, 0x76, 0x6D, 0x2C, 0x07, 0xE2,

0x57, 0x12, 0xB2, 0xCA, 0x0B, 0x53, 0x5E, 0xD8, 0xF6, 0xC5, 0x6C, 0xE7, 0x3D,

0x24, 0xBD, 0xD0, 0x29, 0x17, 0x71, 0x86, 0x1A, 0x54, 0xB4, 0xC2, 0x85, 0xA9,

0xA3, 0xDB, 0x7A, 0xCA, 0x6D, 0x22, 0x4A, 0xEA, 0xCD, 0x62, 0x1D, 0xB9, 0xF2,

0xA2, 0x2E, 0xD1, 0xE9, 0xE1, 0x1D, 0x75, 0xBE, 0xD7, 0xDC, 0x0E, 0xCB, 0x0A,

0x8E, 0x68, 0xA2, 0xFF, 0x12, 0x63, 0x40, 0x8D, 0xC8, 0x08, 0xDF, 0xFD, 0x16,

0x4B, 0x11, 0x67, 0x74, 0xCD, 0x0B, 0x9B, 0x8D, 0x05, 0x41, 0x1E, 0xD6, 0x26,

0x2E, 0x42, 0x9B, 0xA4, 0x95, 0x67, 0x6B, 0x83, 0x98, 0xDB, 0x2F, 0x35, 0xD3,

0xC1, 0xB9, 0xCE, 0xD5, 0x26, 0x36, 0xF2, 0x76, 0x5E, 0x1A, 0x95, 0xCB, 0x7C,

0xA4, 0xC3, 0xDD, 0xAB, 0xDD, 0xBF, 0xF3, 0x82, 0x53

]

key = bytes(key)



DIR = ''

files = [

    '5760650163482280EF03C48A97277F7E490A0761'

]

out_files = ['entries', 'resource_data', 'resources']



for i in range(len(files)):

    with open(DIR + files[i], 'rb') as f:

        ct = f.read()



    cipher = ARC4.new(key)

    pt = cipher.decrypt(ct)



    with open(out_files[i], 'wb') as f:

        f.write(pt)

运行生成文件

010查看文件

base解密

保存为zip

利用rockyou字典爆破密码

解压压缩包

最后flag为SHCTF{NObody_d0_no4_1ov4_ttthe_Cute_shenghuo2}

[Week2] Schneider

题目描述:

1
Use Schneider tool open the file and you will get the flag.

下载附件
根据题面这个题想让我们找Schneider tool,Schneider是一家做工业软件的公司,旗下有产品EcoStruxure Operator Terminal Expert,这个软件导出的项目后缀恰好是.vxdz,那我们就下载这个软件打开附件即可

在UserGroup1找到Password,左上角ShowPassword即可

还有一种方法
利用src-2020-0010
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
#!/usr/bin/env python3

"""

Schneider Electric EcoStruxure Operator Terminal Expert Hardcoded Cryptographic Key Information Disclosure Vulnerability

SRC ....: SRC-2020-0010

CVE ....: N/A

File ...: EcoStruxure Operator Terminal Expert V3.1.iso

SHA1 ...: 386312d68ba5e6a98df24258f2fbcfb2d8c8521b

Download: https://download.schneider-electric.com/files?p_File_Name=EcoStruxure+Operator+Terminal+Expert+V3.1.iso

"""

import os

import re

import sys

import glob

import zlib

import zipfile

from Crypto.Cipher import DES3



# hardcoded values

key  = [ 202, 20, 221, 52, 225, 154, 5, 123, 111, 219, 11, 199, 145, 27, 200, 129, 254, 222, 253, 119, 213, 134, 72, 78 ]

iv   = [ 95, 21, 44, 250, 112, 73, 114, 155 ]

des3 = [ 93, 51, 117, 85, 189, 76, 88, 200, 231, 127 ]

plen  = 8



def check_equal(iterator):

   # if all the values are the same then its padding...

   return len(set(iterator)) <= 1



def _inflate(decoded_data):

    return zlib.decompress(decoded_data, -15)



def _deflate(string_val):

    compressed = zlib.compress(string_val)

    return compressed[2:-4]



def delete_folder(top) :

    for root, dirs, files in os.walk(top, topdown=False):

        for name in files:

            os.remove(os.path.join(root, name))

        for name in dirs:

            os.rmdir(os.path.join(root, name))

    os.rmdir(top)



def decrypt_file(filename):

    print("(+) unpacking: %s" % filename)

    decr = DES3.new(bytes(key), DES3.MODE_CBC, bytes(iv))

    default_data = bytes([8, 8, 8, 8, 8, 8, 8, 8])

    with open(filename, "rb") as f:

        if list(f.read(10)) == des3:

            encrypted = f.read()

            raw_data = decr.decrypt(encrypted)

            if not check_equal(list(raw_data)):

                raw_data = _inflate(raw_data)

        else:

            f.seek(0)

            raw_data = f.read()

    # now that we have the decrypted data, let's overwrite the file...

    with open(filename, "wb") as f:

        f.write(raw_data)



def encrypt_file(filename):

    print("(+) packing: %s" % filename)

    encr = DES3.new(bytes(key), DES3.MODE_CBC, bytes(iv))

    with open(filename, "rb") as f:

        packed_data = f.read()

        if not packed_data == bytes([8, 8, 8, 8, 8, 8, 8, 8]):

            packed_data = _deflate(packed_data)

        # padding for encryption, same as schneider

        pad = plen - (len(packed_data) % plen)

        # if we just have padding in there, then dont bother adding more padding now...

        if len(packed_data) != 8:

            for i in range(0, pad):

                packed_data += bytes([pad])

        encr_data = bytes(des3) + encr.encrypt(packed_data)

    with open(filename, "wb") as f:

        f.write(encr_data)



def unpack(project):

    z = os.path.abspath(project)

    output_dir = os.path.splitext(z)[0]

    print("(+) unpacking to %s" % output_dir)

    if os.path.exists(output_dir):

        print("(-) %s already exists!" % output_dir)

        return False

    zip_obj = zipfile.ZipFile(z, 'r')

    zip_obj.extractall(output_dir)

    zip_obj.close()

    # two levels deep, we can do more if we need to

    for file in list(set(glob.glob(output_dir + '/**/**/*.*', recursive=True))):

        decrypt_file(file)

    print("(+) unpacked and decrypted: %s" % project)



def pack(project):

    z = os.path.abspath(project)

    output_dir = os.path.splitext(z)[0]

    # two levels deep, we can do more if we need to

    for file in list(set(glob.glob(output_dir + '/**/**/*.*', recursive=True))):

        if os.path.basename(file) != "[Content_Types].xml":

            encrypt_file(file)



    zf = zipfile.ZipFile(project, "w")

    for file in list(set(glob.glob(os.path.basename(output_dir) + '/**/**/*.*', recursive=True))):

        zf.write(file, "/".join(file.strip("/").split('/')[1:]))



    zf.close()

    delete_folder(output_dir)

    print("(+) packed and encrypted: %s" % project)



def main():

    if len(sys.argv) != 3:

        print("(+) usage: %s[options]" % sys.argv[0])

        print("(+) eg: %s sample.vxdz unpack" % sys.argv[0])

        print("(+) eg: %s sample.vxdz pack" % sys.argv[0])

        sys.exit(0)

    f = sys.argv[1]

    c = sys.argv[2]

    if c.lower() == "unpack":

        unpack(f)

    elif c.lower() == "pack":

        pack(f)

    else:

        print("(-) invalid option!")

        sys.exit(1)



if __name__ == '__main__':

    main()

python3运行

最后flag为SHCTF{ez_ICS_checkin_right?}

[Week2] 屁

题目描述:

1
什么,原来你也玩术力口!不过你别想偷走我的工程文件!我可是把分卷压缩的文件名打乱了,这次你想解压也解压不了!

下载附件

分卷压缩的 ZIP 文件通常以 z01z02 等后缀来标记数据顺序,但题目中的文件名已被打乱。虽然数据总量不多,但直接进行全排列会有 3628800 种可能,计算量较大。然而,文件的头和尾都有特征,确定这两个部分后,排列组合的数量可以减少到 40320 种。

找到文件头以 PK 开头的文件,将其后缀改为 ZIP 打开,可以得到压缩文件的 「CRC」 和大小,这些信息可以用来判断是否解压成功。

还可以看到压缩方法采用 「Deflate」 算法 ,没有加密,这意味着「数据区」的文件数据可以直接使用 zlib.decompress 进行解压。

最小的文件即为文件尾。

删除 ZIP 的文件头尾后,编写代码进行爆破


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

import itertools

import zlib

from tqdm import tqdm




def read_binary_file(file_path):

    with open(file_path, "rb") as f:

        return f.read()




def try_decompress(data):

    try:

        decompressed_data = zlib.decompress(data, -zlib.MAX_WBITS)

        return decompressed_data

    except zlib.error:

        return None




def calculate_crc32(data):

    if len(data) != 105734:

        return None

    return zlib.crc32(data) & 0xFFFFFFFF




def main():

    directory = "E:\\脚本合集\\赛题脚本\\shctf2024\\屁"  # 指定目录

    # 指定开头和结尾文件

    start_file = os.path.join(directory, "E:\\脚本合集\\赛题脚本\\shctf2024\\屁\\屁.z66")

    end_file = os.path.join(directory, "E:\\脚本合集\\赛题脚本\\shctf2024\\屁\\屁.z40")

    files = [os.path.join(directory, f) for f in os.listdir(directory) if os.path.isfile(os.path.join(directory, f))]



    # 移除开头和结尾文件

    files.remove(start_file)

    files.remove(end_file)



    # 生成剩余文件的全排列

    permutations = itertools.permutations(files)



    # 计算排列的总数

    total_permutations = sum(1 for _ in permutations)



    # 重置 permutations 以便再次迭代

    permutations = itertools.permutations(files)



    # 已知的CRC32值

    known_crc32 = 0x0B6E238E



    for perm in tqdm(permutations, total=total_permutations, desc="Processing"):

        # 将开头和结尾文件固定在首尾

        combined_files = [start_file] + list(perm) + [end_file]

        # 连接所有文件的二进制内容

        combined_data = b"".join(read_binary_file(file_path) for file_path in combined_files)



        # 尝试解压缩

        decompressed_data = try_decompress(combined_data)



        if decompressed_data is not None:

            # 计算解压后数据的CRC32值

            calculated_crc32 = calculate_crc32(decompressed_data)



            # 检查CRC32值是否匹配

            if calculated_crc32 == known_crc32:

                print("解压成功!")

                # 输出解压后的数据

                with open("E:\\脚本合集\\赛题脚本\\shctf2024\\屁\\屁.svp", "wb") as f:

                    f.write(decompressed_data)

                print("解压后的数据已保存到 屁.svp")

                break

    else:

        print("没有找到可以成功解压的排列顺序。")




if __name__ == "__main__":

    main()

成功解压后得到术力口工程文件

使用 Synthesizer V 打开

Synthesizer V 使用 ARPABET 作为音素标准,仔细查找可以找到一个字典 https://github.com/cmusphinx/sphinxtrain/blob/master/test/res/communicator.dic.cmu.full

1
S.,H.,C.,T.,F.,Open Curly Bracket,B.,L.,four,C.,K.,Underscore,M.,Y.,seven,H.,colon,five,H.,four,N.,H.,three,Close Curly Bracket

最后flag为SHCTF{BL4CK_MY7H:5H4NH3}

[Week2] 拜师之旅②

下载附件

题目描述玩了个谐音梗”挨打”(IDAT),使用tweakpng工具

可以发现实质是两张图片放到了一起,一张4995为底 ,一张5185为底

假flag的图片为前者优先显示,删掉对应的三个IDAT块

按F7预览,得到flag

最后flag为SHCTF{1t_is_@_lucky_idat}

[Week2] 弄假成真

下载附件

参考https://www.bilibili.com/video/BV1Au4m1g7vT/
运用QRazyBox

QRazyBox的Data Sequence Analysis的功能

首先是右下角 4 个码元组成的块 用鼠标左键轻点就能读到这个块的信息:

接着是上面那块

手撸
用 QRazyBox 自带的 Padding Bits Recovery 功能补上部分像素

通过 Reed-Solomon Decoder 还原出二维码所存数据

Base64解密

010查看文件

发现藏着png文件,分离

扫描二维码

base换表

最后flag为SHCTF{THis_F14GTHis_F14G}

[Week2] 遮遮掩掩?CCRC!

题目描述:

1
我说今天必须爆破出来, 熊说:不可

下载附件

crc爆破
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
import zlib



flag=''

crc_list =[0x42582aaa, 0xbce853c2, 0x211fdb00, 0x70c6b6fe,0x63ad436c,0x84bd90bd,0x55769db8,0x8a2a7829,0x5c66f4cd,0x8454f318,0x8c88cc6a,0x7eb2adde,0x078776df,0x21509dfb,0x0c975144,0xf51f79ac,0xf262197e,0x8b5919f7,0x8b5919f7,0x11d0d7ba,0x5c66f4cd,0x38457732,0xcdff1d1b,0xcbf2ddf2,0x7af934d6,0x21509dfb,0x5bf57dc6,0xd617d273,0xf9d901d6,0xcbf2ddf2,0x21509dfb,0xe98e7a37,0xc94d437d,0x1bbe8b92,0x7dc6ef2a,0x0f1e9f47,0x5c66f4cd,0x54f6ab19,0x3b6a9c6f,0x9e80fced,0x94f0383e,0xcc7fcc02,0x8eca39aa,0x7b2fb1b3,0x62dd04ef,0x211fdb00]

for target_crc in crc_list:

    for i in range(256):

        for j in range(256):

            for k in range(256):

                data = bytes([i,j,k])

                crc = zlib.crc32(data) & 0xffffffff

                if crc == target_crc:

                    data=data.decode()

                    print(f"Found matching data: {data}")

                    flag+=data

                    break

print('解密得到:'+flag)

运行得到

与熊论道

最后flag为SHCTF{F0ll0w_TaFFy_m1@0_ThanK5_M1@0}

[Week3] The Secret of Tokenizer

题目描述:

1
Easy chall...If you're confused, try to figure out what the chall title means

下载附件

bkcrack明文攻击
ZIP已知明文攻击深入利用 - FreeBuf网络安全行业门户

#准备已知明文
echo 89504E470D0A1A0A0000000D49484452 | xxd -r -ps > png_header

#攻击获得密钥
bkcrack.exe -C challenge.zip -c challenge/letstalktokens.png -p png_header

攻击修改压缩包密码
bkcrack.exe -C challenge.zip -k 390aeba0 029c2d16 8c38b960 -U new.zip good

解压压缩包得到

后面的otf文件丢到fontdrop网站查看,https://fontdrop.info/

在Data的description能看到密文

然后在搜索后加上看压缩包的那个png文件提示发现其实这个是文本经过GPT的tokenization之后形成的token,用处是让GPT更好的理解输入文本的语义,句法和语义,然后其实在github搜也能找到tiktoken这个模块(这里选用GPT3.5)然后直接写脚本解密,然后在这篇文章也有写

https://blog.csdn.net/sinat_37574187/article/details/131210574

exp:

1
2
3
4
5
6
7
8
9
import tiktoken

enc = tiktoken.encoding_for_model("gpt-3.5-turbo")

text = [8758, 1182, 37, 90, 12174, 6803, 2632, 62, 22, 71, 18, 2632, 18, 31, 43, 2406, 11237, 1159, 564, 18, 77, 16, 89, 18, 5544, 1267, 19, 267, 18, 81, 12340, 92]

flag = enc.decode(text)

print(flag)

运行得到flag

最后flag为SHCTF{Oh_U_R_7h3_R3@L_LLM_Tok3n1z3rs_M4st3r!!!}

[Week3]拜师之旅③

题目描述:

1
Nanian233成功解出了pngMaster的模拟题, 大师很是欣赏, "那么现在,开始入门考试吧"

下载附件

png拿到使用zsteg可以看到藏了一个压缩包并且得到密码:#P@SSSSSSW0RD!!

foremost提取压缩包

解压压缩包

提取压缩包并解压得到2.png,放大可以观察到有很多像素点,并且在exif处得到提示:real_size=320*180

和原图刚好差12倍,使用脚本提取新图后得到flag
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
from PIL import Image



img = Image.open('E:\\脚本合集\\赛题脚本\\shctf2024\\还原12倍\\2.png')

w = img.width

h = img.height

img_obj = Image.new("RGB",(w//12,h//12))



for x in range(w//12):

    for y in range(h//12):

        (r,g,b)=img.getpixel((x*12,y*12))

        img_obj.putpixel((x,y),(r,g,b))



img_obj.save('E:\\脚本合集\\赛题脚本\\shctf2024\\还原12倍\\3.png')

运行得到

最后flag为SHCTF{YOU_P@55_THe_Ex@m!}

[Week3]xor

题目描述:

1
sorry, I delete the flag python xor.py rm -f xor.py flag

下载附件


创建一个文件flag(/data/flag)并写入flag字符串
然后创建/randomfile.py并执行:

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

def generateRandomBytearray(length):
    random_bytes = bytearray()
    for _ in range(length):
        random_bytes.append(random.randint(0, 255))
    return random_bytes
    
arrs = []
flag = bytearray(open("data/flag", "rb").read())
files = ["data/flag"]

for i in range(256):
    byte_arr = generateRandomBytearray(len(flag))
    arrs.append(byte_arr)
    files.append(f"data/file{i}")
    with open(f"data/file{i}", "wb") as file:
        file.write(byte_arr)

于是在/data/目录下得到了file0~file255这256个文件

再创建一个xor.py(/data/xor.py)

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import xor  
from os import listdir

files = [file for file in listdir() if file != 'xor.py' and file != 'flag']
flag = bytearray(open("flag", "rb").read())
for file in files:
    file = open(file, 'rb').read()
    flag = xor(flag, file)

print(flag)
with open('xor', 'wb') as f:
    f.write(flag)

执行后得到了xor(/data/xor)文件
题目描述给出了最后执行的两条命令:

1
2
python xor.py  
rm -f xor.py flag

于是形成了题目附件所展示的文件集合
exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import xor

from os import listdir



files = [file for file in listdir() if file != 'solve.py']

flag = b''

for file in files:

    file = open(file, 'rb').read()

    flag = xor(flag, file)



print(flag)

运行得到

最后flag为SHCTF{Y0u_F!nd_Th3_F1@g}

[Week3]完

题目描述:

1
想对你说的话,都在歌词里了,怎么看到歌词呢?想想如果没有在线音乐软件那2000年是怎么听音乐的

下载附件

提示了2000,软件为foobar2000,导入进去
查看属性

注释是rabbit,后面发现key,010查看音频

rabbit解密

最后flag为SHCTF{h0pe_y0u_love_th1s_song_Of_Eason}

[Week4] 天命人

题目描述:

1
2
3
4
5
6
出题: J_0k3r
难度: 中等

"人,我保住了。经,我取到了。俺老孙啥功名不要,只求回到这花果山终老,过过逍遥*子。上面的天王老子信不过我,我懂 让你小子带着虾兵蟹将过来虚张声势,又想唬我回去做神仙,我也懂。我不懂的是……,为什么不给我flag"

先短再长,从左到右

下载附件

查看描述.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
flag格式为SHCTF{}   
同一条数据的按键之间用_连接 不同条数据之间的用+连接
如:01827d828000003908200100eb8d076f0000ffff000016009a1fe604bc4a0f03ff80000000800000000005040000000000505e0f032918005e95af2cd222910d
这条数据中按键为A和B下一条数据按键为C和D
则:SHCTF{A_B+C_D}

只考虑按键不考虑摇杆量,同一条数据按键连接顺序为按键名称由长到短 如果长度相同则按从左到右顺序
所有按键名称如下:
方向:N W E S
L1 L2 L3
R1 R2 R3
Square
Cross
Circle
Triangle
Create
Options
Touchpad
Mute
PS

打开流量文件

没思路,找到出题人博客翻到

ps5手柄usb&蓝牙流量协议 - J_0k3r

找到脚本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
def decode_hid_data(hex_string):
# 将十六进制字符串转换为字节串
bytes_data = bytes.fromhex(hex_string)

# 解析数据包
report_id = bytes_data[0]
left_stick_x = bytes_data[1]
left_stick_y = bytes_data[2]
right_stick_x = bytes_data[3]
right_stick_y = bytes_data[4]
l2_trigger = bytes_data[5]
r2_trigger = bytes_data[6]
vendor_defined = bytes_data[7]
# 解析 Hat switch 按键
hat_switch = bytes_data[8] & 0x0F
hat_direction = ""
if hat_switch == 0x0:
hat_direction = "N"
elif hat_switch == 0x1:
hat_direction = "NE"
elif hat_switch == 0x2:
hat_direction = "E"
elif hat_switch == 0x3:
hat_direction = "SE"
elif hat_switch == 0x4:
hat_direction = "S"
elif hat_switch == 0x5:
hat_direction = "SW"
elif hat_switch == 0x6:
hat_direction = "W"
elif hat_switch == 0x7:
hat_direction = "NW"
elif hat_switch == 0x8:
hat_direction = "Neutral"
square_button = (bytes_data[8] >> 4) & 0x01
cross_button = (bytes_data[8] >> 5) & 0x01
circle_button = (bytes_data[8] >> 6) & 0x01
triangle_button = (bytes_data[8] >> 7) & 0x01
l1_button = bytes_data[9] & 0x01
r1_button = (bytes_data[9] >> 1) & 0x01
l2_button = (bytes_data[9] >> 2) & 0x01
r2_button = (bytes_data[9] >> 3) & 0x01
create_button = (bytes_data[9] >> 4) & 0x01
options_button = (bytes_data[9] >> 5) & 0x01
l3_button = (bytes_data[9] >> 6) & 0x01
r3_button = (bytes_data[9] >> 7) & 0x01
ps_button = bytes_data[10] & 0x01
touchpad_button = (bytes_data[10] >> 1) & 0x01
mute_button = (bytes_data[10] >> 2) & 0x01

# 输出按键状态
print("Square" if square_button else "")
print("Cross" if cross_button else "")
print("Circle" if circle_button else "")
print("Triangle" if triangle_button else "")
print(hat_direction if hat_direction else "")
print("L1" if l1_button else "")
print("R1" if r1_button else "")
print("L2" if l2_button else "")
print("R2" if r2_button else "")
print("Create" if create_button else "")
print("Options" if options_button else "")
print("L3" if l3_button else "")
print("R3" if r3_button else "")
print("PS" if ps_button else "")
print("Touchpad" if touchpad_button else "")
print("Mute" if mute_button else "")

# 示例数据包的十六进制字符串表示
hex_string = "01827d828000003908200100eb8d076f0000ffff000016009a1fe604bc4a0f03ff80000000800000000005040000000000505e0f032918005e95af2cd222910d"

# 解码并输出按键
decode_hid_data(hex_string)
SHCTF{L1+E_R2+R2_Square+R2_Cross+L2_R2+L3_R2+PS_Options}

[Week4]今日无事,勾栏听曲。

题目描述:

1
昨晚上在梦里和k1妹妹旅游去了,睡醒之后怅然若失,于是我把印象里的地点画了下来,请提交我们的旅游地点。提交格式SHCTF{MD5(旅游地点)}。

下载附件

music文件,根据文件名猜测是音频文件,但直接加后缀不行,因为这个是pcm原始数据,需要用audacity导入原始数据

打开发现音频可以正常播放

观察波形,放大发现有非常明显的高频(880)和低频(440),我们读取转01

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
import numpy as np
from scipy.io import wavfile
from scipy.fft import fft
# 设置参数
sample_rate = 44100 # 采样率
duration_per_bit = 0.01 # 持续时间
low_freq = 440 # 低频表示0
high_freq = 880 # 高频表示1
threshold = 660 # 分界线
input_file = 'E:\\脚本合集\\赛题脚本\\shctf2024\\处理低高频\\music.wav'
rate, data = wavfile.read(input_file)
samples_per_bit = int(sample_rate * duration_per_bit)
bit_sequence = []
for i in range(0, len(data), samples_per_bit):
bit_data = data[i:i + samples_per_bit]
spectrum = np.abs(fft(bit_data))[:samples_per_bit // 2]
freqs = np.fft.fftfreq(len(bit_data), 1 / sample_rate)[:samples_per_bit // 2]
dominant_freq = freqs[np.argmax(spectrum)]
if dominant_freq < threshold:
bit_sequence.append('0')
else:
bit_sequence.append('1')
bit_string = ''.join(bit_sequence)
output_txt_file = 'E:\\脚本合集\\赛题脚本\\shctf2024\\处理低高频\\result.txt'
with open(output_txt_file, 'w') as f:
f.write(bit_string)

运行得到

01文本放进赛博厨子一把梭

保存为rar文件,打开意外错误

发现是2.9老版本的winrar进行压缩的,5.0及以上版本rar格式压缩算法不一样

参考:

RAR文件格式学习(了解)_rar文件头-CSDN博客

RAR 5.0 archive format

RAR文件格式分析 | Sp4n9x’s Blog

010查看rar压缩包文件

HEAD_TYPE的字节是7A,将其改成74

保存并打开

打开draw.txt

draw.txt由0123组成,0是空格,|是1,-是2,/是3,\是4,画图

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
from PIL import Image, ImageDraw, ImageFont

# 设定对应关系
char_map = {
'0': ' ',
'1': '|',
'2': '-',
'3': '/',
'4': '\\',
}

# 读取txt文件
with open('E:\\脚本合集\\赛题脚本\\shctf2024\\画图\\draw.txt', 'r') as f:
lines = f.readlines()

# 替换数字为字符
lines = [[char_map[ch] for ch in line.strip()] for line in lines]

font_size = 10
width = len(lines[0]) * font_size
height = len(lines) * font_size

image = Image.new('RGB', (width, height), color='white')
draw = ImageDraw.Draw(image)

font = ImageFont.load_default()

for y, line in enumerate(lines):
for x, ch in enumerate(line):
draw.text((x * font_size, y * font_size), ch, font=font, fill='black')

# 保存图片
output_image = 'E:\\脚本合集\\赛题脚本\\shctf2024\\画图\\draw.png'
image.save(output_image)

运行得到

发现是一座塔,一共七层,搜一下七层高塔

发现是西安大雁塔,md5加密一下

最后flag为SHCTF{21506a1b677c7254879d86bbec5b4ec9}

[Week4] 音频里怎么有一幅画?

题目描述:

1
2
3
4
5
6
出题: pjx1314
难度: 中等

哈哈!你的画已经被我的 key 污染了,并且我还将 key 深深藏在另一个音频里,你休想轻易揭开画里的秘密!

hint:注意文件名,你可以永远相信 CRC 的判断【并新增题目描述】

下载附件

查看deep.wav文件的属性,找到密码:MARETU

根据文件名猜测deepsound隐写

得到rar

010查看rar文件

发现这实际上是一个zip压缩包文件,删除 RAR! 字符,并将 KP 改为 PK,然后运行 ZIP 模板

根据文件头信息,能发现文件名长度 frFileNameLength 的值被设置为 3,直接将其修改为 7。但只修改文件名长度会导致模板运行错误,并且运行结果也没有中心目录区,这说明数据区内容识别错误,我们还需要修改一个值。

同时调整 frCompressedSizefrFileNameLength22361167,然后重新运行 ZIP 模板。

在注释里,我们发现了零宽字符。将 010 Editor 拉到最下面也可以看到这些字符。通过 zwsp-steg 解密这些零宽字符。

zwsp-steg 解密这些零宽字符

Offdev.net - Zero-width space steganography javascript demo

解密后得到字符串Pass:Z3r0-W1D7H,由于没有其他需要解密的地方,且压缩包无法正常解压,推测这就是压缩包的密码。

将数据区和目录区的加密标志位都改为 09

输入密码后,成功解压出 key.wav 文件

使用 AU 打开 key.wav,查看频谱图。上方是 Aztec Code,下方是被污染的汉信码。

扫描 Aztec Code 后得到时间:00:11:67

Aztec Code 反相,与下方的汉信码抵消,得到完整的汉信码。

由于官方wp写的比较简洁,我就为了让小白更容易理解操作我就写详细一点步骤

1.首先用audacity导入key.wav

2.分离立体声为单声道

3.选择上面的Aztec那个声道进行反相

4.选择全部声道进行混音并渲染到新轨道

查看新轨道的声道频谱

保存在桌面,用AU打开查看频谱

汉信码在线识别

得到提示:链接,内容介绍了 AI 生成可扫码图像,目前没什么用,回过头来查看flag.wav

使用 Audacity 导入 flag.wav

发现 flag.wav 的图片明显被污染,猜测污染源就是这两个码。根据 Aztec Code 的时间 00:11:67,推测两个二维码音频的起点是 00:11:67

这一步我也说详细点

1.先导入key.wav和flag.wav

2.将key.wav拖到00:11:67,这一步需要先找大致位置

然后缩放拖到准确位置

3.分离立体声为单声道

4.将汉信码、flag其中一个声道进行反相

5.将汉信码和flag两个声道进行混音并渲染到新轨道

查看新轨道声道的频谱

结合汉信码的提示,推测这是 AI 绘画生成的二维码。在 GitHub 搜索关键词 AI QRcode,找到一个暴力识别项目

Tokeii0/LoveLy-QRCode-Scanner: A script to brute force decode QR codes, mainly for decoding blurred or AI-generated QR codes that can’t be scanned by WeChat.

使用LoveLy-QRCode爆破扫描二维码

最后flag为SHCTF{AI_4rt_1s_M4gica1}

注:

1
在这里感谢一下pjx1314师傅,没有他我对照官方wp复现不出来,是他一步步教我如何复现出来,pjx1314师傅出的两道题都颇有收获,一道分卷压缩,一道音频反相以及ai二维码

复现太不容易了,喵!


文章作者: yiqing
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 yiqing !
  目录