news 2026/10/20 15:42:53

CTF实战:ZIP伪加密原理与010Editor手工修复全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CTF实战:ZIP伪加密原理与010Editor手工修复全解析

做CTF Misc的朋友,对.zip压缩包肯定是又爱又恨。每次拿到一个压缩包,双击一看出“输入密码”,思路就开始分裂:是爆破,是明文攻击,还是干脆这是个伪加密?zip伪加密这道坎,我当年卡了很久,尤其是用010Editor把标志位改了之后还是提示密码,差点以为是工具不好使。后来把ZIP文件结构搞清楚,才发现问题往往出在只改了一半。这篇文章以一个CTF平台上常见的MISC题为例,把zip伪加密从原理到实战完整拆一遍。全程用010Editor做十六进制手工修复,每一步都讲清楚为什么要这么改,以及在哪个位置改。

如果你刚接触CTF,或者被“压缩包要密码但找不到密码”卡住,这篇文章很适合照做。学会之后,以后遇到八成以上的伪加密题,三十秒内就能绕过。

1. 先摸清底细:zip伪加密到底“伪”在哪儿

1.1 ZIP文件的三段式结构

要改伪加密,就不能只知道“把某字节改成00”。你至少得知道这个字节长什么样、在哪一段里。ZIP文件表面上是一个整体,内部其实分了三块:

  • 本地文件头(Local File Header)
  • 实际的压缩数据(Data)
  • 中央目录(Central Directory)和中央目录结尾(End of Central Directory)

每一条压缩文件记录,都会有一个本地文件头,描述这个文件叫什么、用了什么压缩方式、数据放在哪里、原始大小多少。而中央目录则相当于整份压缩包的索引,把每条文件记录的元信息再汇总一遍,方便解压软件快速定位。你在Windows资源管理器里双击zip,系统第一件事往往就是读中央目录,看里面有哪些文件、是否标记了加密。

本地文件头和中央目录里各有一个“通用标志位”(General Purpose Bit Flag)。这个标志位占两个字节,其中最低的bit0专门用来标记“这条记录是否加密”。bit0为1,解压软件就认为文件加了密码;bit0为0,就认为是普通文件。

1.2 伪加密就是把“门锁”贴了假标签

“伪加密”的精髓在于:数据本身从头到尾都没被加密,压缩算法该是什么样还是什么样,但通用标志位里的加密位被改成了1。就好比一个抽屉根本没上锁,但外面贴了一张“此处有锁”的纸条。解压软件看到纸条,就停下来向你要密码。

很多CTF平台喜欢出这类题,就是因为代码实现简单,又能考查选手对二进制格式的敏感度。题目制作者用普通方式压一个文本进去,然后把本地文件头、中央目录里的标志位改成带bit0的值,让你误以为压缩包加了密。

常见的伪加密标志位值有两个:

  • 01 00:表示bit0置1,别的标志都是0。
  • 09 00:表示bit0置1,bit3也置1。bit3是“数据描述符”标志,有时代表示CRC和大小信息不在本地文件头里,而是放在数据段后面。

所以你在010Editor里看到的标志位,不一定是简单的“加密=1”,它可能同时携带了其他含义。这也是为什么网上有些教程让你把09改成00,但我在后面会建议你更稳妥地只清除bit0,比如把09改成08。这个差异看起来小,遇到某些严格解压工具时就是能不能解开的区别。

1.3 判断一个zip是不是伪加密

拿到压缩包,先别急着爆破。最快的方式就是打开010Editor,看本地文件头和中央目录的标志位。如果两个位置都出现了01 00或09 00,而文件里没有任何加密数据特有的字段,那大概率是伪加密。更专业的做法是看解压时的表现:正常加密的zip输入错密码会直接报错,伪加密则无论你怎么输都报错,因为核心数据根本没加密,解压软件只是在“检查密码”这一步就被拦住了。

还有一种判断技巧:用压缩软件打开,如果能正常看到文件列表、文件大小、甚至能预览,但解压时要求密码,这种也高度可疑。因为真加密状态下,很多软件连列表信息都要解密才能读全。

2. 工具选型与准备工作:为什么用010Editor

2.1 十六进制编辑器对比:010Editor的优势

