解题过程

(本题有两个故事线,实际步骤可能与此wp有所不同)
第一步:使用binwalk分析出有zlib数据,但是无法使用binwalk -e或foremost分离出有效文件,在010editor中查看图片。
image.png
第二步:010 editor中看到最后一个IDAT数据块长度异常,导出这段zlib数据。
image.png

第三步:观察IDAT标识后面的87 9C两个字节,恢复成zlib数据头标识78 9C,写脚本将此段zlib数据解压缩,可得到一个rar压缩包。注意解压缩的zlib数据应该是去掉IDAT-length、IDAT-type、IDAT-crc的数据部分,即(78 9C ….. )。
image.png

  1. import zlib
  2. data = open("zlib_hex_data.txt", 'r',
  3. encoding="utf-8").read().replace(" ", "").replace("\n",
  4. "").strip()
  5. data_dec = zlib.decompress(bytes.fromhex(data))
  6. print(data_dec[:100])
  7. with open("zlib_data.rar", 'wb') as wf:
  8. wf.write(data_dec)
  9. #b'Rar!\x1a\x07\x01\x00J\x97,}\x0c\x01\x05\x08\x00\x07\x01\x01\x96\x9c\x87\x80\x00\xf7\xea}W\x13\x03\x02\xbd\x00\x04\xbd\x00\x00\x90:\xd1\xdc\x80\x00\x00\x03CMT\xe5\xa6\x82\xe6\x9e\x9c\xe4\xbd\xa0\xe4\xb8\x8d\xe7\x9f\xa5\xe9\x81\x93\xe8\xbf\x99\xe6\x98\xaf\xe4\xbb\x80\xe4\xb9\x88\xe4\xb8\x9c\xe8\xa5\xbf\xef\xbc\x8c\xe5\x8f\xaf\xe4\xbb\xa5\xe5\x8e\xbb\xe7\x9c\x8b

解压压缩包可得flag2,注意压缩包中有提示请先获取flag1。
第四步:继续找flag1,分析最开始的那张图片,实际使用zsteg和exiftool可以发现其他可以信息。
exiftool看到Copyright有可以十六进制:翻译过来是:dynamical-geometry。
image.png
zsteg发现这张图片除了存在extradata外,在中也有脏数据。
image.png
使用StegSolve检查隐写。
image.png
第五步:导出十六进制,这里不能直接打开图片,可使用foremost将PNG快速分离出来,最后得到一张590x590,大小为979KB的图片,注意如果仅去掉PNG字符前数据并改后缀为PNG也能正常查看图片,但会阻塞下一步分析像素操作。
第六步:到这里只有一张色彩值杂乱的PNG图片,分析其像素。

  1. from PIL importImage
  2. image = Image.open(r'C:\Users\during\Downloads\00000000.png')
  3. allpixels = []
  4. for x in range(image.width):
  5. for y in range(image.height):
  6. allpixels.append(image.getpixel((x, y)))
  7. print(len(allpixels)) # 348100
  8. print(allpixels[:4])
  9. # [(40, 176, 80), (37, 181, 75), (1, 253, 3), (2, 252, 4)]
  10. # 0x50 0x4B 0x03 0x04

第七步:取前四个字节即可看出,像素第三列隐藏着压缩包十六进制,批量提取并保存成zip压缩包,使用第四步得到的密码:dynamical-geometry解密,得到flag1文件。

  1. from PIL importImage
  2. image = Image.open(r'C:\Users\during\Downloads\00000000.png')
  3. allpixels = []
  4. for x in range(image.width):
  5. for y in range(image.height):
  6. if image.getpixel((x, y)) == (0, 0, 0):
  7. continue
  8. allpixels.append(image.getpixel((x, y))[2])
  9. hex_datalist = [str(hex(i))[2:].zfill(2) for i in allpixels]
  10. print("".join(hex_datalist)[:100])
  11. # 504b0304140009006300caa05753d904fdb22a4b0500dce856000f000b00666c6167312d61736369692e73746c0199070001
  12. with open("outpur.txt", 'w') as wf:
  13. wf.write("".join(hex_datalist))

第八步:记事本打开文件后,是3D打印模型中的STL格式文件,STL格式分为ascii、binary格式,使用在线工具或开源工具查看模型即可。这一步并不需要脑洞,拷贝stl-ascii格式数据百度即可查询到STL文件格式的有关内容。
image.png
根据flag1的STL格式,将flag2也尝试用STL预览器查看:
image.png