资讯动态

CTF杂项信息隐藏实战:从PNG元数据到LSB隐写的完整链路

发布时间:2026/10/9 17:24:17 来源:尧图企业网站定制
昨天把SWPUCTF 2024 秋季新生赛的题目重新过了一遍最想写复盘的是[SWPUCTF 2024 秋季新生赛]hidden。题名只有六个字母却几乎浓缩了新生赛杂项题最典型的考法信息隐藏。文件末尾塞压缩包、EXIF里写密码、像素最低位藏flag——这些在“hidden”这个主题下都能串起来。我是比赛结束后重新做的整个过程大概四十分钟中间卡得最久的地方不是最后提取flag而是压缩包密码藏在图片EXIF里我第一轮扫字符串时漏掉了。还好回头查了元数据不然可能要在爆破上浪费时间。这篇文章把完整链路、工具选择和几个容易翻车的细节都写清楚给准备入门CTF杂项的朋友一个可复现的参考路径。1. 拿到题目后的第一轮信息收集1.1 先用file和strings确认文件底细把附件下载下来是一个压缩包。解压后得到两个文件hidden.png和readme.txt。很多新手喜欢直接双击图片看眼睛能看到的东西我建议先忍一忍按“识别类型 → 扫字符串 → 看元数据 → 看二进制结构”的顺序走能避免漏掉绝大多数低级线索。先跑file确认图片类型$ file hidden.png hidden.png: PNG image data, 1200 x 800, 8-bit/color RGB, non-interlaced这是一个标准PNG没有伪装头。接着用strings把文件里的可打印字符串扫出来重点看有没有flag格式的字段、base64片段、或者像PK这样的压缩包头部特征$ strings hidden.png | head -50输出里能看到正常的IHDR、IDAT块信息但混了一段看起来像base64的字符串。我下意识拿去解码结果是一堆乱码。这说明字符串层的信息并不完整后面可能还有二次编码或压缩。strings只能捞表面文章文件尾部的真实附加数据、像素低位的数据它基本无能为力。readme.txt 的内容也值得反复读where is the flag? maybe in the dark.“dark”这个词很关键。后面解出LSB隐写后才明白它暗示的是“最低有效位”因为最低位对色彩影响极其微弱就像是画面里看不见的黑暗角落。题目给提示从来不会直接写答案但也不会给你一个无关的单词。1.2 元数据往往是密码和高频线索的老窝基础命令之后下一步是看元数据。PNG虽然没有JPEG那种复杂的EXIF体系但它有 tEXt、iTXt、zTXt 这些文本块题目的密码、提示、甚至半截flag都可能放在这里。用exiftool扫一遍$ exiftool hidden.png ... Comment : Password: SWPUCTF_2024_H1dden ...这个Comment字段就是突破口。Windows下右键图片属性也能看到一些基础元数据但tEXt块这种结构必须用命令行工具才能完整显示。新生赛出这种点就是为了逼选手学会用工具而不是靠鼠标点来点去。除了exiftoolpngcheck -t也可以查看PNG文本块。比赛里我见过把flag拆成多段分别放在不同文本块的题只靠一张图片的常规属性根本看不全。所以元数据检查要养成习惯不是打开图片看一眼就完事。1.3 隐藏文件也要查解压后的目录看起来很简单但我习惯用ls -la再看一遍$ ls -la total 28 drwxr-xr-x 5 user user 4096 ... -rw-r--r-- 1 user user 24576 ... -rw-r--r-- 1 user user 1024 ...很多题目会在目录里塞隐藏文件文件名可能以点开头也可能在末尾加空格、加不可见Unicode字符。Windows下如果没开“显示隐藏文件”很容易直接漏掉。这道题虽然主要线索不在隐藏文件里但检查一遍总归不亏。2. 题目背后的三类隐藏思路2.1 文件系统层面的隐藏文件系统层最常用的手段是修改文件名和属性。一个文件叫flag.txt实际却是张图片一个文件夹叫flag里面却什么都没有真正的信息藏在一个由空格组成的文件名中。还有把文件直接丢到系统隐藏目录、或者用NTFS ADS数据流藏内容的操作都属于这个范畴。应对方式也很机械ls -la看隐藏文件find按文件类型搜xxd看真实文件头。CTF里所谓“hidden”题目很大一部分就是在考验这种基础的信息收集习惯。新生赛尤其喜欢把文件名里的某一段字母大写/小写混合用来提示密码比如H1dden这种写法。2.2 二进制附加与文件拼接第二种常见思路是在文件尾部追加其他数据。PNG、JPG这类图片查看器对文件尾部的额外数据容忍度很高即使你在一个正常PNG后面追加一个完整的ZIP图片依然能正常打开肉眼完全看不出区别。检测手段主要是binwalk。它通过扫描文件签名来定位嵌入内容比如在PNG图片的十六进制偏移量0x1D619位置发现PK开头就会报告“Zip archive data”。foremost也可以用来自动分离它会把识别出的文件抠出来但有时候会产生碎片文件需要二次确认。2.3 像素级隐写最后是像素级隐写也是本题最后一层关卡的核心。以PNG为例图像由像素矩阵构成每个像素包含R、G、B三个颜色通道每个通道取值0到255。把每个通道的最低位替换成我们要隐藏的比特人眼几乎无法察觉颜色的变化。这种算法叫LSB隐写。提取时只要按固定顺序把每个通道的最低位取出来重新拼成字节就能还原隐藏信息。zsteg、stegsolve都能快速检测但真要理解原理最好还是自己写一遍Python脚本。后面我会专门讲脚本里的通道顺序和位序坑。3. 从线索到flag的完整复盘3.1 用EXIF密码打开第一道锁刚才提到了hidden.png的Comment字段里写着一个密码Password: SWPUCTF_2024_H1dden这个密码大概率不是最终flag而是解压下一层压缩包的钥匙。我先把它记下来然后回到图片本身的二进制结构上。为什么建议先解析元数据再做binwalk因为很多题目的设计逻辑是“线索指引工具”元数据给密码binwalk负责分离压缩包密码用于解压。如果你一上来就用foremost硬分离拿到一个加密压缩包却没有密码还是会卡住。先找线索再上工具顺序很重要。3.2 binwalk定位隐藏的ZIP文件对hidden.png做一次完整扫描$ binwalk hidden.png DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 PNG image, 1200 x 800 ... 120345 0x1D619 Zip archive data, at least v2.0 to extract偏移量120345处出现了一个ZIP。这说明PNG文件尾部被追加了一个压缩包。我直接用binwalk -e提取$ binwalk -e hidden.png提取结果里出现secret.zip。如果你不用binwalk手动用dd截取也可以$ dd ifhidden.png ofsecret.zip bs1 skip120345 count4096count需要根据文件实际大小调整先用ls -l hidden.png算出偏移到结尾的字节数。手动截取的好处是更可控也能避免binwalk偶尔误报导致提取出大量垃圾文件。3.3 解开压缩包进入第二层隐写secret.zip用之前拿到的密码解压得到一个flag.png。打开后是一张看起来像纯色噪声的图片肉眼看不出任何文本。这时候就该怀疑LSB隐写。先用zsteg验证$ zsteg flag.png输出里能看到类似base64的字符串。不过我没有直接抄工具结果而是用Python自己实现了一遍提取逻辑一方面是验证另一方面是比赛时你能根据题目灵活调整通道和位序。下面是简化版提取脚本from PIL import Image img Image.open(flag.png).convert(RGB) width, height img.size bits for y in range(height): for x in range(width): r, g, b img.getpixel((x, y)) bits str(r 1) bits str(g 1) bits str(b 1) chars [] for i in range(0, len(bits), 8): byte bits[i:i8] if len(byte) 8: break chars.append(chr(int(byte, 2))) print(.join(chars))运行后得到一串Base64解码后就是最终flagSWPUCTF{h1dd3n_1s_n0t_4lw4ys_s4fe}这里对flag做了脱敏处理实际操作时你会看到题目给出的完整内容。整个链路其实不复杂难点在于每一步都要想到“还有下一层”。3.4 自己写LSB脚本时的三个关键细节第一PIL的getpixel在RGBA图片里会返回4个值必须用[:3]或者convert(RGB)丢弃Alpha通道。第二有的题按R、G、B顺序逐个像素提取有的题要先把所有R通道提取完再提G通道顺序错了会得到完全不同的乱码。第三位序也有讲究最低位在前还是在后结果天差地别。遇到乱码时不要慌先打印提取结果的前几段看是不是出现可读的flag{或者base64特征字符。如果完全没有大概率是通道顺序不对尝试改成“按通道分离再拼接”的写法channels {r: [], g: [], b: []} for y in range(height): for x in range(width): r, g, b img.getpixel((x, y)) channels[r].append(r 1) channels[g].append(g 1) channels[b].append(b 1)然后再决定是RGB还是BGR的顺序拼接。这种灵活性是工具替代不了的。4. 新手容易踩的坑与排查技巧4.1 文件头被篡改怎么修复有的题目会把文件头改掉比如把PNG的89 50 4E 47改成其他值导致图片无法打开。遇到这种问题第一反应不应该是删掉重下而是用十六进制编辑器把文件头改回来。$ xxd hidden.png | head -3如果开头不是PNG、JPG、ZIP中任何一个的正常签名就去查一下对应格式的签名表。常见的PNG头是89 50 4E 47 0D 0A 1A 0AZIP头是50 4B 03 04JPG头是FF D8 FF E0。把篡改的字节修正后很多文件就能正常打开。4.2 strings结果到底怎么筛选strings输出会非常长尤其是图片类文件正常的文本块和压缩数据会产生大量不可读内容。建议加上过滤$ strings hidden.png | grep -iE flag|swpu|ctf|password|pk只看和题目相关的关键词。如果没有输出再放宽到base64特征用grep -E ^[A-Za-z0-9/]{20,}{0,2}$过滤长字符串。这道题其实在strings阶段就能看到一段base64但它不是flag而是图片里某些压缩数据的残影如果不继续用binwalk很容易被误导。4.3 压缩包是真加密还是伪加密ZIP压缩包解压时提示需要密码但unzip -l secret.zip又能正常列出文件名这种往往是伪加密。伪加密只是在ZIP文件头的通用位标志里把加密位设为1实际数据并没有真正加密。判断和解除伪加密有个经典方法用十六进制编辑器打开ZIP找到通用位标志字段把加密标志位从09改成00保存后再解压。也可以用工具ZipCenOp.jar一键修复。本题里压缩包是真实加密所以必须用EXIF里的密码。先判断加密类型再决定是找密码还是爆破能省下大量时间。4.4 常见问题速查表现象可能原因排查方法图片无法打开文件头被篡改用xxd查看头修复签名strings抓不到flag信息被压缩或编码用binwalk看结构再分离binwalk扫描无结果文件被加密或隐写方式不是附加数据检查LSB、DCT、MSB压缩包要密码但能列出文件伪加密修改加密标志位压缩包真实加密且没有线索密码隐藏在元数据/文件名/readme用exiftool扫描所有可读字段LSB提取全是乱码通道顺序或位序不对对比zsteg输出调整脚本5. 这道题带给我的思考5.1 从出题人视角看hidden做完这道题我最强烈的感受是题目是一层一层递进的“藏宝图”。第一层藏在元数据第二层藏在文件尾部第三层藏在像素最低位。每一步都需要换一个工具但每一步都不会让你突然跳到没学过的知识上。这种设计很考验基本功会不会用strings、binwalk、exiftool、zsteg懂不懂PNG结构、ZIP结构、像素编码。“hidden”这个题名其实在提醒选手不要只会盯着看得见的地方。flag不会直接写在屏幕上更多时候躲在“看不见但存在”的角落里。新生赛不会用太离谱的脑洞但一定会用最经典的手法把选手的信息收集习惯挨个检查一遍。5.2 常用工具链该沉淀成肌肉记忆我整理了一下自己常用的杂项工具基本可以覆盖80%的新生题工具适用场景题中使用环节file识别真实文件类型确认PNG类型strings提取可打印字符串发现异常base64exiftool查看元数据找到Comment密码binwalk扫描附加文件签名定位尾部ZIPforemost自动分离嵌入文件备用分离方案stegsolve查看像素位平面验证LSB隐写zsteg检测LSB/BMP隐写快速定位提取结果010 Editor十六进制编辑修复文件头/伪加密工具之间要会交叉验证。zsteg给出的结果不一定全对binwalk也可能误报最靠谱的方式是结合多个工具的输出再用自己的脚本去复现。5.3 实战中的一点心得我个人在做信息隐藏类题目时的步骤是先看readme和文件名再file和strings然后exiftool最后binwalk。如果这几个跑完还没有结果再去想LSB、DCT、水印这类隐写方向。绝大多数新生题不会超过这个范围。这道题对我的最大价值不是那个flag格式的字符串而是让我重新确认了一个道理隐藏的本质是“制造信息不对称”而解题的本质是“消除信息不对称”。你掌握的检查维度越多看到的“隐藏”就越少看到的“线索”就越多。之后再做类似题我第一件事都会把元数据查干净因为很多作者喜欢把密码放在最容易被忽略的地方而一次完整的元数据扫描往往能直接省掉半小时爆破时间。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