图片分析
引言
图片题在Misc中具有极其重要和基础性的地位,可以说是Misc的“半壁江山”和入门必修课。图片题是检验选手信息搜集、工具使用和跨领域联想能力的试金石。熟练掌握图片题的相关技术,是CTF参赛者,尤其是Misc方向选手的一项核心能力。接下来就让我来分享一下传统图片题的做题基本思路(传统!传统!新题的出题鬼知道他耍什么花样)。
一把梭
很多基础的图片题会把flag藏在浅显的数据层,这时候只要把图片丢给随波逐流就可以非常容易地拿到flag
例如:ctf.show这道题只需要把图片放进一把梭工具,它就会自动检索出flag

010Editor
同样是上一道题,我们也可以用16进制工具打开手动检索flag相关信息

不难看出,在文件的末尾,我们看见了要找到的flag
Binwalk&foremost
binwalk
题目链接:ctf.show
拿到附件并经过以上两个步骤后均没有发现flag,可以使用binwalk对图片进行分析,看图片是否含有附加文件

可以看到图片中还有另外一张png图片,使用binwalk -e尝试提取那张图片

但是binwalk并没有成功提取到我们所需要的那张png,只是导出来两个.zlib文件。
foremost
既然我们知道题目所给图片中确实有另外的图片,但是用binwalk无法提取,那我们不妨尝试用foremost进行提取
使用foremost提取时,会生成一个output文件夹,可以看到包含flag的图片已经在里面了,至此我们拿到了flag。
注:即使没有成功提取,foremost提取也会给你生成output文件夹,里面就只有你的原始图片。
IDAT块
IDAT块是PNG图像文件真正的“数据心脏”。它像一座仓库,专门存放经过压缩处理的图像像素核心数据。一个PNG文件可以连续拥有多个IDAT块,它们必须按顺序拼接,才能解压还原出完整的画面。在文件结构里,它紧随描述图像基本信息的IHDR块之后,终结于IEND块之前,构成了“头-身-尾”中不可或缺的“身躯”。
题目链接:ctf.show
经过以上几步操作后,我们连flag的影子都没有看到,但是根据随波逐流扫描出来的结果,我们发现这张图片有且仅有两个IDAT块,emm……数量不多不少,我们可以试一下删除其中一个IDAT块看看,这时候就得请出我们的TweakPNG了,打开图片,并删除第一个IDAT块。哦豁!flag出来了!

虽然这题我们很容易就拿到了flag,但有些题目(详见ctf.show)可能会要我们依次删除好多IDAT块,慢慢尝试才能拿到flag
dd手动分离
遇到binwalk -e无法成功分离文件时,可能是如下原因
| 主要原因类别 | 具体原因与说明 | 解决思路提示 |
|---|---|---|
| 1. 文件签名/魔数被修改或破坏 | 出题人故意修改了嵌入文件的文件头(如将 PK改为 PK),导致 binwalk 的签名识别失败。这是 CTF 中常见的反自动化手段。 |
使用 binwalk -A或 file、xxd手动分析可疑数据段,尝试根据文件结构手动修复正确的文件头。 |
| 2. 文件被加密或混淆 | 嵌入的文件内容被加密、编码(如 Base64、ROT)或进行了异或混淆,使其不具备有效的文件签名。 | 先对整体文件或分离出的数据块进行解密或解码操作。常用工具如 cyberchef,或编写 Python 脚本尝试常见密钥。 |
| 3. 嵌套结构或非常见格式 | 文件被多次嵌套(如压缩包套压缩包),且使用了不常见的算法或格式,导致 binwalk 的提取插件不支持。 | 使用 binwalk -Me尝试递归提取。若失败,则需手动使用 foremost、dd或 010 Editor按分析出的偏移量逐层分离。 |
| 4. 文件系统/容器损坏或不完整 | 嵌入的文件(如一个压缩包)本身 CRC 校验错误、结构不完整,或被截断,导致无法正常解压。 | 尝试使用 7-zip或 zip -FF等工具的修复功能。对于 PNG 等格式,需检查并修复数据块(如 IDAT 的 CRC)。 |
| 5. 工具本身限制或 Bug | Binwalk 的签名库未包含该文件类型,或特定版本的提取插件存在缺陷。 | 更新 binwalk 到最新版。使用替代工具进行签名扫描和提取,如 foremost、dd(手动)、7-zip(直接尝试解压)。 |
| 6. 数据未按标准格式嵌入 | 数据被直接附加在文件末尾(如直接附加在 PNG 的 IEND 块之后),没有封装成独立的压缩包格式,因此没有可供识别的签名。 | 使用 binwalk --dd='.*' <文件>暴力切分所有数据段,或直接用 dd、010 Editor从末尾截取数据进行分析。 |
这时候我们可以尝试用dd手动分离文件
1 | dd if=<输入文件> of=<输出文件> bs=<块大小> skip=<输入块数> seek=<输出块数> count=<块数> |
练手题:ctf.show
对于题目给的jpg图片,我们用了前面的所有手段都没有拿到flag,所以尝试一下dd手动分离。


分离成功得到flag

修改图片宽高
题目链接ctf.show
题目提示:flag在图片下面
用010Editor打开图片,010里面是默认装了jpg模板的,如果没有在模板库里面安装一下就行(如果你可以手动改的话也不是不行)
因为题目提示是flag在图片下面,所以我们把图片的Y变大

修改并保存过后我们可以看到flag
不完全归纳:如果图片真实的宽高与现有图片宽高相符,随波逐流扫描出来会出现类似“宽高相符”的字样(纯属个人归纳)。

利用不同帧之间的间隔时间来隐写
题目链接ctf.show
题目提示:flag就像水,忽快忽慢地流
根据提示再结合附件是GIF动图,尝试利用identify来处理该GIF图片,并把提取的数组储存起来。
1 | identify -format "%T " misc39.gif > 1.txt |

打开1.txt发现是36跟37的交叉出现,与01有点相似,所以尝试用0替换36,用1替换37,将得到的编码7个一组进行解码得到flag

1 | ctfshow{52812ff995fb7be268d963a9ebca0459} |

APNG分离图片信息
题目链接ctf.show
图片识别为apng图片,用APNG Disassembler(APNG Disassembler download | SourceForge.net)读图片信息进行分离

得到好多.txt文件,利用脚本循环读取apngframe28.txt到apngframe68.txt,从每个文件中提取一个数字并转换为对应的ASCII字符,最终将这些字符拼接成一个完整的flag字符串。
1 | flag="" |
坐标转图片
题目链接ctf.show
题目提示:你见过扶乩吗
自己想半天没想明白,后面查了一下大佬们的做题笔记,发现是坐标转图片。用identify命令提取数据
1 | identify misc46.gif >message.txt |


可以看到很多坐标信息,用脚本提取图片每次偏移的值当做坐标,再作图
1 | import re |
得到flag
题目链接ctf.show
这题我还没看懂,等我看懂了再回来把这题解析补上,大家可以先去看看ctfshow misc46~47解法-CSDN博客
这位大佬的解析