ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

CTF Misc26-30刷题:GIF隐写、PNG修复、伪加密与流量分析实战

CTF Misc26-30刷题:GIF隐写、PNG修复、伪加密与流量分析实战 最近在BUUCTF上按题号刷Misc正好刷到26到30这一档。说实话这五题难度不高但考点非常典型GIF逐帧隐写、PNG高度修复、压缩包套娃与伪加密、密码爆破加LSB隐写、流量分析配合二维码修复。如果你已经在Misc题里刷过几道但总在“该用什么工具”“分离出来之后怎么继续”这类环节卡壳这篇文章可以直接当作业抄。我会按题号把每道题的完整思路、操作命令、报错排查看下来答案统一打码方便你自己跑一遍。先提醒一句Misc题不存在什么高深算法拼的就是对文件格式和工具链的熟悉程度。26到30正好覆盖了最常考的五个方向把这几题吃透后面再遇到图隐写、压缩包、流量包基本就是换个文件名重复同样的流程。1. 先补齐视野Misc26-30的考点分布与工具准备1.1 这五道题正好串起Misc的核心考点我按编号把这几道题的考点整理了一下你可以对着这个表快速定位自己卡在哪一类题号核心考点主要工具翻车点Misc26GIF多帧隐写StegSolve / ffmpeg只看了第一帧Misc27PNG高度修复 CRC校验010 Editor / Python脚本改高度不重算CRCMisc28压缩包套娃 伪加密binwalk / 7-Zip / 010 Editor被伪加密骗去爆破Misc29密码爆破 MD5提示 LSBARCHPR / StegSolve / 在线解密没先看提示就硬爆破Misc30流量分析 二维码修复Wireshark / CQR / 画图工具定位角补错位置这个表看着简单但它其实代表了一类很常见的出题套路每道题只考一个点但题目外面会包上各种伪装。比如Misc27表面上是一张“显示不全”的PNG实际考的是PNG块结构Misc28表面上是一堆压缩包实际考的是对伪加密特征的识别。你做的时候如果只盯着表面现象很容易绕远路。另外这五题还有一个共同点只要第一眼把文件头看准解题思路基本能确定一半。所以下面每一步我都会带上“怎么判断”的过程而不是只给结论。1.2 环境准备确认你的兵器库刷Misc题最忌讳工具装了一堆但不会用。针对这五题我实际用到的东西就这么多列成清单你照着装就行Windows环境010 Editor看十六进制和PNG块结构StegSolveJava版解GIF帧和LSBARCHPR压缩包爆破7-Zip解套娃压缩包。Linux环境binwalk文件分离Python3跑CRC修复脚本zsteg/Steghide图片隐写备用。流量分析Wireshark这个必备后面Misc30要用它导出HTTP对象。辅助工具在线MD5解密站破解32位hex提示、CQRPython二维码纠错库、ffmpeg抽GIF帧。工具数量控制在十个以内就够了多了反而分散注意力。我自己平时主用Windows只有在binwalk分离文件或者跑脚本时才切到WSL或虚拟机。StegSolve需要Java环境启动命令是java -jar stegsolve.jar第一次用容易忘记加java -jar直接双击会报错。这里有个经验binwalk在Windows下的体验不算好尤其是遇到大文件或者嵌套压缩包时容易卡死建议直接用Linux环境或者WSL里的binwalk输出的文件结构也更清楚。后面Misc28的套娃压缩包我就是在WSL里用binwalk -e一步分出来的。2. 图隐写两题从GIF逐帧到PNG高度修复2.1 Misc26GIF的每一帧都可能藏着话Misc26拿到手是一个动态图片文件。这题第一眼很有迷惑性浏览器打开后是一个不断轮播的动图画面里有个像是flag的字符串一闪而过但你截屏永远慢半拍。这里最关键的一步是意识到动图是由多帧组成的flag就藏在其中某一帧里你要做的不是盯屏幕而是把每一帧拆出来。我用的方案是StegSolve打开文件后走Analyse - Frame Browser左侧会列出所有帧逐帧点击右侧看图像内容。实际操作中前面几帧都是无关的图案到我数到第5帧时才看到完整的一行flag字符。这里有一个容易被忽视的细节StegSolve的Frame Browser默认加载第一帧如果你直接在原始Image窗口里看永远只能看到第一帧的内容不会自动播放所以一定要进Frame Browser界面。如果你的GIF帧数特别多或者StegSolve打开直接报错可以改用ffmpeg抽帧ffmpeg -i misc26.gif frame_%03d.png这个命令会把每一帧导出成单独的PNG图片然后你只需要写个简单的文件列表按顺序翻就行。实测下来StegSolve对帧数少、尺寸小的GIF很稳定一旦帧数上百用ffmpeg批量导出再快速预览反而更高效。再补充一个让新手比较容易忽略的问题有些GIF帧里藏的不是明文字符而是反色图片或者需要调对比度才看得见的信息。如果逐帧翻完没发现明显flag可以试试StegSolve的Analyse - Image Combiner和帧反色功能把可疑帧反色后再看。Misc26没到这一步但我在其他题里踩过这个坑提前说一声省得你绕路。2.2 Misc27修复PNG高度把flag“拉”出来Misc27拿到手是一张普通的PNG图片图片只显示出一部分下方一大片是黑底或者直接截断。第一反应是丢binwalk和strings都没线索这时候就该怀疑图片本身被改过了。CTF里最常见的操作之一就是修改PNG的IHDR块里的高度值把图片“裁剪”到只剩一部分而实际像素数据仍然留在文件里。要理解这个操作得先知道PNG的文件结构。PNG文件以固定的8字节签名开头89 50 4E 47 0D 0A 1A 0A之后跟着若干数据块。每个块的结构是4字节长度、4字节类型、数据、4字节CRC校验。其中IHDR是第一个块长度固定13字节前4字节是图片宽度紧接着4字节是图片高度。用010 Editor打开文件后偏移16到19是宽度偏移20到23是高度。我把Misc27的PNG用010 Editor打开后看到宽度正常高度却只有00 00 01 2C。作为参考一张正常的完整图片高度不应该只有这么一点明显是被改小了。处理方案很简单把高度改大让图片“恢复”出完整尺寸。我直接用010 Editor编辑把高度改成00 00 02 58然后保存。但这里有一个大坑PNG每个数据块末尾4字节是CRC-32校验值它由块类型和块数据共同计算得到。你只改了高度数据CRC还是旧的图片打开时会直接报“CRC mismatch”或者干脆打不开。所以改完高度必须重算CRC。用010 Editor手工算也可以选中IKDR块的类型和数据从偏移12到28共17个字节在菜单里算CRC-32把得到的新值写回偏移29到32。不过为了稳定我更推荐直接用Python脚本一次性搞定尤其是遇到需要反复试不同高度的情况import struct import zlib def fix_png_height(src, dst, new_height): data bytearray(open(src, rb).read()) # 偏移0-7是PNG签名IHDR块从偏移8开始 # 宽度在偏移16-19高度在偏移20-23 width struct.unpack(I, data[16:20])[0] data[20:24] struct.pack(I, new_height) # IHDR块类型数据为偏移12到28重算CRC crc zlib.crc32(data[12:29]) 0xffffffff data[29:33] struct.pack(I, crc) open(dst, wb).write(data) print(fwidth{width}, new_height{new_height}, crc{hex(crc)}) fix_png_height(misc27.png, misc27_fixed.png, 0x258)跑完脚本后用看图工具打开修复后的文件完整图片直接显示出来flag就印在下方原本被“隐藏”的区域里。Misc27到这里就结束了但思路可以通用以后遇到PNG显示不完整、显示区域异常优先检查IHDR里的宽高值再顺手检查一下CRC是否匹配。这个套路在Misc题里出镜率极高。3. 压缩包三连坑套娃、伪加密与暴力破解3.1 Misc28层层解压是体力活也是信息活Misc28给出的文件是一张图片但直接看图片什么都没有。按老规矩先跑一遍binwalk分离binwalk -e misc28.png分离结果里出现了一个压缩包还有一个看起来没什么用的文件。把这个压缩包解压里面又是一个压缩包再解压里面还是压缩包。这种套娃题最恶心的不是套得多而是每一层都可能加了点小机关。Misc28走到第二层时Windows资源管理器能正常显示压缩包内的文件名但双击文件准备解压时却弹出“需要密码”的提示。这就非常可疑因为前面一层根本没有提到密码而且这个压缩包的特征很符合伪加密。伪加密的本质是压缩包实际上没有加密数据只是在Zip文件头的“通用位标记”General Purpose Bit Flag里把加密标志位置成了1让解压工具误以为它需要密码。用010 Editor打开这个压缩包找局部文件头PK\x03\x04偏移6和7处的两个字节。正常情况下未加密是00 00这题里却是09 00把第0位加密标记和第1位压缩方式标记同时置位了。处理方法有两种一是直接把09 00改成00 00保存再正常解压二是直接换用7-Zip有时候它能自动忽略伪加密标志直接解压。我选择直接用010 Editor改成00 00因为这样最干净。保存后重新解压果然不需要密码。继续往里拆最后一层压缩包里终于出现了一个文本文件打开后里面是一个被切碎的flag片段再配合前面某一层的图片备注信息拼起来就是完整的flag。这类套娃题真正的信息点往往不在压缩包的深层而在每一层的边角料里。比如压缩包的文件名、文件注释、同目录下的小图片、甚至压缩包生产工具字段都可能藏提示。所以解压的时候不要只盯着压缩包本身每一层解完都顺手看一下同目录下有没有其他文件。3.2 Misc29爆破密码之前先破译MD5提示Misc29做起来要稍微绕一点。首先拿到的是一个加密的压缩包和一个看起来是图片的文件。压缩包明确加了密码尝试了常见的弱密码都不对。这时候先别急着上爆破我去翻了图片用StegSolve打开后没在通道里看到明显信息但用010 Editor拉了文件尾部的字符串发现有一段32位的hex字符。32位hex这种格式十有八九是MD5值。在线反查了一下这段MD5得到了一串明文试了下正好是这个压缩包的密码。这一步非常关键因为如果没注意到这个MD5提示直接去爆破压缩包密码如果是由大小写字母、数字混合组成的爆破时间会非常难看。所以做题顺序很重要先找提示再决定要不要爆破。解压之后里面是一张BMP图片。用StegSolve打开走Analyse - Data Extract这时候要处理的就是LSB隐写了。LSB隐写的原理说起来很简单图片每个像素由RGB三个通道组成每个通道是0到255的灰度值。人类对颜色最低位的改变几乎无感知所以可以把要隐藏的二进制数据按位写进这些最低位里。提取的时候反过来把每个通道的最低位按顺序取出重新拼成ASCII字符或者文件。在StegSolve的Data Extract界面里我勾选了R、G、B三个通道的0号位Bit Order选LSB First然后点击Preview按钮右侧信息区里直接出现了flag字符串。需要说明的是如果提取出来是乱码可以试试切换Bit Order为MSB First或者在颜色通道上换一种组合。LSB题的参数组合就这几种实际试一下最多几秒钟就能定位正确格式。3.3 压缩包题通用避坑清单把Misc28和Misc29放一起看压缩包相关的题目其实可以总结成一套固定处理流程我从这两个题里提炼了三条最实用的经验先判断是不是伪加密。在010 Editor里看局部文件头的通用位标记00 00是未加密09 00是典型的伪加密01 00也可能是。伪加密直接改标记或者用7-Zip解不用浪费时间去爆破。爆破前先搜提示。压缩包文件名、注释、同目录图片、甚至压缩包末尾的附加数据都可能是密码线索。Misc29的密码藏在MD5里在线反查一下就是明文你要是直接开ARCHPR爆破等于放着捷径不走。解压后先检查有没有第二层。很多题第一层解出来的文件本身还是一个待处理的容器要么再分离要么再解密。不要一解压出一个文本就急着找flag顺手看看这个文件大小是否异常、是不是还有嵌套。4. 第30题综合实战流量分析加二维码修复4.1 流量包里的蛛丝马迹从pcap导出关键文件Misc30拿到的直接就是一个pcap流量包文件。这种题型的核心思路是在别人抓好的网络流量里找到被传输的可疑文件或者关键字符串。打开Wireshark之后不要急着逐条看包先走Statistics - Protocol Hierarchy看看流量主要集中在哪些协议上。Misc30的协议分级统计里HTTP明显占了大头这说明文件传输大概率是通过HTTP进行的。确认重点后直接走File - Export Objects - HTTP这个功能会把所有HTTP传输中的对象列出来包括图片、压缩包、脚本等。我在这里看到了一个看起来像图片的PNG文件还有一个奇怪的文本文件。分别导出之后文本文件里是一段提示文字PNG文件则是一张被截断过或者被遮挡过的二维码图片。如果某个流量包的重点不在HTTP而在其他协议上排查方向也要跟着变。比如ICMP流量里经常出现异常大小的包负载里可能藏了数据DNS查询里可能藏了经过base64编码的子域名字符串甚至TCP流里明文传文件的情况也很常见。Misc30用的是HTTP所以这里只展开HTTP的流程。追关键TCP流时可以右键某个HTTP请求包选择Follow - TCP Stream直接看到请求和响应的完整内容有时flag就嵌在传输的数据里。4.2 修复二维码定位角把最后一段flag扫出来从流量包导出的二维码图片信息区域大体完整但三个角上的定位方块缺失了导致扫码工具识别不了。二维码的定位角是那个经典的“回”字结构通常分布在左上、右上、左下三个位置。很多题目会故意挖掉或者用其他图案覆盖这几个角你只需要把缺失的角补回去就能恢复识别。修复方法最直观的是用画图工具。先在一张完整的二维码图片里截取一个定位角复制到损坏图片上放在正确的位置。如果缺损的是对角位置就把复制出来的角旋转90度、180度或270度再贴上去。实际操作中我把左上角的定位角复制到右上角后扫码仍然失败后来发现是位置偏了几像素导致二维码整体的定位偏差全部错位了。所以粘贴的时候建议把图片放大到像素级对齐边缘不要凭肉眼随便放。补充完整之后手机扫码还是扫不出来我检查了一下发现图片四周没有留白。二维码识别要求图案周围有一定宽度的空白区域我用画图工具在四周各加了大概30像素的白边再扫码就顺利识别了。如果你不喜欢手动处理也可以考虑用Python的CQR库做纠错它能处理一定程度的污损和缺失但定位角如果缺失太多还是手动补齐更靠谱。最终扫码得到的字符串经过一次base64解码后拼接出了完整的flag。Misc30到这里解完整个26到30的区间也就刷完了。4.3 综合题拆解先分类再深挖Misc30这类综合题最大的风险不是不会用Wireshark而是不知道下一步该干什么。我的习惯是拿到文件后先做一次系统性的“体检”第一步用file命令看真实文件类型第二步用binwalk看有没有隐藏文件第三步用010 Editor快速过一眼十六进制头最后再根据结果决定进入哪条分支。这一套流程走下来Misc30的流量包、Misc28的图片、Misc27的PNG都能在几分钟内定位到正确方向。还有一个小习惯值得分享每道题做完我会在笔记里记一句“这题在考什么”。比如Misc26写“GIF帧遍历”Misc27写“IHDR高度CRC修复”Misc28写“zip伪加密识别”Misc29写“MD5提示LSB”Misc30写“HTTP对象导出二维码补角”。后来参加比赛遇到同类题目我翻笔记就能立刻想起工具和操作顺序这个积累比单纯刷题有用得多。我个人做完26到30的最大感受是BUUCTF的Misc题不追求脑洞考的是你是否熟悉文件格式和工具特性。第27题如果没有PNG块结构的概念你连为什么报CRC错误都看不懂第29题如果不知道先找提示再爆破可能浪费几个小时。工具本身都不复杂难的是建立“看到现象想到原因”的反射。这篇先更到Misc30后面继续往后刷的话我会按同样的格式把题解补进来。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进