ZIP 破解

伪加密

原理

在 ZIP 文件中,数据区与目录区中的 Flags 应该是相同的值。当数据区的标志位为加密标志,而目录区的标志位为非加密标志时,这个时候许多 ZIP 软件会将其识别为被加密,但实际上并不存在对应的密码。

破解

只需要将数据区和目录区的标志位置为0即可。

弱密码爆破

原理

说白了就是用工具将各种符号和数字排列测试密码,通常用于6位数以下的密码。

破解

一般来说推荐使用 ARCHPR 对 ZIP 压缩包进行暴力破解处理。一般是范围内枚举(例如纯数字或数字与字母的排列组合)或是使用专有的字典进行弱密码爆破。
同时也可以使用 hashcat 和 bkcrack 对 ZIP 的密码进行破解。

CRC 碰撞

原理

当压缩文件内容较少或仅有部分明文未知时,可以采用 CRC 碰撞的方式去暴力破解明文(因为压缩包中保存的 CRC 校验值为压缩前内容的校验)。

破解

可以使用 Python 脚本进行爆破,但下面的脚本仅是示例,如果有特别的需求(例如未知明文在已知明文中间段时)需要自行修改脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import binascii
import itertools

def CRCcrack(unknownBytes: int, targetCRC: int, known: bytes = b'') -> list[bytes]:
"""
CRC 碰撞
Parameters:
unknownBytes - 未知的字节数
known - 已知明文(默认为拼接)
Returns:
完整明文
"""
rst = []
for m in itertools.product(range(128), repeat=unknownBytes):
msg = known + bytes(m)
crc = binascii.crc32(msg)
if crc == targetCRC:
rst.append(msg)
return rst

print(CRCcrack(3, binascii.crc32(b'123')))

1
使用方法:python crc32.py reverse 0x4FA83D8C

明文攻击

原理

ZIP 加密模式本质上是将密码转化为内置的一个密钥进行加密的,而密钥是有限长度的,所以如果我们知道一个压缩包内其中一个文件的完整明文,那么我们就可以通过算法将密钥百分百地计算出来(理论上可以把密码也百分百计算出来),且理论上破解速度只与被压缩文件大小有关。

破解

推荐使用 ARCHPR 的明文攻击模式进行破解,需要一个明文压缩包和含有明文文件的密文压缩包,其中他们的压缩算法应该是相同的。
同时也可以使用 bkcrack 进行破解。

注意

文本文件如果编码不同(例如 UTF-8 与 GBK)可能导致压缩出来的大小不同,所以各种编码都需要尝试一次。
不同的压缩软件压缩出来的文件可能会导致 ARCHPR 报错,一般推荐 Bandizip 与 WinRAR 都尝试一次。

深入明文攻击

原理

ZIP 加密模式本质上是将密码转化为内置的一个密钥进行加密的,而密钥是有限长度的,而且 ZIP 的加密方式使得我们可以只解密部分密文,如果我们知道某个文件的部分密文,那么我们可以遍历所有可能的密钥去进行比对(类似 CRC 碰撞的原理)。
但仅有 ZipCrypto Deflate 算法和 ZipCrypto Store 算法可以用此方式破解。

破解

使用 bkcrack 需要已知明文的十二个字节和偏移,其中八个字节必须连续。
需要使用到的参数:

-C file.zip 加密压缩包
-c file 提取的密文文件(密文部分)
-p key.txt 指定明文部分
-x offset hex 指定偏移量和部分明文十六进制值
-o offset 指定明文部分的偏移量
-k key1 key2 key3 指定三段解密密钥
-d file 解压缩得到的目标文件

例如针对 JPG 的压缩包,我们可以使用以下命令:

首先生成明文文件:

1
echo -n "FFD8FFE000104A4649460001" | xxd -r -ps > key.txt

随后进行密钥爆破:

1
bkcrack -C 1.zip -c t.jpg -p key.txt -o 0

或者是针对 ZIP 的压缩包,我们可以使用以下命令:
首先我们这个 ZIP 中存在 flag.txt 的明文:

1
echo -n "flag.txt" > key.txt

其次我们知道 ZIP 文件的头,故进行密钥爆破:

1
bkcrack -C 1.zip -c flag.zip -p key.txt -o 30 -x 0 504B03041400

需要注意的是,当已知字节数越多时,得到的密钥越准确。
得到三段密钥后我们进行提取:

1
bkcrack -C 1.zip -c flag.zip -k 683a571e f954e70c 49da18ac -d 111.zip

需要注意的是,如果文件是使用 Deflate 算法进行压缩的话,需要使用其自带的 inflate.py 脚本(在 ./tools/ 文件夹中)进行解压缩:

1
python inflate.py < 1.jpg > 2.jpg  

长密码哈希

ZIP 内部使用 PBKDF2 算法,在 AES-256 加密模式下(包括 ZIPX),如果输入密码长度超过 64 字节,它会使用 PBKDF2 重新生成密钥,新生成的哈希值作为文件的实际密码。
换句话说,就是实际密码=SHA1(输入密码)。

特殊实例

以时间戳作为密码

原理

时间戳一般是一个两位小数,ZIP 文件所保存的创建时间和更新时间并不一定与当时所获取的时间戳是一致的,也许会差几秒,所以我们需要先将文件创建时间转化为时间戳,然后进行掩码爆破。

破解

例如文件创建时间为 2019/05/17 8:25:28,我们使用如下脚本进行转化时间戳

1
2
3
4
5
import time

a = time.struct_time((2019,5,17,8,25,28,-1,-1,-1))
print(time.mktime(a))
得到结果 1558052728.0,设置掩码 15580?????.?? 或者 15580?????.? 爆破即可。