深入理解zip伪加密
前言: 之前一直认为,zip的伪加密也就是判断奇偶,改一改加密标志位那么简单,甚至可以直接上手拿工具去梭,感谢经过C3ngH师傅指正后,才意识到其中原理的重要性。对其深入研究后,记录下这篇文章。
zip伪加密原理
了解伪加密之前,我们需要深入理解zip的文件结构。
一个zip通常由三部分组成,即:压缩源文件数据区、压缩源文件目录区、压缩源文件目录结束标志
如图:

压缩源文件数据区:
| HEX | 含义 |
|---|---|
| 50 4B 03 04 | 这是zip的头文件标记(0x04034b50),对应文本PK |
| 14 00 | 解压文件所需的 pkware 版本 |
| 00 00 | 全局方式位标记(有无加密) |
| 08 00 | 压缩方式(0x0008,对应Deflated) |
| AA 84 | 最后修改文件时间(遵循MS-DOS时间格式) |
| 5F 5B | 最后修改文件日期(遵循MS-DOS时间格式) |
| 6A B1 EC C9 | CRC-32校验和(0xC9ECB16A) |
| 19 00 00 00 | 压缩后尺寸 |
| 18 00 00 00 | 未压缩尺寸 |
| 08 00 | 文件名长度 |
| 00 00 | 扩展记录长度 |
| 66 6C 61 67 2E 74 78 74 | 文件名(对应flag.txt) |
压缩源文件目录区
| HEX | 含义 |
|---|---|
| 50 4B 01 02 | 目录中文件文件头标记 |
| 1F 00 | 压缩使用的 pkware 版本 |
| 14 00 | 解压文件所需 pkware 版本 |
| 00 00 | 全局方式位标记(有无加密) |
| 08 00 | 压缩方式 |
| AA 84 | 最后修改文件时间 |
| 5F 5B | 最后修改文件日期 |
| 6A B1 EC C9 | CRC-32校验和 |
| 16 00 00 00 | 压缩后尺寸 |
| 18 00 00 00 | 未压缩尺寸 |
| 08 00 | 文件名长度 |
| 24 00 | 扩展字段长度 |
| 00 00 | 文件注释长度(0字节,表示没有注释) |
| 00 00 | 磁盘开始号(0,表示文件不跨磁盘) |
| 00 00 | 内部文件属性 |
| 20 00 00 00 | 外部文件属性 |
| 00 00 00 00 | 局部头部偏移量 |
| 66 6C 61 67 2E 74 78 74 | 文件名(对应flag.txt) |
| 0A 00 20 00 … DC 01 | 扩展字段(长度为36字节) |
压缩源文件目录结束标志
| HEX | 含义 |
|---|---|
| 50 4B 05 06 | 目录结束标记 |
| 00 00 | 当前磁盘编号 |
| 00 00 | 目录区开始磁盘编号 |
| 01 00 | 本磁盘上纪录总数 |
| 01 00 | 目录区中纪录总数 |
| 5A 00 00 00 | 目录区尺寸大小(十进制90字节) |
| 3C 00 00 00 | 目录区对第一张磁盘的偏移量 |
| 00 00 | ZIP文件注释长度 |
| 无 | ZIP文件注释内容 |
伪加密原理
在一个正常、健康的ZIP文件中,对于同一个文件条目,其压缩源文件数据区和压缩源文件目录区中的“全局方式位标记”(即加密标志)必须完全一致。
如:

而解压软件处理ZIP文件通常分两步:
步骤一:列出文件列表
软件首先读取ZIP文件末尾的中央目录(目录区),这里包含了所有文件的索引信息(文件名、加密标志等),软件根据这里的信息向用户展示文件列表,并给加密文件打上“*”的图标。
步骤二:解压具体文件
当用户选择解压一个文件时,软件根据中央目录记录的指针,找到文件对应的本地文件头(数据区),软件依据数据区中的标志位来执行实际的解压操作。
伪加密,则是在一个正常未加密的zip文件上进行修改:将压缩源文件目录区的全局方式位标记改为加密的状态,这样,压缩软件首先读取目录区,就会认为“这是一个加密文件”,从而向用户索要密码。(但实际上,文件根本没有加密,这也是“伪加密”叫法的由来。)
例如:

这里将00 00改为09 00,压缩软件就会显示加密:

经过实测,7-Zip检测的是数据区的全局方式位标记,其他解压软件例如BandZip和WinRAR检测目录区的全局方式位标记,这三种软件都只检测一位,并不会检测另一个位置,同时也不会进行报错。
你可能会好奇,为什么这里非得改成09而不是其它数字呢?
这与压缩软件判断通过全局方式位标记判定加密的逻辑有关:
全局方式位标记是一个16位的二进制数(在ZIP文件中以2个字节表示),在这16个位中,最低位(Least Significant Bit,也称之为第0位)是加密的总开关。
在ZIP文件中,这2个字节是小端序存储的。例如,你看到00 00,实际值应为0x0000。
对应的二进制数为:0000 0000 0000 0000,最低位为0,因此判定为未加密,压缩软件会直接解压。
而09 00,对应二进制数:0000 0000 0000 1001,最低位为1,因此会判定为加密。
不同的加密算法也具有不同的详细特征:
| 加密算法 | 全局方式位标记(二进制) | 典型十六进制值 | 原理与特点 |
|---|---|---|---|
| 未加密 | xxxx xxxx xxxx xxx0 | 00 00,08 00 | 第0位=0。总开关关闭,文件未加密。 |
| PKWARE 传统加密 | xxxx xxxx xxxx xxx1 | 01 00,09 00 | 第0位=1,且第6位和第11位均为0。 |
| AES 加密 | xxxx xxx1 xxxx 1xx1 | 01 09,01 41,01 63 | 第0位=1,且第6位=1,第11位=1。 |
但是总的来说,不管哪种加密,第0位都是决定加密的总开关。当第0位为0时,对应的十六进制值为偶数值;当第0位为1时,对应的十六进制值为奇数值。因此,我们才有了通过判定奇偶值来判断加密的说法。
解题思路
在CTF比赛题目中,涉及到伪加密类型,我们需要同时分析zip的压缩源文件数据区和压缩源文件目录区,判定其是否为伪加密,再通过修改目录区的全局方式位标记来破解伪加密。
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时