处理二进制文件,可选工具很多:HxD、Hex Fiend、WinHex、010Editor。我只用010Editor,不是因为别的不能用,而是它有几个针对这类操作特别顺手的功能。

  • 支持一次查找所有匹配项,能把文件里所有50 4B 03 04列出来,不用一个个翻。
  • 有ZIP相关模板,能帮你看懂每段的含义。
  • 搜索和跳转偏移都很直观,适合做字节级修改。
  • 支持脚本,熟悉之后能把重复操作变成批处理。

不过要说明一点,010Editor是收费软件,但试用期足够做CTF题。HxD免费版也完全够用。工具不重要,重要的是你清楚自己在改什么。

2.2 实操前的两个好习惯

打开zip之前,我强烈建议先复制一份出来,命名成flag_fixed.zip,直接在副本上改。伪加密修改通常只有一两个字节,但一旦改错,原文件就废了。CTF赛题下载一次没问题,可如果是比赛环境下只能下载一次,你就知道备份有多重要。

第二步,在010Editor里把偏移显示打开,默认是十六进制偏移。这样你搜索到ZIP头后,能快速数到对应偏移位置。很多人改完发现没生效,就是数错了偏移。

另外,拿到文件先做基本检查:

file flag.zip

如果输出是Zip archive data,说明至少是个标准zip,不是藏在图片里的隐藏数据。CTF Misc题经常把一个文件塞进另一个文件尾部,所以也可以顺手用binwalk扫一下:

binwalk flag.zip

确认没有其他附加数据,再进入伪加密处理阶段。

3. 核心实操:010Editor手工修改伪加密标志位

3.1 第一步:定位本地文件头

在010Editor中打开zip副本,按Ctrl+F,搜索方式选“Hex Values”,输入:

50 4B 03 04

50 4B 03 04就是ZIP本地文件头的签名。找到之后,看签名后面的字节。本地方文件头的结构里,签名占4字节,第五、六字节是“解压所需版本”,第七、八字节才是通用标志位。

举个例子,你搜到的文件头开头长这样:

50 4B 03 04 14 00 09 00 00 00

逐段拆开:

  • 50 4B 03 04:本地文件头签名
  • 14 00:解压所需版本
  • 09 00:通用标志位
  • 00 00:压缩方式

也就是说,标志位从文件头偏移+6的位置开始,占两个字节。当前值09 00里,bit0是1,表示加密。我们接下来把bit0清零。

这里就是关键分歧点。如果按最粗暴的做法,把09 00整个改成00 00,大多数题目也能解压,因为原始zip本来就没用数据描述符。但为了不破坏bit3,更严谨的做法是:把值0x0009与0xFFFE按位与,得到0x0008,也就是改成08 00。如果原始值是01 00,改成00 00即可。

在010Editor里操作很简单:点击09这个字节,输入08,保存。

3.2 第二步:定位中央目录文件头

光改本地文件头,可能还是不够。接下来搜索中央目录签名:

50 4B 01 02

中央目录文件头比本地文件头多了几个字段。签名占4字节,第五、六字节是“版本由谁创建”,第七、八字节是“解压所需版本”,第九、十字节才是通用标志位。所以中央目录里的标志位在偏移+8的位置。

如果看到类似:

50 4B 01 02 1E 03 14 00 09 00 00 00

那么14 00后面紧跟着的09 00就是中央目录的标志位。同样,把09改成08,或者按原始值对应的正确结果修改。

为什么中央目录必须改?因为很多解压软件,比如Windows自带的资源管理器,读取的是中央目录而不是本地文件头。你只改本地文件头的话,资源管理器一看中央目录里还写着“加密”,照样找你要密码。反过来也一样,某些命令行工具可能优先看本地文件头。所以稳妥的做法就是两个位置都查到、都改到。

3.3 第三步:保存并验证

修改完成后,Ctrl+S保存。然后不要用010Editor去看解压效果,而是退出去,用命令行或资源管理器解压:

unzip flag_fixed.zip

如果之前是伪加密,这时会直接解压出里面的文件,不会问密码。如果还提示密码,也别急,往下看常见问题。

