Lamber's Blog

图片隐写简记

字数统计: 2k阅读时长: 7 min
2022/11/16

图片隐写一把梭流程总览

这篇文章适用于以下场景——在一场CTF中如果你实在解不出自己本方向的题目(比如你是一个RE选手,但RE实在是超出能力范围太多),并且你又想在比赛结束前做点什么(不想干巴巴的等WriteUp)。那么你可以参考本文章去尝试着处理一下MISC题目,该文章完全傻瓜式教程。如果想了解具体原理,那你不就成了个MISC选手?(如果你真的想转行,图片隐写的原理在百度上还是能够搜到一大堆的)

  1. 下载图片,观察图片内容是否会有hint
  2. 右键查看图片属性
  3. Stegsolve判断图片是否存在LSB隐写
  4. 扔进binwalk看图片中是否有隐藏文件
  5. HxD直接编辑图片十六进制数据(查看隐藏的线索,提取隐藏的文件,修复损坏的图片)
  6. 对于gif图片的处理

具体操作如下所示

1. 观察图片

  1. 首先将题目中所给的图片下载下来,初步观察图片中有什么内容,有些时候一道隐写题做不下去了,就是因为忽略了图片中最原始的信息。
  2. 观察完图片的内容之后,右键查看图片的属性。有些时候出题者会将flag直接放在备注里面,或者在备注里面放一点hint。

2. Stegsolve处理LSB隐写

  1. 用Stegsolve将图片打开,然后狂点下面这个箭头按钮(往左往右都可以),可能直接拿到flag,也可能会遇到出题人所留下的hint。
  1. 在上面一排功能栏处选择Analyse–>Data Extract,并按照以下顺序进行操作。那么有可能在右边文本框处拿到flag或者hint。也有可能左边的十六进制码能构成新的图片或者其它文件(遇到这种情况就点击下面的Save Bin将十六进制码保存下来并将其后缀名改为文件头所对应的文件后缀名,文件头所对应的文件后缀名请参考下面第四点)

3. 扔进binwalk里面

如果以上方法没有发现任何线索,那么可以扔进binwalk看看图片里是否夹杂着其他文件,使用方法大致如下(binwalk还有一个-e参数,可以自动提取文件中的夹杂文件,不过我比较喜欢手动提取)。binwalk的扫描结果界面如图,注意两个箭头的位置,第一个箭头表示该数据所对应的十六进制码的位置,可以根据此位置来将对应数据的十六进制码复制粘贴出来,完成一个手动提取的过程。第二个箭头则是对数据信息的一个简易描述,比如第一横排,说明了该文件是一个jpg格式的图片。很显然,第二个方框处的描述说明着,在这张jpg图片里面还隐藏着另外一张jpg图片(Ps:至于如何对十六进制码进行操作,请看下面第四点)

4. HxD(winhex, 010editor)进行图片处理

首先你得知道常用文件头与文件尾

文件后缀名 文件头 文件尾
jpg FF D8 FF E1 FF D9
png 89 50 4E 47 AE 42 60 82
gif 47 49 46 38 00 3B
zip 50 4B 03 04 50 4B
rar 52 61 72 21

重点说明一下PNG文件的格式(一般跟图片修复有关的题目,都是给的PNG图片)

图中蓝色部分为chunk[0]段
前四个字节00 00 00 0D:即为十进制13,代表数据块长度为13(该段为固定值)
之后四个字节49 48 44 52:是文件头数据块的标示(该段为固定值)
之后进入13位数据块,前8个字节中:前四位00 00 02 21表示图片宽,后四位00 00 02 19表示图片高
最后四位FF 5C 78 10:是png的CRC32校验码

  1. 把图片扔进HxD或者winhex或者010editor里面(个人推荐用HxD,感觉操作会舒服一些)。首先观察整体的十六进制码,可能直接得到flag,如果没能直接得到flag的话,也有可能在十六进制码中藏有一些hint(比如各种各样的编码什么的)
  1. 观察文件头部(如果题目给你的文件后缀名是png,但是你实际看到的文件头是jpg头,这时候你就可以将文件头改回png头,其实此情况特别少见,几乎可以忽略)
  2. 配合好binwalk使用,承接第三点,第三点中我们用binwalk发现在题图中还隐藏着另外一张图片,图片所对应的十六进制码的位置为0xB300,在HxD中定位操作如下。

确定隐藏图片的数据位置之后,就可以将这张隐藏图片的数据复制粘贴出来,保存为新的图片。有可能这张新的图片就是flag,也有可能拿到hint

  1. 通过CRC校验修复PNG图片,承接上文所重点提到的PNG图片格式。用以下脚本来检验图片的高度是否发生过修改(脚本只用修改crc32key部分和data部分)。效果图如下

将题中所给图片的高,修改为脚本跑出来的实际高即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import zlib
import struct
crc32key = 0xFF5C7810 #此处放CRC32的值
data = bytearray(b'\x49\x48\x44\x52\x00\x00\x02\x21\x00\x00\x02\x21\x08\x02\x00\x00\x00') #HxD copy chunk[0] part
n = 4095
for w in range(n):
width = bytearray(struct.pack('>i', w))
for h in range(n):
height = bytearray(struct.pack('>i', h))
for x in range(4):
data[x+4] = width[x]
data[x+8] = height[x]
crc32result = zlib.crc32(data)
if crc32result == crc32key:
print(width,height)

5. 如何看清gif图片中的flag(hint)

有些时候可能会在解题过程中遇到gif图片的处理,这里推荐一个比较好用的抽帧网站(地址在下面)。该网站的用法也比较直白,先上传文件然后选择frames。就可以看到gif图片分离出来的每一帧了。其中可能会夹杂着flag或者hint。

后记

有很多人都说MISC是脑洞题,看谁脑洞大就能做出来。但其实看多了MISC之后,还是很有套路的。按照流程一步一步走,总能把flag给找出来。这篇文章写的是关于图片隐写部分的。其实图片隐写还能夹杂很多其它考点,比如什么古典密码呀,什么zip伪加密呀等等。这些隐藏的考点基本都能通过百度速查解决。在这里我只是给大家说明了拿到一张图片,你能从哪些角度去处理它。整个解题流程就应该从一个点入手,逐渐深入,搜集更多的信息。信息越多,你做出来的概率就越大。
杂项题与其它几个大类的题相比,它会显得更加青涩。就像你在一张全是文言文的语文卷子上面发现了一道趣味脑筋急转弯。我觉得杂项的地位更像是CTF赛场的调剂品,在考验体力与脑力的激烈比赛中,给人一丝放松。
然后呢,废话说了这么多,调剂品归调剂品,还是别沉迷其中。好好学好自己的本职方向,该挖CVE的去挖CVE,该去pwnpwnpwn的去pwnpwnpwn。知识很多,学海无涯。


各工具的网页链接:

  1. binwalk——https://github.com/ReFirmLabs/binwalk
  2. Stegsolve——http://www.caesum.com/handbook/Stegsolve.jar
  3. HxD——https://mh-nexus.de/en/downloads.php?product=HxD20
  4. gif图片处理——https://ezgif.com/split
CATALOG
  1. 1. 图片隐写一把梭流程总览
  2. 2. 具体操作如下所示
    1. 2.1. 1. 观察图片
    2. 2.2. 2. Stegsolve处理LSB隐写
    3. 2.3. 3. 扔进binwalk里面
    4. 2.4. 4. HxD(winhex, 010editor)进行图片处理
    5. 2.5. 5. 如何看清gif图片中的flag(hint)
  3. 3. 后记