比赛:CTFshow 5ctf
简称:废物杯
平台:https://ctf.show
开始:2021/2/22 20:21
结束:2021/2/23 20:21
规则:
1 比赛期间可以随意讨论,题目难度为5难度
2 公平竞技,独立比赛
3 服务器不要爆破,不要攻击服务器,不要扫描!!!
4 奖品:总榜前5,每人50元京东代金卷
5 题目征集:https://shimo.im/docs/YP3tVqPJTxD6jhdt
比赛排名:
rank score username
1 6053 Mr水函
2 5063 FW_Mumuzi
3 4431 hssec
4 3561 V3geD4g
5 3410 pcs
6 2810 ⎝Lazzaro⎠
7 2585 atao
8 2555 feng
9 2128 donmen@铜匠
10 1782 战胜阿狸,从我做起
11 1637 spaceman
12 1619 kangtongxue
13 1604 i_kei
14 1604 ENJOEY
15 1433 vincent
16 1417 zealot
17 1394 Y4tacker
18 1389 darkwang
19 1232 zcy2018
20 1199 lorlike
21 1119 lastsward
22 1031 sonder
23 1009 N1k0la
24 994 RookieZ996
25 994 Nuyooah
26 764 pc1215
27 764 watanuki
28 740 lu0sf
29 732 屁孩
30 732 B1ack1out3
31 732 Ra1n0nm3
32 732 owod
33 692 duck0123
34 666 FANGXIE
35 666 Zoe
36 656 7herightp4th
37 631 shyshy
38 631 g4_simon
39 625 werewolfcjj
40 531 1u1u
41 526 striving
42 526 A99
43 500 ordertensor
44 496 Jan
45 494 f1hgb
46 494 r4yn
47 494 Ricky
48 494 夜中空想
49 494 try2be
50 494 MoonBack
51 494 Cha0s
52 477 aaa
53 468 ty1024
54 459 β-AS
55 454 pl1rry
56 245 神说要有光.
57 238 qianwen
58 238 newbie99
59 238 Tkxagzs_3
60 238 yuchouxuan
61 238 GOTG
62 238 WankkoRee
63 238 aliga
64 238 As1def
65 238 Neve3no
66 238 Scr1pt
67 238 syyu
题目WP
杂项部分
题目名称:Just Another 拼图
附件:puzzle.zip
题目内容:史上最简单的拼图misc题!贴心到连序号都已经全部标注好,令gaps彻底失业、眼科医院纷纷倒闭!唯一的问题是图里好像没有flag?这点小问题应该无关紧要吧。
flag:ctfshow{Sorry_Mario_but_princess_is_here}
解题过程:
拿到压缩包后先解压,得到12张jpg图片。一眼可以看出能按序号拼成4x3的大图,但是拼好后图里确实没有flag,还说flag在别的图里。那就只能从其他地方下手。
Linux下发现图片全都无法正常查看,说明二进制数据肯定被动过手脚。strings命令看一下,发现所有图片都包含IDAT字符串,10.jpg还包括IHDR字符串。那么很明显,一张png图片被拆成12个IDAT块(其中一块还包括IHDR块),然后藏在了12张jpg图片的二进制数据里面。进一步用十六进制编辑器查看可以发现,IDAT块的数据都是正好插在jpg的文件尾标记FF D9前面。从而可以提取出这12段数据,再拼接上png文件头和文件尾就可以得到原来的png图片。
先写脚本提取所有的数据:
`path = 'C:/Users/Administrator/Desktop/Just Another 拼图/puzzle/puzzle'
data = [''] * 12
for i in range(12):
data = open(path + str(i) + '.jpg', 'rb').read()
HEAD = 0x89504E470D0A1A0A.to_bytes(8, 'big')
IHDR = data[10][0x29EA : 0x2A03]
IDAT = [''] * 12
for i in range(12):
n = data.find(b'IDAT') - 4
IDAT = data[n : -2]
print(len(IDAT))
接下来需要排列IDAT块的顺序,很明显10.jpg里连着IHDR块的IDAT是第一块,11.jpg里长度最短的IDAT是最后一块,其他块的顺序不明,暂且先按序号排起来:
PNG = HEAD + IHDR + IDAT[10]
for i in range(10):
PNG += IDAT
PNG += IDAT[11]
out = open(path + '.png', 'wb')
out.write(PNG)
out.close()
`
注意Windows下没有IEND块也可以显示PNG图片,所以文件尾暂且不用管。打开图片看一下:
只有最上方一部分显示正确,说明目前只有第一个IDAT块位置是正确的。接下来就要手动排列所有的IDAT块直到整张图片显示完整,使用tweakpng工具:
如图,使用Move up功能,每次把一块IDAT移到第二位,保存后用Windows照片查看器实时查看PNG图片,如果正确显示的部分变多就说明顺序正确。目前的第二块肯定是错误的,因此这一步最多只需要试九次。如图为找到第二块IDAT后的情况:
接下来找第三块IDAT,理论上最多只需要试七次:
重复以上步骤,全程最多只需要试(9+8+7+6+5+4+3+2+1 = ) 45次,但实际上比如第三块,按顺序来只需要试一次就可以得到正确结果。因此全程需要尝试的次数远低于45次,验题时试下来大概在20次左右。
最后把全部IDAT块排列正确得到图片:
flag:ctfshow{Sorry_Mario_but_princess_is_here}