我这里多说一句:有的压缩包里有多个文件条目,意味着会有多个本地文件头和多个中央目录记录。你要分别查找所有50 4B 03 04和所有50 4B 01 02,把每条记录里偏移+6和+8的标志位都检查一遍。常见错误就是只改了第一个文件头,后面那个没管,结果解压到一半又被卡住。

4. 进阶:一条命令恢复和脚本自动化

4.1 用ZipCenOp.jar快速验证

如果你只是想快速验证某个zip是不是伪加密,还有一个老牌工具:ZipCenOp.jar。当年在CTF圈子里流传很广,命令是:

java -jar ZipCenOp.jar r flag.zip

这里的r表示restore,作用就是扫描zip里的本地文件头和中央目录,把加密标志位清掉。如果运行后提示成功,再用解压软件试一下,通常就能解开。

但这个工具有个缺点:它会把所有条目的加密位都清掉,不分真伪。如果遇到真加密的zip,执行之后压缩包会变坏,数据还是加密的,但标志位已经不认了。所以更适合做“验证伪加密”的操作,而不是最终修复手段。另外,它对中文文件名、非常规压缩选项支持一般,输出信息也比较含糊。我自己的习惯是:能手动改就手动改,手动改完如果失败,再用这个工具试试,反向排除问题。

4.2 用Python脚本批量处理

如果题目给你几十个zip,或者你想把整套操作沉淀下来,可以写个小脚本。核心逻辑还是那句话:扫描本地文件头和中央目录,把通用标志位的最低bit清零,其他位保留。

import struct import shutil def clear_fake_encryption(src, dst): shutil.copy2(src, dst) with open(dst, "rb") as f: data = bytearray(f.read()) # 本地文件头签名 PK\x03\x04,标志位在偏移 +6 idx = 0 while True: idx = data.find(b"PK\x03\x04", idx) if idx == -1: break flags = struct.unpack_from("<H", data, idx + 6)[0] if flags & 0x0001: struct.pack_into("<H", data, idx + 6, flags & 0xFFFE) print(f"local header at 0x{idx:04X}: flags 0x{flags:04X} -> 0x{flags & 0xFFFE:04X}") idx += 4 # 中央目录签名 PK\x01\x02,标志位在偏移 +8 idx = 0 while True: idx = data.find(b"PK\x01\x02", idx) if idx == -1: break flags = struct.unpack_from("<H", data, idx + 8)[0] if flags & 0x0001: struct.pack_into("<H", data, idx + 8, flags & 0xFFFE) print(f"central dir at 0x{idx:04X}: flags 0x{flags:04X} -> 0x{flags & 0xFFFE:04X}") idx += 4 with open(dst, "wb") as f: f.write(data) if __name__ == "__main__": clear_fake_encryption("flag.zip", "flag_fixed.zip")

这个脚本用了最简单的全文件扫描方式,对CTF题目里的小zip足够用。唯一要注意的是,如果压缩包数据段里恰好也出现了50 4B 03 04这样的字节序列,可能会被误判。不过题目文件一般都很小,实际遇到误判的概率很低。如果要写得更严谨,可以解析中央目录偏移,然后通过中央目录记录里的“本地文件头偏移”字段定位,但那就超出这次的篇幅了。

5. 实战案例复盘:一题看完整个解题链

5.1 拿到压缩包后的第一动作

用一次完整过程来说明。我在某个CTF练习平台上遇到一道MISC题,下载下来的文件名是misc1.zip,大小只有几百字节。先执行:

file misc1.zip unzip misc1.zip

unzip直接提示:

Archive: misc1.zip [misc1.zip] flag.txt password:

这时候千万别急着上爆破工具。几十万条密码跑下去,大概率白费力气。先问自己:题目有没有给任何密码线索?如果没有任何提示,伪加密的可能性立刻排在前面。

用binwalk扫了一下,没有附加数据,文件就是标准的zip。于是进入010Editor。

5.2 十六进制定位记录

打开后,搜索50 4B 03 04,找到了一个本地文件头。开头几个字节是:

50 4B 03 04 14 00 09 00 00 00 08 00

标志位是09 00,bit0是1,很可疑。再搜索50 4B 01 02,找到中央目录,开头是:

50 4B 01 02 1E 03 14 00 09 00 00 00

