使用 Biham 和 Kocher 的已知明文攻击破解传统 ZIP 加密。
ZIP 归档可能包含许多条目,其内容可以被压缩和/或加密。 具体来说,条目可以使用基于密码的对称加密算法进行加密,该算法通常称为传统 PKWARE 加密、传统加密或 ZipCrypto。 该算法生成一个伪随机字节流(密钥流),通过与条目内容(明文)进行异或运算来产生加密数据(密文)。 生成器的状态由三个 32 位整数组成,使用密码初始化,并在加密过程中随着明文不断更新。 这种加密算法容易受到已知明文攻击,如 Eli Biham 和 Paul C. Kocher 的研究论文《对 PKZIP 流密码的已知明文攻击》(A known plaintext attack on the PKZIP stream cipher)所示。 给定密文和至少 12 个字节的对应明文,可以恢复密钥流生成器的内部状态。 利用这一内部状态,不仅可以完全解密密文,还可以解密使用相同密码加密的其他条目。 它还可以用于暴力破解密码,复杂度为 nl-6,其中 n 是字符集大小,l 是密码长度。
bkcrack 是一个命令行工具,实现了这种已知明文攻击。 主要功能包括:
您可以在 GitHub 上获取最新的官方发布版本。
Ubuntu、MacOS 和 Windows 的预编译包可供下载。 将下载的归档文件解压到您喜欢的任何位置。
在 Windows 上,运行 bkcrack 需要 Microsoft 运行时库。 如果您的系统上尚未安装这些库,请下载并安装最新的 Microsoft Visual C++ Redistributable 包。
或者,您可以使用 CMake 编译该项目。
首先,下载源代码文件或克隆 Git 仓库。
然后,在源代码树中运行以下命令将在 install 文件夹中创建安装。
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=install
cmake --build build --config Release
cmake --build build --config Release --target install
bkcrack 可在以下列出的软件包仓库中获得。 这些包由外部维护者提供。
您可以像这样查看名为 archive.zip 的归档中的条目名称和元数据:
bkcrack -L archive.zip
使用 ZipCrypto 加密的条目容易受到已知明文攻击。
攻击至少需要 12 个字节的已知明文。 其中至少 8 个字节必须连续。 连续的已知明文越大,攻击速度越快。
假设有一个 zip 归档 encrypted.zip,其中条目 cipher 是密文;以及 plain.zip,其中条目 plain 是已知明文,可以像这样运行 bkcrack:
bkcrack -C encrypted.zip -c cipher -P plain.zip -p plain
假设有一个文件 cipherfile 包含密文(从加密头部的 12 个字节开始),以及 plainfile 包含已知明文,可以像这样运行 bkcrack:
bkcrack -c cipherfile -p plainfile
如果已知明文对应的是密文的非起始部分,可以指定一个偏移量。 如果已知明文包含部分加密头部,偏移量可以为负。
bkcrack -c cipherfile -p plainfile -o offset
如果已知的连续明文很少(8 到 11 个字节),但在其他已知偏移位置知道一些字节,可以通过提供这些信息来达到总共 12 个已知字节的要求。
为此,使用 -x 标志,后面跟偏移量和十六进制字节。
bkcrack -c cipherfile -p plainfile -x 25 4b4f -x 30 21
如果攻击成功,可以保存与攻击所用密文对应的解密数据:
bkcrack -c cipherfile -p plainfile -d decipheredfile
如果从之前的攻击中已知密钥,可以使用 bkcrack 解密数据:
bkcrack -c cipherfile -k 12345678 23456789 34567890 -d decipheredfile
解密后的数据可能是压缩的,具体取决于创建 zip 文件时是否使用了压缩。
如果使用了 deflate 压缩,可以使用 tools 文件夹中提供的 Python 3 脚本来解压缩数据。
python3 tools/inflate.py < decipheredfile > decompressedfile
要一次性访问加密归档中的所有条目,可以生成一个新归档,内容相同但不加密。 这假设所有条目最初都使用相同的密码进行加密。
bkcrack -C encrypted.zip -k 12345678 23456789 34567890 -D decrypted.zip
也可以生成一个使用您选择的新密码加密的新归档:
bkcrack -C encrypted.zip -k 12345678 23456789 34567890 -U unlocked.zip new_password
您也可以通过其对应的内部表示来定义新密码。
bkcrack -C encrypted.zip -k 12345678 23456789 34567890 --change-keys unlocked.zip 581da44e 8e40167f 50c009a0
这两个命令可以一起使用,以在不知道密码但知道内部密钥的情况下更改加密归档的内容: 您可以制作一份使用您选择的密码加密的副本, 然后使用归档管理器编辑该副本,并在提示时输入所选密码, 最后使用原始加密密钥将修改后的归档重新制作一份副本。
给定内部密钥,bkcrack 可以尝试找到原始密码。
您可以使用给定字符集中的字符来查找密码:
bkcrack -k 1ded830c 24454157 7213b8c5 -b ?p
您可以限制搜索到给定长度或一定长度范围的密码:
bkcrack -k 1ded830c 24454157 7213b8c5 -b ?p -l 9
bkcrack -k 1ded830c 24454157 7213b8c5 -b ?p -l 8..10
选项 -r <length> <charset> 是 -l 0..<length> -b <charset> 的快捷方式:
bkcrack -k 1ded830c 24454157 7213b8c5 -r 10 ?p
如果您对密码如何构成有一些了解,可以指定一个掩码来限制搜索空间,从而使恢复速度大大加快。 这对于长密码(例如 12 个或更多字符的密码)尤其重要,因为暴力破解会非常耗时。
例如,假设您大致记得密码由 8 个小写字母、一个连字符和 6 个十进制数字组成,可以使用以下命令:
bkcrack -k 1940e266 d3fd3d89 71ce9871 -m ?l?l?l?l?l?l?l?l-?d?d?d?d?d?d
这会在几毫秒内运行完成,而暴力破解替代方案则需要数小时。
暴力破解和基于掩码的密码恢复的搜索空间均通过字符集定义。 字符集是一系列字符或现有字符集的快捷方式。 预定义字符集如下所示。
除了预定义字符集,您还可以使用 -s 选项定义自定义字符集。
自定义字符集可以引用预定义字符集或其他自定义字符集。
自定义字符集对于精确指定基于掩码的恢复搜索空间特别有用。
例如,如果您知道密码由 10 个字母(大写或小写)和 5 个二进制数字组成,可以使用以下命令:
bkcrack -k b8c377a6 f603160f 1832a78b -m ?x?x?x?x?x?x?x?x?x?x?y?y?y?y?y -s x ?u?l -s y 01
example 文件夹中提供了一个教程。
更多信息,请查看文档并阅读源代码。
欢迎在 GitHub 上提出改进建议或提交拉取请求。
如果您想表示对项目的支持,欢迎通过 Github Sponsors 进行捐赠或赞助项目。
本项目根据 zlib/png 许可证 的条款提供。
| 快捷方式 | 描述 | 值 |
|---|
?l | 小写字母 | abcdefghijklmnopqrstuvwxyz |
?u | 大写字母 | ABCDEFGHIJKLMNOPQRSTUVWXYZ |
?d | 十进制数字 | 0123456789 |
?s | 特殊字符 | !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ |
?a | 字母数字字符 | 同 ?l?u?d |
?p | 可打印 ASCII 字符 | 同 ?l?u?d?s |
?b | 所有字节 | 0x00 .. 0xff |