通过这道题可以加深对png结构的了解,相关考点在国内很少见,是很不错的一道题 ~
附件链接:https://pan.baidu.com/s/1oyXUbwRP0EFALdR6A-ZWjA 提取码:vurw
Simulating the human brain is currently impossible, but perceptron is trying to do that!
Hint 1:There are many same sizes IDAT chunks in perceptron, are all of them necessary?
Hint 2:There are other PNGs too. Try to recover them.
下载附件得到一张png图片,按照惯例先分析图片,用zsteg
分析
可以发现zlib区块,当我们用zsteg分析正常的图片的时候,是不会得到这个信息的(如下图)
由此说明题中所给的图片有一些问题
再用010editor查看图片的信息,我们查找789C
,可以发现在这个图片中存在三个789C
先来补充一下相关的知识(感谢夏风师傅的指点):
IDAT
块是储存图像数据的块,在这个块中存放在图像真正的数据信息,也就是说没有它就看不到图像zlib datastream
表示,它储存在一个IDAT
块中IDAT
区块,在IDAT
块中只会出现一个zlib
块789C
在png文件中为zlib
的标志位zlib
数据块只有一个标志位,即只会出现一次789C
到这里就会发现问题了,在这个png文件中有三个789C
,也就是说在这个图片中还隐藏着另外两张图片的信息
由于IDAT
中出现多个zlib
块时只会识别第一个,所以我们尝试将第一个zlib
块删去,使其识别第二个块
删去从29h
到3047h
的第一个zlib
部分,观察得到的图片效果
出现这种情况我们考虑是否图片的宽高出现了问题,用FzWjScJ师傅的脚本爆破一下,将宽高有可能的图片全部生成(此处建议在一个单独的文件夹中跑程序,因为会生成很多图片……)
#python3
import binascii
from Crypto.Util import number
p = open('2.png','rb').read()
# print(p[0x14:0x17]+chr(0xaf).encode()[-1:])
count = 0
for a in range(0x00,0xff):
data = p[:0x12] + chr(0x04).encode() + chr(a).encode()[-1:] + p[0x14:0x16] + chr(0x00).encode() + chr(0xa0).encode()[-1:]
# print(binascii.crc32(data))
p2 = p[:0x12] + chr(0x04).encode() + chr(a).encode()[-1:] + p[0x14:0x16] + chr(0x00).encode() + chr(0xa0).encode()[-1:] + p[0x18:0x1d] + number.long_to_bytes(binascii.crc32(data)&0xffffffff) + p[0x21:]
p1 = open(str(count)+'.png','wb')
count += 1
p1.write(p2)
p1.close()
这里的宽高并非是图片本身的宽高,如果校验CRC32你会发现宽高是错误的,图片的核心数据部分是IDAT,这里我们只是借用了png的其他区块让图片显示而已。
当分辨率为1132x160时可以成功看到图片
当然这并不是flag,但是证明了我们方法没有问题,下面我们再用同样的方法处理第三个zlib
块
当分辨率为1084x160时得到第二个图片
而真正的flag就是这个图片的内容:SUSEC{7he_r3aL_flag_iZ_tH15}
想要做出这道题,需要对png文件结构有一定的了解,而这道题也可以帮助我们更好的了解png的结构,了解这种比较少见的png图片隐写方式,总的来说是一道非常不错的题!
这个比赛的另一道misc题也很不错,想要了解的话可以戳这里~