中央目录的标志位同样是09 00。也就是说,这个压缩包被做了双重伪加密标记:本地文件头和中央目录都写着“加密”。

按照第3节的操作,我把本地文件头偏移+6处的09改成08,把中央目录偏移+8处的09改成08,保存。再执行:

unzip misc1_fixed.zip

这次没有任何密码提示,直接解出了flag.txt。打开一看:

MISC{zip_fake_encryption_is_just_a_flag}

整个过程两分钟,没有跑爆破,没有猜密码。

5.3 这类题的变体情况

伪加密题在改标志位时,还存在几种变体:

  • 只改了本地文件头,中央目录没改。这类题用某些第三方解压软件可能能开,用命令行就卡住。
  • 只改了中央目录,本地文件头没改。这时候Windows资源管理器会要密码,但部分命令行工具可能直接解出来。
  • 压缩包里有多个文件,只对其中一个文件做伪加密,其他正常。如果解压时提示密码,要检查每条记录的标志位。
  • 某个条目的本地文件头是01 00,中央目录是09 00,两个地方不一致,说明制作者改得比较粗暴。

不管怎么变,检查“所有”文件头的标志位,永远是通用解法。

6. 常见问题与排查实录

6.1 为什么我改了标志位还是提示密码

这个问题我遇到太多次了,原因基本逃不出下面几类。

第一,只改了本地文件头,没改中央目录。前面说过,Windows资源管理器优先读中央目录,中央目录还标记加密,就会继续要求密码。第二,压缩包里有多个文件,你只改了第一个文件头。第二条记录的文件头可能还是加密标志位,解压到那个文件时照样卡住。第三,改错偏移。本地文件头的标志位在偏移+6,中央目录在偏移+8,有人把一个文件里的所有09都改成00,反而把压缩方式、CRC字段都碰了。第四,这个包其实不是伪加密,而是真加密。真加密的数据段已经加入了基于密码的加密流,就算你把标志位清零,解压时也会发现数据不对,或者直接报CRC错误。

排查方法很简单:搜索50 4B 03 04和50 4B 01 02,逐个数偏移;再结合原始备份对比。如果清掉标志位后,能解压但解出来的内容CRC校验失败,就说明不是伪加密,赶紧恢复备份,走爆破或者明文攻击路线。

6.2 修改后提示CRC错误或文件损坏

有几种可能。如果是真加密,清除标志位后,解压程序会尝试按普通数据解压,但压缩后的字节流实际是解密后的数据,两个对不上,CRC自然错。这时候必须还原文件,用其他方式。

还有一种可能是你把bit3清掉了。原始标志位是09,代表同时启用了bit0和bit3。如果你把整个09改成00,数据描述符的信息就丢了。解压时如果本地文件头里的CRC和大小本来就是零,解压器找不到正确的数据位置,就会提示损坏。这正是我前面强调“只清bit0、保留其他位”的原因。遇到这种情况,把00改回08再试,大概率能恢复。

如果文件确实损坏,还可以用zip -F来自动修复,但那是另一套流程了。比赛环境里,我建议每次改之前都保留原始副本,才能回退。

6.3 伪加密和真加密到底怎么彻底区分

最直接的方法是看数据段结构。真加密的zip,每个压缩条目在数据段开头会有一段长度基于密码的加密头,字段排列和普通zip不同。伪加密则完全没有这些,数据段就是普通压缩流。

更省力的判断方式是:先用010Editor清除标志位,如果能正常解压且CRC通过,就是伪加密;如果解压出来是乱码、CRC错误或文件大小对不上,就是真加密。这个“测试性修改”不会破坏原始文件,只要改了之后不行马上恢复即可。

还有一点,CTF题目里很少会只给你一个真加密的zip然后让你爆破,因为大字典爆破非常耗时间。如果看到zip要密码,又没有任何密码线索,先按伪加密处理,成本最低。确认伪加密被排除后,再考虑:

  • 弱密码爆破
  • 已知明文攻击
  • CRC32碰撞
  • 压缩包注释里藏线索
  • 文件尾部附加数据

6.4 结尾附加内容容易被忽略

