资讯动态

CTF Misc入门:zip伪加密原理与十六进制手修实战

发布时间:2026/10/19 4:42:42 来源:尧图企业网站定制
CTF Misc题里zip伪加密可以说是入门绕不开的一道坎。我最早遇到伪加密题目是某场比赛给了一个放在附件里的zip包双击直接弹密码框。当时我以为密码线索藏在图片、压缩包注释或者文件名里结果翻遍所有素材最后才发现是zip文件本身的结构被人动过手脚。后来刷题多了发现不少师傅第一眼看到带锁的zip就会条件反射去跑字典但伪加密根本不需要爆破改了标志位就是送分题。这篇文章就把我自己的复现过程、原理理解和几个踩坑记录整理一下希望能让刚接触CTF Misc的读者少走弯路。1. 项目概述带锁却无锁的zip包1.1 这道题到底考什么先明确一下伪加密是什么。正常的zip加密是对压缩数据本身做了加密处理解压时必须输入正确的密码由解压工具先解密再解压。而伪加密是通过修改zip文件头里的某个标志位让解压工具以为这个压缩包被加密了。实际上压缩数据根本没加密过只是被一个“纸糊的锁”锁住了。CTF Misc题目里经常用这一招来考察选手对文件格式的理解。题目通常表现成一个zip包打开时提示需要密码且没有任何提示密码的线索。很多新手卡在这里是正常的因为第一反应是找密码、猜密码、跑字典而不是去怀疑这个zip包本身有没有“说谎”。1.2 为什么“送分题”反而容易翻车zip伪加密一直被归类为送分题但我在物理和线上赛都见过不止一个队伍在这种题上浪费大量时间。主要原因有三个。第一个原因是工具依赖症。很多新手知道用某个工具能一键修复但当工具失效、报错或者题目加点花样时就不知道从哪里下手。第二个原因是概念混淆。伪加密和真加密在文件图标、解压提示上几乎一模一样不打开十六进制看结构很容易把伪加密当成真加密去爆破。第三个原因是改错字节。zip文件里面相关标志位不止一处本地文件头和中央目录都有各自的标志位漏改一处就解不开误改其他标志位又可能让压缩包直接损坏。所以这篇复现总结的重点不是教一个“解题命令”就完事而是把zip结构、标志位含义、修复流程、判断技巧都讲清楚真正做到遇题不慌。2. 工具准备与第一轮信息收集2.1 工具清单与选型理由我复现伪加密题目时用的工具组合比较固定这里列一个清单file快速判断文件真实类型binwalk检查是否有文件拼接或打包结构010 Editor / WinHex打开十六进制视图手动修改标志位7-Zip / WinRAR作为常规解压工具验证结果ZipCenOp.jar一键修复伪加密的备用工具zipdetails / python zipfile模块分析zip内部的记录结构工具不在多关键是要理解每个工具起什么作用。比如binwalk适合检测“一个文件里是否藏着别的东西”许多Misc题目会在一个正常图片里拼接一个zip或者在zip后追加一串隐写数据这些都能通过binwalk扫出来。010 Editor则是手动修复的核心遇到工具修不了的情况最终还是靠它直接改字节。2.2 先别急着改字节信息收集三连拿到一个zip包我的习惯是先做三件事。第一步用file命令确认文件类型避免被拓展名误导。有的题目把zip包改成jpg后缀或者反过来直接在图片末尾拼一个zip直接双击打开是图但把后缀改回zip或者用binwalk分离后才是真身。$ file flag.zip flag.zip: Zip archive data, at least v2.0 to extract如果file输出的是JPEG image data之类的东西那就要警惕了大概率是文件伪装或者拼接。第二步用binwalk扫描整体结构看看是否只有一个zip文件还是zip里面还嵌套了其他文件。$ binwalk flag.zip DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 Zip archive data, at least v2.0 to extract输出结果是只有一个zip档案说明题目没有在文件前后拼接杂项重点可以完全放在zip本身的结构分析上。如果binwalk扫描出多个Zip archive data那就要先用binwalk -e分离再逐个检查。第三步用7-Zip或者WinRAR打开试一次注意观察解压时的提示。如果提示“需要密码”先不要急着爆破接着用zipdetails看一下内部记录。这一步是收集线索不是解决问题。3. 拆解zip伪加密的底层原理3.1 zip文件的“三巨头”结构要理解伪加密就得先认识zip文件的基本骨架。一个完整的zip文件至少包含三部分本地文件头Local File Header以PK 03 04起始、中央目录Central Directory以PK 01 02起始、中央目录结尾记录End of Central Directory以PK 05 06起始。本地文件头描述了压缩包内某个条目的基础信息例如文件名、压缩方式、压缩后大小、原始大小、CRC校验值以及一个很重要的“通用位标记”general purpose bit flag。中央目录则记录了整个压缩包所有条目的索引和属性可以被理解为整个zip包的文件目录。解压工具打开一个zip时首先读取中央目录再根据目录中的偏移量定位到各个本地文件头。之所以要在伪加密问题上强调“三巨头”是因为加密标志位在本地文件头和中央目录里各有一份。新手只改其中一处往往出现“看起来改好了其实还是解不开”的情况原因就在于此。3.2 伪加密到底改了哪个字节“通用位标记”是zip文件头里一个2字节的小端无符号整数其中第0位bit0为1表示该条目使用密码加密。正常压缩的zip包bit0通常是0如果某个包打开时被要求输密码要么是数据真的加密了要么是bit0被人为改成了1。为了更直观我用十六进制演示一个常见的本地文件头开头50 4B 03 04 14 00 00 00 09 00 ...这一串里50 4B 03 04是本地文件头签名接下来的14 00是两个小端字节代表解压所需的最低版本。再往后两个字节00 00是通用位标记的低位和高位表示按小端顺序组合后是0x0000。但示例里这里是09 00组合后为0x0009。0x0009这个值包含了两个标志位bit01表示加密bit31表示存在数据描述符Data Descriptor。也就是说这本来可能是一个0x0008标志的普通zip条目题目作者将bit0置为1变成了0x0009于是所有解压工具都会把它当成“加密文件”。再看中央目录中的对应部分中央目录头签名是50 4B 01 02通用位标记位于签名后偏移8个字节的位置仍然是2字节同样是0x0009。修复伪加密的操作很简单把本地文件头和中央目录里通用位标记的bit0都清成0数据解压就完全正常了。3.3 本地头、中央目录、EOCD的联合校验顺着结构继续往下看还有两个细节需要理解。第一很多解压工具是“信中央目录”的。它们先读中央目录决定这个包能否解压、是否需要密码。所以如果你只改了本地文件头的标志位没有改中央目录里的标志位很多工具依然会提示密码错误。反过来只改中央目录不改本地头部分工具能绕过去但遇到校验严格的工具就会出问题甚至解出来的文件内容损坏。最稳妥的做法是两个地方的bit0一起清掉。第二并不是把所有标志位都清零就万事大吉。如果一个zip条目本来就有数据描述符标志位bit3你把0x0009改成0x0000结果相当于删掉了数据描述符标志可能影响流的读取和CRC校验。正确做法是按位操作只清bit0保留其他原有标志位。我在实际修复时更推荐用十六进制编辑器手动把09 00改成08 00而不是直接改成00 00。中央目录结尾记录EOCD本身不包含加密标志位但它是zip文件正常结束的重要位置也经常被用来做文章。有的题目会在EOCD后面追加一串十六进制数据里面藏着真正的flag有的题目会把EOCD的注释字段写得特别长隐藏线索。所以排查时别光盯着文件头文件末尾也要看一眼。4. 完整实操从十六进制修复到手写脚本4.1 题目现场还原我这次复现的题目是某场比赛Misc方向的一道模拟题。附件就是一个zip包解压提示输入密码没有任何额外的密码线索。按前面信息收集的流程走完file确认是zipbinwalk没有发现额外拼接块说明问题集中在zip自身。在动手修改之前先用010 Editor打开zip包按快捷键搜索十六进制字符串50 4B 03 04定位本地文件头。我习惯把光标停在签名起始处然后记下当前偏移量。再搜索50 4B 01 02定位中央目录头。zip里条目不多来回切换看一下结构就很清晰了。第一次分析的时候本地文件头的通用位标记位置显示为09 00中央目录的位置也显示为09 00基本可以断定是伪加密。为什么敢断定因为常见的真正加密压缩包通常不止改一个标志位压缩数据部分也能看到明显的加密特征而伪加密的典型表现就是本地头和中央目录都只有bit0被置位其他地方与原zip几乎没有任何差异。4.2 手动修改十六进制全流程定位到本地文件头后偏移6处就是通用位标记。当前值是09 00小端含义是0x0009bit0是1。我把它改成08 00也就是0x0008保留数据描述符标志清除加密位。保存文件。用同样的方法定位中央目录头在偏移8处找到同一份通用位标记仍然从09 00改成08 00。保存关闭后用7-Zip测试解压这次不再提示密码文件直接解出来了。需要特别提醒的是修改前一定先备份原文件。万一误改导致压缩包损坏还能退回去重新分析。我在第一次手改的时候就犯过把版本号当成标志位的低级错误结果把54 00版本改成00 00压缩包直接打不开后来靠备份才救回来。看十六进制时建议先列出偏移量、对应字段再动手别只盯着那一排字节凭感觉改。4.3 用Python脚本批量修复手动修改适合单个文件如果题目里有多个zip包或者嫌来回搜索太麻烦可以直接写一个小脚本把所有通用位标记的bit0清掉。下面这个脚本同时处理本地文件头和中央目录比较实用import struct import sys def fix_zip_encryption(path): with open(path, rb) as fp: data bytearray(fp.read()) local_count 0 central_count 0 for i in range(len(data) - 4): if data[i:i 4] bPK\x03\x04: flag struct.unpack(H, data[i 6:i 8])[0] if flag 0x0001: data[i 6:i 8] struct.pack(H, flag ~0x0001) local_count 1 continue if data[i:i 4] bPK\x01\x02: flag struct.unpack(H, data[i 8:i 10])[0] if flag 0x0001: data[i 8:i 10] struct.pack(H, flag ~0x0001) central_count 1 continue with open(path, wb) as fp: fp.write(data) print(f[] 本地文件头修复: {local_count}) print(f[] 中央目录修复: {central_count}) if __name__ __main__: fix_zip_encryption(sys.argv[1])脚本思路很简单遍历整个文件字节序列找到本地文件头签名就检查偏移6处的通用位标记找到中央目录签名就检查偏移8处的通用位标记只要bit0是1就清除。注意flag ~0x0001这种写法是为了只去掉加密位而保留其他标志位比直接赋0更安全。运行方式python3 fix_zip.py flag.zip脚本输出修复数量后再用unzip验证$ unzip flag.zip Archive: flag.zip inflating: flag.txt看到inflating而不是“password required”基本就成功了。4.4 修复结果验证解压成功后先别急着欢呼还要做一次内容验证。有些包即使修改了标志位文件也能解出来但解出来的内容是乱码这时候就要重新审视它到底是不是伪加密。验证方法比较直接解压后打开文件看看内容是否是可读明文如果解出来是二进制乱码说明数据部分确实被加密过需要继续找密码或者其他线索。另外解压成功不代表原包一定被正确修复了。我用010 Editor重新打开修复后的zip检查本地文件和中央目录中的通用位标记都变成了08 00且其他字段没有被误改这才算收尾。严谨一点的话还可以用文件校验工具对比解压文件的CRC和中央目录里记录的CRC是否一致一致说明数据完整。5. 常见问题与排查技巧实录5.1 改完还是提示密码这是伪加密题目里最经典的翻车现场。我在实际带新人的时候发现十个卡在这里的人里有八个是只改了本地文件头没有改中央目录。前面原理部分说过解压工具优先读取中央目录中央目录里的bit0不改本地文件头改得再干净也没用。另一个可能原因是改错了位置。通用位标记在小端序下09 00表示0x0009如果你把00 09当成0x0009去改虽然十六进制看起来都是“改了标志位”但实际修改的字段完全不同。要记住标志位的两个字节在小端序下是“低字节在前”判断时一定要按偏移定位而不是看到00就懒得往前翻。还有一种情况是zip包里有多个文件条目本地文件头不止一个。有些新手扫描到第一个本地文件头改完就跑了后面条目仍然带着加密位。这时候可以再用脚本跑一遍看输出里修复了几个本地文件头如果数量与压缩包内文件数不一致说明漏了。5.2 伪加密还是真加密先别急着猜拿到一个要求密码的zip不建议直接凭图标判断它是伪加密还是真加密。我自己的习惯是分三步走。第一步看通用位标记本身。如果原包的标志位是0x0001、0x0009这样明显只有加密位被置上的组合伪加密嫌疑很大。如果标志位组合和压缩方式比较特殊比如AES加密的包通常还会有额外的加密算法标识字段那会更接近真加密。第二步看压缩数据区域。伪加密的压缩数据本身是明文的意味着如果压缩方式是Stored不压缩你甚至能在文件数据中直观看到原始文件内容的关键字符。但在不看明文的情况下可以用zipdetails查看每个条目的压缩大小、CRC等参数伪加密包往往和正常包几乎一致。第三步直接把bit0清掉再试。改完标志位后如果能正常解压且内容可读说明伪加密解压出乱码或者解压失败说明它原本就是真加密需要继续寻找密码线索。这个方法虽然有点“先动手再分析”的意思但实际解题效率很高。我把判断逻辑整理成一张表现象可能原因处理方案提示密码binwalk无附加数据伪加密或真加密查看本地头与中央目录的bit0bit0为1其他标志位正常疑似伪加密清除bit0后尝试解压清除bit0后解压出明文确认伪加密直接读取flag清除bit0后解压出乱码真实数据加密回头找密码线索或爆破清除bit0后仍然要求密码中央目录没改或改错位置回到010 Editor重新检查5.3 题目里的其他隐藏坑除了标志位本身zip伪加密题目还经常在文件结构上做手脚这里记几个常见套路。有的题会把一个正常zip和一个伪加密zip拼接在一起文件打开速度正常但解压会出错这时候要用binwalk先把两部分分离再分别做伪加密修复。有的题会把文件名本身伪装成假后缀比如flag.txt后面加了很多空格或者用不可见字符让文件名看起来正常解压出来才发现不是目标文件。还有的题会在本地文件头与文件数据之间塞入额外字段影响解压工具对偏移量的判断手动改完标志位后如果还是报错检查一下额外字段长度是否被改过。在EOCD注释里藏线索也是Misc常见做法。修复完伪加密之后建议顺手用十六进制编辑器拖到文件末尾把EOCD前后的数据都扫一遍。统计下来我在这类题目中遇到过好几次“伪加密只是开局真正的flag藏在注释里”的情况。6. 个人心得与后续延伸6.1 为什么理解结构比记住工具更值钱刷题刷久了会发现真正让你与别人拉开差距的不是多会背工具名而是能不能在工具失效的瞬间直接用十六进制编辑器看懂文件在说什么。伪加密这道题的价值并不在于它本身多难而是通过它你可以熟悉zip文件的整体结构。理解了通用位标记以后再遇到压缩包相关的变形题比如故意闭合zip、修改压缩方式、篡改CRC校验值你就能立刻建立起排查方向而不是拿到文件就蒙。我刚入门时也很依赖可视化工具某个工具一旦不支持某一类变体就只能乱试。后来强迫自己用010 Editor打开每一个zip逐个字段对照慢慢才建立起了“看到一串十六进制能脑补出它属于哪个区域”的能力。这个过程没有捷径但伪加密是一个极佳的练手对象因为文件小、结构常见、修改点明确。6.2 后续还可以继续深挖的方向想起一个延伸点不只是zip文件有伪加密APK、JAR、Office的docx/xlsx等本质上都是zip容器同样适用这套伪加密的原理和修复思路。我之前遇到过打包成jar的CTF题里面某个.class资源文件被标记成加密实际数据还是明文用同样的方法去掉bit0就能正常读取对后续逆向分析帮助很大。另一个值得尝试的方向是写一个更完整的zip解析脚本不要只依赖在字节流里搜索PK签名而是真正从EOCD解析出中央目录偏移量再按偏移量精准定位每一个本地文件头。这样能避免误改某些刚好包含PK签名的数据也能进一步锻炼对二进制格式的理解。最后再用自动化脚本串联“扫描-解析-修复-验证”四步比赛里遇到同类型题目十几秒就能出结果。伪加密本身是个小知识点但只要愿意深挖它能带出来的东西其实不少。希望这篇复现总结能帮你少踩几个坑下次再看到带锁的zip先想想它有没有真的上锁。我自己也还在继续整理其他压缩包相关的变形题后续有新的复现心得再补充分享。

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

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

免费获取报价 →
↑