::: hljs-center
居中
:::
CTF—图像隐写三板斧(续)
声明:本博文只是分享知识,如果有人利用此技巧去做违法违规的事情,本人概不负责!
接着上期的练习继续分享关于图像隐写题目的知识点。
接着上期的练习继续分享关于图像隐写题目的知识点。
1. 第一板斧升级
一些图像会在图像的靠下部分显示重要信息,比如,故意减小图像高度使得图像重要信息不显示,从而达到隐写的目的。通过利用010 Editor不仅能发现插入隐藏,还可以帮助我们修改图片高度。
PNG图像的宽高在IHDR块中。出题人会直接修改原图的高度而不修改其他值,但是PNG每个块都有CRC值,强行修改高度将导致根据新的高度值计算出的CRC值和IHDR块中的原CRC值不匹配。在Windows系统中,CRC值不匹配的PNG图像可以正常打开,并且只显示IHDR块中指定的高度;但在Linux和mac OS系统下,CRC值不匹配的PNG图像不能正常打开。这是这类题目的一个重要特征。如果我们只有Windows系统,也能在010 Editor中发现CRC值不匹配的提示信息。
当我们发现PNG图像高度被修改时,一种方法是利用010 Editor把高度改成一个较大值。
【例题】hi.png
【题目描述】找到文件中的flag
【解题思路】把图像拖入010 Editor,如下图所示:
先不要做任何操作,可以看到左下角黄条有报错信息,其含义为chunk[0]的CRC不匹配”。chunk[0]是所有块中的第一个块,即IHDR。出现“chunk[0]的CRC不匹配”时,我们要想到很可能是图像的宽高被人修改了。 接下来的思路是在010 Editor中调整图像宽高,一般情况下,只需要修改高度即可。如下图所示:
展开chunk[0]中的ihdr结构体,能看到详细的宽高信息(width表示宽度,height表示高度,单位是像素)。如果随意修改宽度值,图像会出现“花屏”的效果,因此一般只修改高度值。问题是高度值应该改为多少比较合适呢?一种简单粗暴的方法是改成一个较大值,例如修改成1000。用鼠标左键双击height字段,把400修改成1000,然后将图片“另存为”一张新图片(注意不要直接保存,直接保存会覆盖原图像,而修改后还需要和原图比较)。修改后的结果如下图所示,在图像下方显示flag,同时出现黑色区域,这是因为高度值过大,Windows的照片查看器默认填充黑色。
上面的例题是最简单的情况,只需要随便调大高度值即可,但在某些情况下,需要把图像的宽高修改为准确值。例如,当修改高度过大时,修改后的图像不能用StegSolve打开。由于在IHDR中保存着根据原宽高值计算得到的CRC,因此可以利用CRC值爆破出原始宽高的准确值。
【例题】plum.png
【题目来源】2019中石油集团决赛
【题目描述】找到文件中的flag
【解题思路】用010 Editor打开图片,系统报出chunk[0]的CRC不匹配的错误,因此需要修改高度。将高度改为1000后,没有在图像下发现flag。于是继续利用第二板斧,但是修改后的图像不能用StegSolve打开。利用脚步breakwidthheight.py根据CRC值爆破原始高宽,该脚本只针对PNG图像有效,具体方法如下图所示:
图像准确高宽是625*1024,将修改后的图像放到StegSolve中,如下图所示,在红色通道的最低位发现一个二维码,扫码得到flag{affe5937-51d1-4182-87a4-bb4bcf038aea}。当没有修改高度时,原图在StegSolve中看不到二维码。但若高度设置过大,StegSolve将会崩溃,这就是要用脚本得到该图像准确宽高值的原因。
【例题】Luff.jpg
【题目描述】找到文件中的flag
【解题思路】用010 Editor将图像打开,可以看到JPG头部和尾部均没有插入信息。此时,尝试修改图片高度。如图所示,将SOF0段中的Y_image值修改为1000,将文件“另存为”新的图片。双击打开新保存的图片,在图片底部就能看到flag。
实际上,其他格式的图像也可以通过调整高度实现信息隐藏。对于BMP图像,如下图所示,在bmih结构体中,biWidth和biHeight分别表示图像的宽度和高度,我们可以直接修改其数值。需要注意的是,高度值不要一次改得很大,可以每次增加20~50个像素值。
同样地,也可以修改GIF文件的高度,如下图所示。注意:修改的时候首先要修改逻辑屏幕标识符里面的高度值,再修改图像块中图像标识符的高度值。如果有多幅GIF图像,可能需要修改每幅图像对应的图像标识符,再做GIF图像拆分等操作。
2. 第二板斧升级
第二板斧的目的是发现LSB隐写。在之前的例题中,都是把消息直接通过LSB隐写到PNG图像中,这种方法的隐蔽性有待提升。于是有人提出先将信息加密,再通过LSB隐写入图像,这样即使从图像中提取出信息,没有密钥的话也不能恢复出信息。这类题目也称为“带密钥的LSB隐写”,其典型工具是cloacked-pixel( https://githbub.com/livz/cloacked-pixel),主要用到脚本lsb.py。
破解带密钥的LSB隐写题目的关键是找到密钥。这类题目一般都提供提示,结合提示可以很快想到这个考点。
【例题】dong.png
【题目来源】2020山东省科来杯
【题目描述】找到文件中的flag
【解题思路】若用过“三板斧”后没有找到任何线索,由于图片是PNG,因此猜测可能是带密钥的LSB隐写。但关键问题是密钥没有任何提示,要么写脚本用字典爆破,要么猜测弱口令。这里先猜测密钥是123456,使用cloacked-pixel,查看dongflag.txt,可以看到flag{6e9fbfe27c40bbad06db30c42c04c4d6}。
# python2 lsb.py extract dong.png dongflag.txt 123456
[+] Image size 640*640 pixel
[+] Written extracted data to dongflag.txt
3. 第三板斧升级
如果用完“三板斧1.0版”没有找到任何线索,且图片是JPG格式,那么可以在第三板斧中考虑JPG对应的专用工具,如stegdetect、JPHS、OutGuess、Steghide等。在线JPG图像隐写检测工具为https://lukeslytalker.pythonanywhere.com/。在下面的例题中,展示OutGuess离线工具的使用方法。
【例题】UltimateSteg
【题目来源】Th3Jackers CTF 2015
【题目描述】找到文件中的flag
【解题思路】文件名字是“终极隐写”,先掏出我们跃跃欲试的“三板斧”。把文件拖入010 Editor,发现文件头是GIF文件格式,使用GIF模板解析。如下图所示:
单击模板解析结果中的GIF Trailer,可以快速跳转到文件结尾,很明显可以发现GIF文件末尾有一个ZIP格式的文件。这个ZIP文件可以通过binwalk提取,假如binwalk失效,就需要我们手动提取。接下来,我们重点演示如何手动快速提取文件。
单击GIF解析结果的Trailer部分,对应字段会变为蓝底。用鼠标单击窗口右侧的滚动条,快速移动至GIF文件头,然后按住键盘上的键,用鼠标单击GIF文件头的第一个字节,如下图所示,所有GIF文件数据都变为蓝底。
接下来,按Delete键删除GIF数据,将剩余数据另存为ZIP压缩文件,ZIP文件的解压结果如下图所示:
对图像1.png~6.png逐个用“三板斧”分析。把1.png拖入010 Editor,在文件尾发现追加插入的字符串“Lets begin:3tKdX”,于是猜测可能每张图片都隐藏了一个字符串。如下图所示:
在2.jpg结尾发现字符串“Dont be stupid Use another method”。但是用“三板斧”没有找到任何线索,我们选择暂时放弃这张图片,先看看其他图片。
对3.jpg使用第一板斧后发现一个ZIP压缩包,在Kali下用binwalk提取所有文件,进入到提取文件夹下有1000个文本文件,绝大部分文件的内容是“NotHiNg HeRe”。如下图所示:
我们可以写脚本逐个读文件中的内容,把不是“NotHiNg HeRe”的内容打印出来;或者在解压后的文件夹中,采用“cat ”方法。cat命令可以在屏幕上打印文件内容,“”是通配符,代表renew字符串,“cat * ”命令的含义是打印当前路径下的所有文件内容,结果如下图所示。
这时我们可以发现“GoOd 3RlZ30=”,它位于文件368中。
对于4.jpg,仅用第一板斧就能在文件头发现前置插入了“If you insist here is your gift:ZmxhZ”,看到熟悉的“Zmxh”,我们就知道与Base64编码有关,那么每张图中可能有Base64字符串一部分,需要都提取出来后再拼接。
5.jpg文件的末尾告诉我们“So easy Just Look Carefully”,这个提示含义不明,于是接着用第二板斧。使用StegSolve打开图片,单击“>”按钮,如下图所示,仔细查看发现字符串“TaUlw”。
6.jpg也非常简单,在文件末尾可以发现“Almost done! Here is your last gift TGUtU Now form the flag:)”。不难发现,除了2.jpg,其他图片用“三板斧”都能解决,针对2.jpg尝试应用stegdetect、JPHS、OutGuess、Steghide等工具,发现利用OutGuess可以提取出有效信息,N0LWF。
整理提取到的信息,如下所示:
1.png 3tKdX
2.jpg N0LWF
3.jpg 3RlZ30=
4.jpg ZmxhZ
5.jpg TaU1w
6.jpg TGUtU
接下来对这6个字符串进行排列组合,4.jpg肯定是第一个,3.jpg肯定是最后一个。可以写脚本进行排列组合,也可以收工尝试,按照4、1、2、5、6、3的顺序拼接字符串,得到ZmxhZ3tKdXN0LWFTaU1wTGUtU3RlZ30=,对其进行Base64解码,得到flag{Just-aSiMpLe-Steg}。
总结“三板斧(续)的步骤如下:
第一板斧:应用010 Editor、strings
第二板斧:应用StegSolve、steg(lsb.py)
第三板斧:应用binwalk、foremost(stegdetct、JPHS、OutGuess、Steghide)
“三板斧(续)的使用方法如下:
1)第一板斧可以解决肉眼可见的插入隐藏和图像高度隐写
2)第二板斧用StegSolve和zsteg发现图像是否有LSB隐写
3)第三板斧的binwalk和foremost查找较为隐藏的插入隐藏