先说结论:这篇文章是2021年某场CTF比赛Misc方向的部分WriteUp整理。如果你正准备打CTF,或者对隐写、流量分析、压缩包密码这类题还处于“看题一脸懵、看答案觉得简单”的状态,这篇文章可以帮你把解题思路捋顺。我会从工具准备讲起,按题目类型复盘几道有代表性的题,把当时踩过的坑和思考过程原原本本写出来,不是那种只有flag的简版题解。
CTF里的Misc方向,说好听点叫“综合杂项”,说难听点就是“什么怪题都有可能”。但这恰恰是新手最容易入门的方向,因为大部分Misc题不需要太深的底层知识,靠的是耐心、细心和一点点想象力。我参加这届比赛时,Misc方向遇到的题目涵盖图片隐写、压缩包密码、流量分析、音频隐写,基本把常规考点都过了一遍。下面按题型拆开讲。
1. 起手式:Misc方向的基本功与工具准备
1.1 Misc到底在考什么
Misc全称Miscellaneous,在CTF里被戏称为“杂项”。它不像逆向需要啃汇编,不像Pwn需要精通漏洞利用,也不像Web需要熟悉各种框架漏洞。Misc更像是“侦探题”,给你一个文件、一段流量、一张图片、一段音频,让你从中找出藏起来的Flag。
常见考点可以归成几类:文件隐写(图片、音频、视频、PDF等)、压缩包分析(伪加密、密码爆破、明文攻击)、流量分析(HTTP、DNS、ICMP等协议)、编码转换(Base64、进制、凯撒、栅栏等)、内存取证(Volatility分析内存镜像)、二维码修复、甚至还有Word文档里的宏。
新手最容易忽略的一点是:Misc题目考的是“怎么发现线索”而不是“某个高大上的算法”。很多题,答案根本不需要复杂计算,就是你在文件头尾看到了多余数据、图片属性里藏着备注、音频频谱里浮现出一串字符。这也意味着,工具用得熟不熟会直接影响做题速度。
1.2 我常用的工具清单与准备工作
工欲善其事,必先利其器。Misc方向依赖的工具链比较固定,我先列一份我比赛时实际用到的清单。
- 系统环境:Linux虚拟机或WSL都行,日常操作在Linux下完成最顺手,因为很多命令行工具原生支持,省去Windows折腾依赖的时间。
- 文件分析:
file、strings、binwalk、foremost、exiftool、pngcheck。binwalk和foremost用于检测和分离文件中的附加数据。 - 图片隐写:
zsteg(检测PNG/BMP的LSB隐写)、StegSolve(图像通道分析)、Python的Pillow库、010 Editor(十六进制编辑器,也常用于看文件结构)。 - 压缩包:
fcrackzip、zip2john搭配john,还有bkcrack做明文攻击。 - 流量分析:
Wireshark,必须熟悉HTTP过滤、TCP流追踪、导出对象等操作。 - 音频处理:
Audacity,重点用频谱图功能。
这些工具不需要全部精通,但至少要知道它们各自解决什么问题。实际做题的时候,我的固定流程是:先file确认类型,再strings盲搜可打印字符,然后binwalk扫附加内容,如果是有图片的题,再用zsteg或StegSolve看像素层信息。这套流程能覆盖80%的题目。
提示:很多工具用命令行的效率远超图形界面。比如
binwalk -e可以直接提取嵌入文件,strings xxx.png | grep -i flag能一眼找到线索。图形工具留着做通道分析这种需要人工观察的步骤。
2. 一道图片隐写题的完整复盘:文件分离与像素隐写
2.1 从文件头开始排查异常数据
当时的第一道题是一张看起来完全正常的PNG图片,文件名是signin.png,大小1MB多。这类“签到题”多数不会太难,但也不至于直接藏明文,需要按部就班排查。
我用file命令确认这是一个PNG文件,文件头和文件尾都正常。接着用strings搜索图片里的可打印字符串,结果没有发现flag相关字样。这一步没收获很正常,接下来就交给binwalk扫描是否有文件附加在图片尾部。
binwalk的原理是扫描文件中的已知文件头签名,比如JPEG、ZIP、PNG都有固定的十六进制特征。运行:
binwalk signin.png输出显示在偏移量某个位置存在一个ZIP压缩包。看到这个结果,我直接使用foremost或binwalk -e把这些附加数据提取出来:
foremost signin.png -o extracted分离出来的是一个加密的压缩包,里面有一个flag.txt。到了这一步,题目的重点就变了——不再是图片分析,而是压缩包解密。后面会详细讲压缩包怎么处理。
这里想强调一个实际经验:看到图片时,不要只盯着像素层看,先检测文件尾部是否有附加数据。很多出题人喜欢把压缩包直接用cat secret.zip image.png这样的命令拼接到图片后面,然后用strings或binwalk就能发现线索。
2.2 深入像素层的LSB隐写手法
另一道图片题没有附加数据,binwalk扫得很干净,strings也没有结果。这时候怀疑方向就要转到像素层隐写,最常见的思路是LSB隐写。
LSB是Least Significant Bit的缩写,意思是图像每个像素颜色分量的最低位。人眼对颜色变化极其不敏感,把RGB分量最低位的数值替换成隐藏信息的内容,图片看起来和原来几乎完全一样。隐藏的文本可以按顺序写入每个像素的最低位,然后按行拼接还原。
检测这种隐写,我推荐先用zsteg快速扫描:
zsteg -a challenge.png它会遍历PNG和BMP的RGB通道组合,自动检测LSB是否出现可读字符串。如果zsteg没有直接出结果,就用StegSolve手动分析。
StegSolve的操作路径是:打开图片,选择Analyse菜单的Data Extract,在红绿蓝三通道里分别勾选不同位,然后观察生成的图像上是否出现规律性文字。如果你看到一行整齐的ASCII字符显现出来,直接抄下来就是答案。
还有一个容易被忽略的技巧:藏信息不一定在RGB三个通道上,有时候在Alpha通道。Alpha通道是透明度信息,在PNG格式中存在但人眼感知不明显,许多图片查看器甚至不会渲染它。StegSolve里的Alpha选项一定要记得试。
注意:有些题目会把LSB信息水平或垂直翻转存放,或者做整张图片的旋转、镜像变换。如果在通道分析里看到字符明显是反的、倒的,把图像旋转180度或者水平翻转再读,往往就有结果了。
3. 压缩包密码那些事:伪加密判定与爆破实战
3.1 伪加密的判定与修复方法
前文提到的分离出来的压缩包,双击会提示需要密码。但很多CTF选手都知道,压缩包并不一定真的加密了,很多题的“加密”只是伪加密。
ZIP文件的结构由三部分组成:本地文件头、数据区、中央目录文件头。加密标记位存放在“通用位标记”(General purpose bit flag)的第0位。如果这一位是1,解压软件就认为文件被加密了,要求输入密码。伪加密的原理很简单:标记位置了1,但数据区并没有真正加密。解决办法是把标记位改回0,然后直接解压。
实际操作时,用十六进制编辑器打开压缩包,定位到ZIP文件头签名50 4B 03 04,这是PK汗衫的十六进制表示,也就是PK\x03\x04。文件头签名后面的第2和第3个字节就是通用位标记。常见值是09 00或08 00,把它们改成00 00,保存文件后再次尝试解压。
如果只用Windows资源管理器或者常规解压软件,遇到伪加密包还是会被提醒输入密码。所以判断是否为伪加密时,我一般先看文件头里的通用位标记,标记位的后一位是加密方式(传统ZipCrypto还是AES)。真正的加密文件,数据区里的内容也是乱的,伪加密文件的数据区则有明显的明文特征,例如可读文本或者压缩数据的正常结构。
3.2 密码爆破:不要盲目上大字典
确认是真实加密后,才需要考虑爆破。CTF里的压缩包密码通常不会太复杂,常见套路是把某一串英文单词、日期、或题目提示换几种大小写拼法作为密码。真正的爆破工具有fcrackzip、john配合zip2john,以及更现代的hashcat。
先用zip2john把压缩包的密码Hash提取出来:
zip2john encrypted.zip > hash.txt john --wordlist=rockyou.txt hash.txt这里有一个新手特别容易犯的错:直接上rockyou这种超大字典,跑几小时不出结果还傻等。做题不像破解真实目标,密码往往藏在题目上下文里。比如这道题解压出来的文件名是password_hint.txt,里面写着“the key is six digits”。看到这种提示,说明密码是一个6位数字,这时直接用fcrackzip指定纯数字范围爆破:
fcrackzip -u -l 6-6 -c 1 encrypted.zip参数解释:-u表示尝试解开并校验结果,-l 6-6指定密码长度范围,-c 1表示字符集是纯数字。几分钟内就能出结果。实际那次跑出来的密码是199809,就是年份加日期的拼接。这类密码在比赛里出现频率极高,手动拼几个常见组合先试也不亏。
需要提示的是:CTF竞赛中的破解对象都是出题人提供的文件,所有测试都处于授权范围内,学习压缩包破解原理只是为了熟悉文件格式特性。
4. 流量分析:在PCAP文件里翻出隐藏的文件
4.1 先看统计信息,再定位可疑流量
第三道题给了一个capture.pcapng文件,这是Wireshark的标准抓包格式。打开流量包以后,不要直接人肉翻滚数据包列表,那是效率最低的找法。
Wireshark最常用的切入点有三个:
- 统计菜单里的Protocol Hierarchy(协议分级),看哪种协议占比最高。如果一个流量包里出现大量HTTP流量,大概率是文件传输相关操作。
- 统计菜单里的Conversations(会话列表),按数据量排序,找出数据量最大的IP对。数据量异常的会话最有隐藏文件。
- 先用显示过滤器直接筛选协议类型。HTTP流量题通常数据量巨大,直接用
http.request或者http.response过滤关键请求。
当时这份流量包里有很多HTTP请求,其中几个请求的URL指向.php,返回体比较大。我直接用Wireshark的导出HTTP对象功能:File -> Export Objects -> HTTP,会列出所有HTTP响应,按大小排序就能看到几个可疑文件。其中一个响应体看起来像是ZIP文件,点Save导出后,发现又是一个加密压缩包。
4.2 追踪TCP流提取二进制文件
HTTP导出对象是最快捷的方式,但不是每次都有效。有些题目把文件藏在非标准端口、非HTTP协议的TCP流里,这时候要手动追踪TCP流。
操作方法是在数据包列表中找到可疑连接,右键选择Follow TCP Stream,Wireshark会把这条TCP流的所有数据拼在一起展示。如果流里传输的是一个文件,你会在流内容里看到文件头特征,比如PNG是\x89PNG,ZIP是PK,JPEG是\xFF\xD8\xFF。
看到文件头之后,可以把流数据保存为原始二进制,再拖到binwalk里做进一步处理。实际操作中,保存TCP流时要注意选择Show data as Raw,否则保存出来的文件会带有多余的换行或十六进制文本,导致文件损坏。
流量分析题还有一个常见的坑:数据可能被拆成多个TCP分段,直接保存会截断文件。这种情况下要先确认TCP Stream的下拉框中只有一个Stream,如果出现包含多个Stream的提示,说明数据分散在多条TCP连接里,需要把多个流都导出后拼接。
经验之谈:遇到流量题,先看有没有HTTP对象导出是最省力的,没有明显HTTP流量再去看TCP流。如果TCP流里出现大段Base64字符串,复制出来解码,大概率直接就是文件内容。
5. 音频题的处理思路:频谱图里藏着字符串
5.1 波形分析和频谱分析的区分
音频隐写题给的是一个WAV文件。WAV是无损音频,可以随意修改不引入压缩失真,因此非常适合做隐写。
拿到WAV文件后,第一步是在Audacity里打开,看波形总览。大部分隐藏信息的音频可以分为两类形态:
一类是波形异常,比如有一段明显的长音和短音间隔,这通常是摩斯电码。例如短音0.1秒、长音0.3秒,间隔0.2秒,组合起来就能编码成点和划,再转成字母。
另一类是波形看起来完全正常,没有断断续续的怪异节奏,这时候就要切换视图到频谱图。Audacity的左上角轨道类型切换菜单里,把Waveform改成Spectrogram,就能看到频率分布。
频谱隐写的原理是在某个特定频率上叠加信息,比如隐藏字符串被嵌入到固定频率的持续信号里。当你把视图切换到频谱图后,会看到某一段频率范围内出现一排字符形状的高亮图案,那就是隐藏文本。如果看不到,可以调整频谱图的亮度、对比度,有时还要把视图缩放比例调大,字符才会清晰显现。
5.2 用Audacity还原隐藏信息的操作流程
那场比赛里的音频题,我在波形视图里看了很久没有发现异常,节奏一致、音量均匀。切换到频谱图后,立刻在中间频段看到一行英文和数字组成的字符串。
直接截图辨认即可,但要注意字符的反向问题。有些花活会先把字符串水平翻转再嵌入频谱,你在频谱图里看到的d其实是b。如果是正向字符串,直接记录;如果感觉字母形状是反的,用Audacity的效果 -> 反向把整段音频翻转,然后再看频谱,文字方向就会恢复正常。
如果频谱图里的信息表现为整齐排列的点与划,那就还原成摩斯码解。摩斯码的点通常表现为短促的高频信号带,划表现为延长的信号带。把时间轴拉大,用Audacity的选择工具测量每个标记的时长,人工记录后转成ASCII码。
顺便提一句,音频题还有一种比较少见的隐藏方式,叫“相位隐写”或“回声隐写”,需要在特定的分析工具里才能看到,常规思路扫不出来的题就先用耳朵听,完全听不出异常再上频谱分析。那场比赛的音频题属于一眼能看出来的类型,不需要复杂分析。
6. 常见问题排查与比赛心态心得
6.1 工具扫不出来的情况
做Misc题,最崩溃的时刻是binwalk扫了没反应、strings也没搜到、StegSolve看了一圈没东西、Wireshark导出也没收获。这种时候容易怀疑自己是不是漏了关键步骤,但更常见的原因是方向从一开始就跑偏了。
我常用的补救顺序是:
- 回头确认文件类型。
file命令输出与文件扩展名不符的情况很常见,扩展名是.png但实际是空文件头、或者是个GIF,都会影响后面的判断。 - 检查图片尺寸和CRC。用
pngcheck看PNG的IHDR长度和宽度是否被修改过。有些题故意把图片显示区域改小,实际内容在改小的尺寸之外,修复宽高后图片才会显示完整信息。 - 尝试把文件扔进
strings -n 10只搜较长字符串,比默认的4字节阈值更能过滤无意义输出。 - 如果文件是图片且看起来像损坏,尝试用
hexedit检查每一段数据块是否完整。 - 零收获时,把文件放到纯文本编辑器和十六进制编辑器里分别打开,肉眼扫一遍头部和尾部几百字节。有些线索就明晃晃写在那里,只是命令行工具没搜出Flag关键字的变体。
6.2 爆破长时间没结果要果断止损
压缩包爆破是Misc里面最容易浪费时间的环节。我的经验是:如果跑了一个小时还没有任何进展,立刻停掉,回头检查题目描述、文件名、分离出来的其他文件,甚至观察压缩包内的文件名本身。很多密码线索就藏在文件名里,比如password_1839.zip这种命名,密码基本就是1839。
实在没有线索的时候,可以尝试短字典组合,把年份、比赛缩写、admin、root、flag等常用词做排列组合,数量控制在几百条以内,手工写脚本或者直接用crunch生成小字典。不要因为题目“看起来很难”就一上来用几十GB的通用字典,那是商业渗透的思维,不是CTF的思维。
6.3 学会写十几行的小脚本
Misc题目遇到二进制操作时,手工修改经常容易出错。比如要从一个文件里提取特定偏移的数据、要把RGB像素逐位拼成二进制字符串再转ASCII,这些操作写Python脚本比任何图形工具都更可控。
举一个实际例子,提取图片LSB信息时,可以直接用Pillow库逐像素处理:
from PIL import Image img = Image.open('challenge.png') pixels = list(img.getdata()) bits = '' for r, g, b in pixels: bits += str(r & 1) bits += str(g & 1) bits += str(b & 1)然后把bits按8位一组转成字节,再搜索可打印字符串。这种脚本虽然简单,但胜在完全可控,不会因为图形界面某个选项勾错而漏掉信息。
心得:比赛前花两个小时把binwalk、zsteg、pngcheck、Audacity的常用操作练熟,比考场上临时查资料高效得多。Misc题本身不难,输了时间基本就是输在工具不熟。
6.4 时间分配与取舍
Misc是一个解出速度快的方向,也是很容易被人卡住的方向。一场比赛里,我给自己设定的规则是:单题超过四十分钟没有任何有意义的进展就果断放弃或放缓,先把其他题目扫一遍。
Misc许多题的Flag也可以在其他方向里找到。比如一道Web题可能有一个图片附件,里面也藏着一部分Flag。花时间来回测试一道题,不如先收集所有能收集的信息,回头再集中突破。
这次2021比赛Misc方向的题目总体难度适中,靠的就是细心和工具熟练度。如果你在准备下一场比赛,把上面这些文件分析、图片隐写、压缩包处理、流量导出、音频频谱分析的套路练熟,再遇到类似题目就不会手忙脚乱了。最后想说的是:Misc的高分不是靠天分,是做多了题、踩过了该踩的坑之后自然会有的手感。