
1. 拿到附件之后先做的几件事文件结构与考点拆解1.1 解压附件把家底清出来国赛杂项的隐写题从来不是让你拿着工具对着一个文件硬试。拿到手的第一步永远是“清点情报”。这次这道steganography_challenge附件解压之后只有三个文件一张cover.png图片、一个sound.wav音频、一个hint.txt文本。cover.png 1.2 MB PNG image data, 1024 x 768, 8-bit/color RGB, non-interlaced sound.wav 3.8 MB RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, mono 44100 Hz hint.txt 57 B ASCII texthint.txt打开只有一句话colors hide the clue, waves hide the key.这句话基本就把题目主链路点明了颜色图片里藏着线索声波音频里藏着钥匙。如果一上来就在那边盲猜或者拿着 binwalk 一顿乱切反而容易绕远。我习惯先把提示抄在笔记里后面每一步都拿这句话去对现在找到的东西是“线索”还是“钥匙”1.2 固定检查流程file、strings、binwalk 一个都别省不管什么文件我都建议按下面这个顺序走一遍很多不起眼的线索就是这么发现的。先用file确认真实类型防止扩展名误导。这里cover.png确实是 PNG不是改后缀伪装的文件。接着strings快速扫一遍可见字符串看看有没有直接塞在文件头尾的提示strings cover.png | head -50结果很干净图片主体没有明显的明文字符串。这一步没收获很正常隐写题很少会把 flag 直接写在文件尾部等你strings出来除非是签到题。然后是binwalk看文件里有没有内嵌的其他文件binwalk cover.png输出中间有一大段 PNG 图像正常的数据段但出现了一条值得注意的记录偏移十六进制偏移描述12134560x128490Zip archive data, at least v2.0 to extract也就是说cover.png的尾部被附加了一个 ZIP 压缩包。顺着这个思路用binwalk -e cover.png把内嵌文件分离出来得到一个hidden.zip。这时候问题来了运行unzip hidden.zip提示需要密码。到这里题目已经露出了第一个卡点压缩包是加密的。如果你只知道爆破那很可能会在这道题上浪费大量时间。但回头看看hint.txt人家已经告诉你“waves hide the key”密码大概率不在图片上而是在音频里。这就是杂项题的典型特征线索是分散的得靠人脑做关联。2. 图片里的第一层秘密对 cover.png 做 LSB 隐写检查2.1 LSB 隐写到底在藏什么既然hint.txt说 “colors hide the clue”那图片这一层多半不是简单地在文件尾部藏数据而是把信息写进了像素的颜色分量里。LSB全称 Least Significant Bit最低有效位。一张 8 位深度的 RGB 图片每个像素有三个颜色通道每个通道用一个字节表示范围是 0 到 255。把每个字节最低的那一位替换成你想隐藏的数据比特人眼看不出任何差别因为改 1 个 bit 只会让颜色值变化 1/255视觉上几乎无感。但数据量相当可观。一张 1024x768 的图片有 78 万多个像素每个像素 RGB 三个通道各提供 1 bit就是约 23 万个字节的隐藏空间。出题人通常会把自己的目标字符串按 ASCII 编码展开成二进制再逐位写入这些最低位。由于人类眼睛对 R、G、B 通道的敏感度略有差别最稳妥的做法是把数据同时塞进某个固定的通道组合里这也是 zsteg 这类工具会输出一堆组合候选的原因。2.2 用 zsteg 一键扫遍全部通道组合针对 PNG 和 BMP我最常用的工具是zsteg。它能把各种通道组合、位平面深度都试一遍省去手动点 StegSolve 的大量时间zsteg cover.png输出里会出现大量候选但大多数是噪声。真正有效的信息往往整整齐齐地以可见字符开头。我扫到的关键结果是这样的b1,bgr,lsb,xy | text: look_into_sound.wav, the rhythm_is_the_key我把这条单独提取出来zsteg cover.png b1,bgr,lsb,xy /tmp/lsb_extract.txt strings /tmp/lsb_extract.txt得到的就是这句提示look_into_sound.wav, the rhythm_is_the_key。到这里“colors hide the clue”这条线闭环了图片的 LSB 里没有直接给密码而是把你往音频方向指。2.3 为什么不直接用 StegSolve很多人入门时喜欢用 StegSolve 的 Analyze 功能手动切通道一张一张地看 RGB 三个 plane。这个方法对“隐写内容直接以肉眼可见图案或文字形式呈现”的题很有效比如在 Red plane 0 里直接看到一行字符串或二维码。但问题是如果隐写数据是字符串文本手动看像素平面不一定看得出来尤其是当你不知道它具体埋在哪个通道组合时。zsteg 的优势是自动枚举。它支持的参数包括zsteg cover.png --all zsteg cover.png -v--all会把所有通道组合全部列出来-v输出更详细的解码结果。如果你在这个阶段看到输出里有一堆rand或者不可读字符别急着下结论那很可能是通道组合不对或者隐藏数据使用了异或等简单加密。纯杂项隐写题大多数不加密zsteg在 PNG/BMP 上的表现相当可靠。注意zsteg 不支持 JPG。JPEG 的隐写通常走 DCT 系数修改或附加数据遇到 JPG 要换steghide、outguess、stegdetect这类工具或者用strings和hexdump看文件尾部。国赛的隐写题为了保证操作可复现PNG 出现频率明显更高。3. 把图片尾巴切下来binwalk、dd 与加密 ZIP 的处理3.1 从 binwalk 扫描结果到手动分离binwalk -e会自动把内嵌文件分离到_cover.png.extracted目录下大部分时候够用。但遇到偏移不是从 0 开始、或者工具解析失败的情况手动dd才是最稳的兜底方案dd ifcover.png ofhidden.zip bs1 skip1213456bs1 skip1213456的意思是直接从 1213456 字节处开始复制直到文件末尾。这个偏移就是 binwalk 输出里的十进制偏移。切出来的hidden.zip再用file验证一下确认是 ZIP 文件。这里有个小细节PNG 文件内部本身包含多段 zlib 压缩数据binwalk 会把它们也识别成Zlib compressed data所以扫出来一堆相近的记录千万不要慌。判断是不是文件尾部的追加内容最简单的方法是看偏移量是不是非常大、且后面再没有 PNG 的 IHDR/IDAT 标志。习惯上我还会用010 Editor或hexdump直接看文件末尾有没有PK\x03\x04头hexdump -C cover.png | tail -20如果结尾出现50 4B 03 04那就是 ZIP 头可以基本断定图片后面粘了一个压缩包。3.2 判断 ZIP 是普通加密还是伪加密拿到hidden.zip之后第一件事不是急着解压而是看加密方式。用zipinfo -v hidden.zip查看或者用 7-Zip 打开看是不是要求输入密码。我这次遇到的hidden.zip是真加密压缩头里能看到明确的加密标志位。如果解压时提示密码错误但题目给出过密码那就要考虑“伪加密”的可能。伪加密的本质是压缩包里的数据其实没有真正用密码加密只是把 ZIP 头里的 general purpose bit flag 第 0 位改成了 1让解压软件误以为它加密了。判断伪加密有个通用技巧用binwalk扫到 ZIP 之后再用 010 Editor 打开看 local file header 里的 bit flag。如果确认是伪加密可以直接用ZipCenOp.py修复或者手动把那一位从 1 改成 0。很多新人第一次遇到伪加密会以为是密码爆破失败白白消耗大量时间。但这一题的密码是真实存在的就在音频里。于是解题主线自然转移到sound.wav上。4. 音频里的钥匙Audacity 频谱图分析、摩斯码解码4.1 Audacity 打开 sound.wav先切到频谱图sound.wav播放起来是一段大约 20 秒的沙沙声如果只停留在“听波形”这一步基本什么都听不出来。这类音频题的标准操作是切到频谱视图。在 Audacity 里打开文件后默认显示的是波形图顶部菜单选择视图 - 频谱图或者直接按快捷键切到 Spectrogram 模式。刚切过去可能一片漆黑或一片亮白什么也看不清这时候要调一下视图的亮度与对比度。我习惯把频谱图颜色方案改成灰度再把对比度拉高隐藏的图形会立刻显现。![占位说明频谱图设置面板通常是黑白灰配色可以调整频率范围与亮度曲线]放大音轨之后能看到中频区域有一串明显的、由短线和点组成的图案一段一段排布间距规律。这就是用音频频率高低拼出来的摩斯码图案。所谓“waves hide the key”钥匙就藏在这里。4.2 抄录摩斯码并解码得到压缩包密码频谱图显示的图案抄下来是这样的... - ...-- --. ----- ..-. ..- -.抄录时有个很容易犯的错误把点、划、字符间隔三者搞混。摩斯码靠“停顿长短”区分点与划、字符与字符。点是一短音划是三倍长的音字符与字符之间有一段较长的停顿。看频谱图的时候图形横向宽度就代表持续时间窄的是点宽的是划间隔大的地方是字符边界。手抄出来之后可以查摩斯码表也可以直接写一个极短的 Python 脚本解码morse_code { .-: A, -...: B, -.-.: C, -..: D, .: E, ..-.: F, --.: G, ....: H, ..: I, .---: J, -.-: K, .-..: L, --: M, -.: N, ---: O, .--.: P, --.-: Q, .-.: R, ...: S, -: T, ..-: U, ...-: V, .--: W, -..-: X, -.--: Y, --..: Z, -----: 0, .----: 1, ..---: 2, ...--: 3, ....-: 4, .....: 5, -....: 6, --...: 7, ---..: 8, ----.: 9 } encoded ... - ...-- --. ----- ..-. ..- -. tokens encoded.strip().split() plain .join(morse_code[t] for t in tokens) print(plain)输出是ST3G0FUN。这个字符串就是解开hidden.zip的密码。提示解码出来的内容不一定是全大写或全小写解压时如果提示密码错误先试原样大小写再试全小写。很多压缩包密码是区分大小写的我在比赛里不止一次因为手滑把大写字母敲成小写多耽误了十几分钟。4.3 音频隐写题里摩斯码之外的常见套路这一题用到了频谱图加摩斯码但音频隐写还远不止这两种。为了帮大家横向扩展我把常考的几种列一下倒放语音波形图上无法直接阅读但在 Audacity 里选中音轨后执行效果 - 反向把音频倒过来听就能听到一句清晰的提示或者直接是 flag。左右声道分离双声道音频里一个声道是正常音乐另一个声道藏着摩斯电码或语音把声道单独导出再分析即可。频谱图直接拼文字出题人直接把 ASCII 字符以特定频率画在频谱上比如中频区出现 “KEY” 三个字母这种题打开频谱图就能看到非常直观。DTMF 拨号音一段连续的“嘟、嘟”声其实是电话按键音每个声音对应一个数字用 dtmf 解码脚本能还原出电话号码或一组数字线索。这些本质上都是“把信息藏进人耳不敏感或难分辨的维度里”。杂项题就是这样一个一个维度去试音频只是一层常见的载体。5. 用密码解开压缩包一步步拿到 flag5.1 解压 hidden.zip读取 flag回到hidden.zip用刚得到的密码解压7z x hidden.zip输入密码ST3G0FUN压缩包正常解开里面只有一个flag.txt。打开后内容如下flag{st3g0_ch4ll3ng3_d0ne}到这里整道题的主体流程就走通了附件信息读取 - binwalk 发现内嵌 ZIP - ZIP 加密需要密码 - 图片 LSB 提示音频 - 音频频谱摩斯码解出密码 - 解压读取 flag。这条链路每一步都是独立的考点但又是互相咬合的。这其实就是杂项隐写题的设计思路让你在几个常见的载体之间来回推而不是在同一类工具上反复做无意义操作。5.2 如果密码解不开应该先查伪加密再考虑爆破有读者可能在自己试做的时候遇到“密码明明对但解压失败”的情况。我的排查顺序是这样的先看zipinfo -v hidden.zip的加密位。如果加密标志是0x0009可以把这个 ZIP 丢给 010 Editor 检查 local file header 与 central directory 的 bit flag 是否一致。如果 local header 里是 0x0009但 central directory 里是 0x0000或者反过来那就是典型的伪加密。处理伪加密的手段有两种一是直接用binwalk或foremost重新提取看是否因为提取过程破坏了头二是用ZipCenOp.jar这类工具一键修复。修复之后再unzip密码通常直接留空或者填点啥都能解开。如果不是伪加密也不要盲目上字典爆破。先回头把这题的所有线索过一遍LSB 里有没有别的字符串音频频谱有没有遗漏的段落图片文件名有没有暗示。国赛杂项题里压缩包密码几乎都能在前面的线索中直接找到很少需要暴力破解。很多选手卡在最后一步不是因为密码复杂而是漏看了一条提示。6. 复盘总结杂项隐写题的通用套路与避坑实录6.1 我自己的固定检查顺序可以直接当 checklist做完这道题我更坚信杂项题的一线检查顺序应该固定下来省得临场东摸一下西碰一下。我个人现在基本按这个顺序走步骤检查内容常用工具1文件类型确认、哈希记录file、sha256sum2文件尾与可见字符串strings、hexdump3内嵌文件扫描与分离binwalk、foremost、dd4图片类隐写通道扫描zsteg、StegSolve、stegseek5音频类频谱与倒放检查Audacity、dtmf2num6压缩包加密方式判断与解压7z、zipinfo、ZipCenOp当然顺序不是死的。比如hint.txt如果已经明确指到某个方向就可以跳过无关步骤。但固定顺序能减少遗漏尤其是比赛时间紧的时候人的思维很容易僵住。6.2 这道题里和平时练习中最容易踩的几个坑坑一binwalk 分离出一堆“假 ZIP”。PNG 内部的 IDAT 是 zlib 压缩数据binwalk 会误报成很多压缩记录。判断追加文件不能只看Zip archive data关键词要看偏移位置和是否以PK\x03\x04结尾。真正的追加 ZIP 通常出现在文件后 2/3 区域而不是紧跟在 PNG 头后面。坑二摩斯码抄错。频谱图上的点和划如果对比度不够很容易把划中间的微弱断点看成字符间隙。我建议先截一张放大图把每段的宽度量一下再把最宽的间隙当作字符分隔符。如果解码出来出现ST3GOFUN这类明显不连贯的字符串大概率是漏了一个点或划。坑三zsteg 找不到数据就急着换工具。zsteg 默认只扫常见组合有时真正藏数据的组合是冷门的比如b2,bgr,msb,xy或者异或处理过的数据。这时候要加--all或者手动指定组合。这道题的提示直接出现在默认输出里算是运气比较好。坑四Audacity 频谱图看不清。切到频谱图后如果整片都是纯色的可以去频谱图设置里调整亮度、对比度、FFT 大小FFT 太小会导致频率分辨率低图案糊成一团。把 FFT 拉到 1024 或 2048点划边界会清楚很多。6.3 这类题还能怎么延伸这次steganography_challenge讲的是图片 LSB 文件分离 音频频谱 摩斯码。如果你之后想继续练杂项隐写可以往这几个方向延伸盲水印图片叠加提取、二维码修补定位角缺失、掩盖、反转、NTFS 数据流ADS 隐写、Unicode 零宽字符、视频帧提取与逐帧对比、网络流量包里的音频流还原。每个方向背后的工具和思路各不相同但底层的解题逻辑是一致的先建立“这个文件里可能藏着什么”的意识再用工具去验证每一个可能的隐藏维度。杂项题刷多了之后你会发现“国赛难度”很多时候不是难在某个知识点而是难在线索多、流程长、需要耐心和细心。把每个环节的标准操作练熟再难的题也能一步一步拆开。做完这道题之后我最大的体会是隐写题里工具永远只是手段真正的重点是对文件结构的理解和对提示的敏感度。hint.txt那一句话就把整条链路规划好了剩下的工作是在图片、音频、压缩包之间来回验证。如果你刚接触 CTF 杂项我建议不要只盯着某一个工具学而是多拆几道类似的综合题把“读线索 - 验证载体 - 提取内容 - 串联信息”的思维模型建立起来。这套东西练熟了再遇到其他 steganography 题目你会发现自己不再慌也知道下一步该看哪里。