改完标志位解压出文件之后,不要太快结束。有些题目会把真正的flag藏在压缩包尾部,或者把第二个zip塞进第一个zip的注释字段。010Editor看文件末尾,EOCD签名是50 4B 05 06,结尾处还有“注释长度”字段,可以留意有没有多余字节。另外,压缩包注释用zipnote也可以查看:

zipnote misc1_fixed.zip

如果注释里有话,往往就是提示或者隐藏密码。同理,解压出的文件如果不是flag格式,也要再检查一遍文件头和尾部,防止套娃题。

7. 结尾一点个人体会

我现在處理伪加密题,固定流程已经变成:先file看一眼,再unzip试一下,提示要密码就开010Editor,搜本地文件头,看偏移+6;搜中央目录,看偏移+8;清掉bit0,保存解压。全过程不到一分钟。

如果一定要选一个最值得养成的习惯,我觉得是“不要看到一个加密标志就急着上爆破工具”。二进制世界里很多东西只是“看起来如此”,zip伪加密尤其典型。手动改过几个字节之后,你对文件格式的敏感度会明显提高,以后遇到更深层的隐藏数据、隐写分析,也会更有底气。

希望这篇实战拆解能帮你把zip伪加密从“听说过”变成“闭着眼也能解”。下次再看到压缩包要密码,先打开010Editor看一眼,大概率就是那一个字节的事。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 15:40:38

泛微OA Mobile cdnfile任意文件读取漏洞深度剖析与安全加固指南

泛微OA Mobile cdnfile任意文件读取漏洞深度剖析与安全加固指南 最近安全圈有个消息传得挺快&#xff0c;说是泛微OA的Mobile端某个接口存在未公开的任意文件读取漏洞&#xff0c;还配了POC下载链接。这种"带POC的0day"在圈子里历来都是双刃剑——有人拿去刷SRC赚积…

作者头像 李华
网站建设 2026/10/20 15:40:35

C#上位机开发从入门到精通:通信、并发与存储实战

想用C#做上位机开发&#xff0c;绕不开的几座山&#xff1a;串口/TCP通信、多线程、界面刷新、数据落库。我用这个栈做了好几个现场项目&#xff0c;踩过的坑能装满一车。这篇内容就是把C#上位机开发从入门到精通的完整路径&#xff0c;按我自己的理解重新梳理一遍——哪些必须…

作者头像 李华
网站建设 2026/10/20 15:38:49

代理模式核心解析:从静态代理到JDK动态代理与CGLIB实战

你有没有遇到过这种场景&#xff1a;某个业务接口已经稳定运行了好几个月&#xff0c;突然要加操作日志、加参数校验、加缓存、加权限判断&#xff0c;而且这些逻辑几乎和核心业务毫无关系。我一开始的做法很朴素&#xff0c;直接打开实现类&#xff0c;在方法里插入一段代码。…

作者头像 李华
网站建设 2026/10/20 15:38:10

Java老系统注释重构:业务语义注释与状态机还原实践

简介&#xff1a;本资源是一份面向Java初学者与Web开发入门者的轻量级移动应用大厅学习案例&#xff0c;聚焦ServletJSP技术栈的MVC实践。项目以完整可运行的HTML静态页面为核心&#xff0c;辅以详尽中文注释&#xff0c;清晰呈现用户登录、服务浏览等典型移动端大厅交互逻辑的…

作者头像 李华
网站建设 2026/10/20 15:37:22

个人Agent崛起:企业与消费者的博弈规则正在被改写

近一年多&#xff0c;"个人Agent"从一个概念名词慢慢变成了真实可用的工具形态。国外一位科技企业家最近撰文聊到一个有意思的切入点&#xff1a;当每个消费者都拥有了自己的智能代理&#xff0c;企业和消费者之间的博弈方式会完全改写。这篇文章在行业里讨论度不低&…

作者头像 李华
网站建设 2026/10/20 15:37:09

AI智能体沙箱失控排查与治理:从限额熔断到网络边界

上周凌晨两点&#xff0c;我盯着监控面板上一排排“活着”的沙箱&#xff0c;CPU 曲线齐刷刷顶满 100%&#xff0c;队列里的任务全部卡在原地。这种场景做 AI 智能体工程的人应该都不陌生&#xff1a;你把一个看似安全的隔离环境交给模型生成的代码&#xff0c;它却成了失控的温…

作者头像 李华