深入理解zip伪加密

深入理解zip伪加密
M.Y深入理解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字节,这是由上面的扩展字段长度24 00决定的。这是ZIP64、NTFS时间戳等扩展信息的存放位置) |
压缩源文件目录结束标志
| HEX | 含义 |
|---|---|
| 50 4B 05 06 | 目录结束标记 |
| 00 00 | 当前磁盘编号(因为该ZIP文件没有分卷,不跨越多张磁盘,所以从0开始) |
| 00 00 | 目录区开始磁盘编号 (同上,表示中央目录也位于第一个磁盘上) |
| 01 00 | 本磁盘上纪录总数 (表示当前磁盘上有1条中央目录记录) |
| 01 00 | 目录区中纪录总数 (这是整个ZIP文件中最重要的计数之一,它表明这个ZIP文件中总共包含1个文件) |
| 5A 00 00 00 | 目录区尺寸大小 (十进制90字节。这指的是从50 4B 01 02开始到中央目录记录结束的所有字节长度) |
| 3C 00 00 00 | 目录区对第一张磁盘的偏移量 (中央目录相对于存档起始位置的偏移量。小端序,0x0000003C = 十进制 60 字节。这意味着,解压软件需要从ZIP文件开头跳过60个字节,就能找到中央目录(即 PK\x01\x02 签名) |
| 00 00 | ZIP 文件注释长度(0表示ZIP文件没有全局注释) |
| 无 | ZIP文件注释内容(因为注释长度为0,所以这里没有数据) |
伪加密原理
在一个正常、健康的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。这是ZIP格式最初定义的弱加密算法。 |
| AES 加密 | xxxx xxx1 xxxx 1xx1 | 01 09, 01 41, 01 63 |
第0位=1(加密),且第6位=1,第11位=1。这是WinZip开发并标准化的强加密。 |
但是总的来说,不管哪种加密,第0位都是决定加密的总开关,当第0位为0时,对应的十六进制值为偶数值,当第0为为1时,对应的十六进制值为奇数值,因此,我们才有了通过判定奇偶值来判断加密的说法。
解题思路
在CTF 比赛题目中,涉及到伪加密类型,我们需要同时分析zip的压缩源文件数据区和压缩源文件目录区,判定其是否为伪加密,再通过修改目录区的全局方式位标记来破解伪加密。













