- 网络安全
- 密码学
- 渗透测试
【免费下载链接】bkcrack
Crack legacy zip encryption with Biham and Kocher's known plaintext attack.
本文基于 doc/resources.md 整理,系统梳理 bkcrack 背后的研究脉络:Biham 与 Kocher 的经典已知明文攻击及其后续改进论文、PKZIP 密码学的参考书籍、ZIP 文件格式规范,以及围绕"破解内部密钥"与"恢复原始口令"两条路线的开源工具生态。读完本文,你既能理解 bkcrack 算法设计的学术源头,也能知道在什么场景下该选择哪类配套工具,并可将论文结论与仓库源码逐一对应验证。
一、背景:这份资源清单围绕什么展开
bkcrack 是一个命令行工具,实现的是针对传统 PKWARE 加密(又称 ZipCrypto、legacy encryption)的已知明文攻击。其核心结论在 readme.md 中概括为:
- 给定密文与 12 字节以上的对应明文,即可恢复密钥流生成器的内部状态(三个 32 位整数,即内部密钥 X/Y/Z);
- 内部密钥足以解密该密文以及用同一口令加密的其他条目;
- 内部密钥还可以用于以
n^(l-6)的复杂度暴力搜索原始口令(n 为字符集大小,l 为口令长度)。
doc/resources.md 正是围绕这条技术路线,给出了四类关联资源:研究论文、书籍、ZIP 规范、工具。以下各节完整继承该文档的分类结构,并结合仓库源码补充实现层面的印证。
二、研究论文:攻击原理的学术源头
2.1 Biham & Kocher (1995):BK94 攻击
文献:Eli Biham, Paul C. Kocher,《A known plaintext attack on the PKZIP stream cipher》, Fast Software Encryption (FSE 1994), Lecture Notes in Computer Science vol 1008, Springer。这是整个项目的基石,doc/resources.md 明确指出 "bkcrack is based on this paper"。
论文要点(据文档摘录):
- 需要13 字节已知明文:其中8 字节用于生成
2^38个候选内部密钥,剩余5 字节用于过滤候选; - 攻击分为若干阶段:
- 可选地,利用更多连续的已知明文来缩减候选数量;
- 找到口令的内部表示(即内部密钥);
- 从内部表示恢复口令本身。
源码印证 1:8 字节连续 + 12 字节总量。include/Attack.hpp 中定义了两个常量:
/// Number of contiguous known plaintext bytes required by the attack static constexpr std::size_t contiguousSize = 8; /// Total number of known plaintext bytes required by the attack static constexpr std::size_t attackSize = 12;contiguousSize = 8正对应 BK94 论文"8 字节连续明文生成候选"的要求;attackSize = 12则说明 bkcrack 实际采用的是后文 Stay 论文的 12 字节改进版,而非原始的 13 字节。
源码印证 2:攻击主流程。src/main.cpp 的密钥恢复分支清晰呈现论文"生成候选 → 缩减候选 → 攻击验证"三段式结构:先构造Zreduction对象做 Z 值缩减(zr.reduce(progress),对应论文阶段 1),再zr.generate()展开候选(Zi[2,32)),最后调用attack(...)对候选逐个验证(对应论文阶段 2)。src/Zreduction.cpp 的构造函数从密钥流的最后一个字节出发,遍历1 << 22个移位值并利用密钥流查找表KeystreamTab::hasZi_2_16筛出初始候选——这正是"由已知密钥流字节反推 Z 值高位"的表驱动加速手法。
源码印证 3:口令恢复阶段。BK94 的第三阶段"从内部密钥恢复口令"在 src/password.cpp 中体现:先利用Crc32Tab::crc32inv等表逆推口令最后 6 个字节,再对剩余前缀做字符集内暴力搜索——这与 readme 所述n^(l-6)复杂度完全一致。include/password.hpp 的recoverPassword函数签名(字符集、最小/最大长度、断点start、线程数jobs、是否穷举)定义了该阶段的完整参数空间。
2.2 Stay (2002):将已知明文字节数降到 12
文献:Michael Stay,《ZIP Attacks with Reduced Known Plaintext》, Fast Software Encryption (FSE 2001), LNCS vol 2355, Springer。据 doc/resources.md 描述,该论文:
- 回顾了 Biham–Kocher 攻击;
- 提出一个小改进:通过不丢弃 Y7 中的 6 个已知位,将所需明文字节从 13 降到12;
- 建议利用多个文件的 CRC-32 校验字节作为已知明文;
- 随后给出其他方案:例如仅用 4 字节已知明文生成
2^63个候选,或利用伪随机数生成器的弱点。
源码印证:12 字节要求与"免费"的校验字节。bkcrack 的 12 字节口径就是 Stay 的改进值(见上文attackSize = 12)。而"CRC-32 校验字节"建议已被产品化:每个 ZIP 条目数据在加密前会拼接一个 12 字节的加密头,其最后一字节是密码校验字节,可由条目的 CRC-32 或修改时间推导(src/Zip.cpp):
m_entry->checkByte = (header.flags >> 3) & 1 ? lsb(header.lastModTime >> 8) : msb(header.crc32);当密文直接来自 ZIP 档案时,bkcrack 会自动把这个校验字节当作偏移量 -1 处的额外已知明文(src/Arguments.cpp),从而"白捡"一个字节;命令行为此提供--ignore-check-byte选项予以关闭(见 src/main.cpp 的帮助文本)。example/tutorial.md 的"Free additional check byte"一节演示了这一点:猜测 20 字节明文 + 自动加入的校验字节 = 21 字节已知明文。
2.3 Jeong et al. (2012):多文件已知明文的加速
文献:K.C. Jeong, D.H. Lee, D. Han,《An Improved Known Plaintext Attack on PKZIP Encryption Algorithm》, ICISC 2011, LNCS vol 7259, Springer。文档摘录的结论:
- 该文研究利用多个文件的已知明文加速攻击;
- 它假设"最开头的字节"是已知的;
- 但加密头的前10 或 11 个字节是随机的,因此在加密头的伪随机数生成器没有被破解的前提下,这一假设并不实用。
源码印证:加密头大小 12 字节(前 11 字节随机 + 1 字节校验)这一事实与 include/Data.hpp 中Data::encryptionHeaderSize = 12一致,说明 bkcrack 在数据模型层面就承认加密头前部不可预测,这与 Jeong 论文指出的限制互为呼应。
2.4 Coray, Coisel & Sanchez (2019):面向取证场景的口令恢复
文献:S. Coray, I. Coisel, I. Sanchez,《Improved Forensic Recovery of PKZIP Stream Cipher Passwords》, ICISSP 2019, 第 328–335 页。文档摘录的要点:
- 研究如何找到实际口令,分"使用内部密钥"与"不使用内部密钥"两条路线;
- 使用OpenCL 在 GPU 上做计算;
- 该工作已在hashcat中实现(分别对应"无明文口令攻击"与"从内部密钥恢复口令"两个拉取请求,文档中以 hashcat 仓库的 PR #1962 与 PR #2032 标注)。
这条路线与 bkcrack 的-b/--bruteforce(见 include/password.hpp 与 src/password.cpp)互补:bkcrack 在 CPU 上用多线程完成"内部密钥 → 口令"的推导,Coray 等工作则把该搜索空间搬到了 GPU。
三、书籍
doc/resources.md 推荐了:
- M. Stamp, R. M. Low,《Applied Cryptanalysis: Breaking Ciphers in the Real World》, John Wiley & Sons, 2007。
- 书中有一章专门讲流密码,其中一节专门讲PKZIP 加密与 Biham–Kocher 攻击(文档中以
\ref BK94交叉引用标注); - 文档同时给出了作者主页与"PKZIP 攻击专题幻灯片"作为延伸阅读(原文档附外部链接,此处从略)。
- 书中有一章专门讲流密码,其中一节专门讲PKZIP 加密与 Biham–Kocher 攻击(文档中以
对想理解 CRC32 驱动状态更新、为何密钥流只由 Z 的高位决定这类细节的读者,这本书是论文之外较系统的入门读物。
四、ZIP 相关规范
资源清单列出的三份规范文档,分别支撑 bkcrack 的不同功能面:
APPNOTE.TXT — .ZIP File Format Specification(PKWARE 发布,ZIP 格式的开发方)。 bkcrack 的档案读取、条目元数据解析、
-L列表功能都基于该规范实现,入口见 src/Zip.cpp;doc/resources.md 还特别提到,校验字节的用途是"在尝试提取加密条目时,不必继续处理(可能压缩过的)加密数据就能测试给定口令是否正确"。RFC 1951 — DEFLATE Compressed Data Format Specification。 Deflate 是 ZIP 中最常用的压缩算法。bkcrack 攻击成功解密后,若原始条目使用了 deflate,需要用 tools/inflate.py 解压:
python3 tools/inflate.py < decipheredfile > decompressedfile该脚本只有几行核心代码——
zlib.decompress(data, -zlib.MAX_WBITS),负wbits参数表示按 RFC 1951 处理裸 deflate 流(无 zlib/gzip 头)。仓库内还有配套的 tools/deflate.py 用于反向压缩,两者正好覆盖"猜测压缩后明文"所需的压缩/解压缩往返。Microsoft 文档 —
DosDateTimeToFileTime函数说明。 用于描述 ZIP 日期/时间字段所采用的 DOS 日期时间格式。从源码结构看,src/Zip.cpp 解析的本地/中央文件头中的时间字段即采用该格式;它与校验字节的推导直接相关——当条目标志位第 4 位(flags >> 3的第 1 位)置位时,校验字节取自修改时间而非 CRC-32(src/Zip.cpp),因此正确理解这一格式是自动获得"免费校验字节"的前提。
五、工具生态
doc/resources.md 将工具分为三类:破解内部密钥、恢复口令、其他工具。以下逐项继承文档中的描述并补充许可信息。
5.1 破解内部密钥
- PkCrack:Peter Conrad 实现的 Biham–Kocher 攻击,许可为Postcardware。可视为 bkcrack 的直接前身。
- Aloxaf/rbkcrack:Aloxaf 用 Rust 对 bkcrack 的改写,且远早于 bkcrack 就加入了 ZIP64 支持。许可:zlib。
5.2 口令恢复
- hashcat:口令恢复工具,许可MIT;实现了上文 Coray 2019 论文的 GPU 路线(含无明文攻击与从内部密钥恢复两条路径)。
- John the Ripper:经典口令恢复工具;许可接近GPL v2.0(文档特别提示需以该项目的 LICENSE 说明为准,"Almost, see LICENSE")。
- mferland/libzc:Marc Ferland 编写的传统 ZIP 破解工具与库,实现暴力、字典、已知明文三类攻击来恢复口令。许可:GPL v3.0。
这三个工具解决的是"拿到原始口令字符串"的问题。需要注意:就解密数据而言,原始口令并非必需——example/tutorial.md 反复演示了仅凭内部密钥即可-D去密码、-U改密码、-d逐条解密。
5.3 其他工具
Aloxaf/p7zip:Aloxaf 修补的 p7zip,支持用内部密钥直接提取ZIP 文件,语法为:
7za e cipher.zip '-p[12345678_23456789_34567890]'许可:LGPL v2.1 + unRAR 限制。这对"已用 bkcrack 破解出密钥、但只想快速提取内容"的场景非常实用,与 bkcrack 的
-D输出形成两条路径。madler/infgen:把 deflate / zlib / gzip 流反汇编成可读形式的 deflate 反汇编器。许可:zlib。它对"分析压缩后明文长什么样"这类逆向场景有帮助,与 bkcrack 仓库内 tools/inflate.py 的简单解压能力互补。
hannob/zipeinfo:一个 Python 脚本,用于查看某个 ZIP 文件使用了哪种加密方法。许可:CC0 / Public Domain。在做攻击前判断目标是否为 ZipCrypto(只有 ZipCrypto 受本类已知明文攻击影响)时有用;bkcrack 自身的
bkcrack -L archive.zip也能列出各条目的加密方式与压缩方式,见 example/tutorial.md 的-L输出示例。
六、把这些资源串起来:仓库内的可复现实例
上述论文结论与工具链条,在仓库自带示例中可以完整走通一遍:
观察目标:example/secrets.zip 包含两条 ZipCrypto 加密条目(
advice.jpg用 Deflate 压缩,spiral.svg为 Store 未压缩);猜测明文:利用
spiral.svg的扩展名猜测其以<?xml version="1.0"开头,得到 20 字节连续明文,加上自动附加的校验字节共 21 字节——印证了 BK94 的 8 字节连续下限与 Stay 的校验字节建议(example/tutorial.md "Guessing plaintext" 一节);运行攻击:
bkcrack -C secrets.zip -c spiral.svg -p plain.txt输出示例(来自 tutorial)显示
Z reduction using 13 bytes of known plaintext、Attack on 542303 Z values at index 6,最终得到Keys: c4490e28 b414a23d 91404b31。注意这里"13 字节"是含校验字节在内的已知明文字节数,与 BK94 原文的"13 字节"是两回事——bkcrack 本身的要求是 12 字节(其中 8 字节连续,见 include/Attack.hpp);利用密钥:
-D生成无密码副本、-U换口令、-d逐条解密;若条目是 deflate 压缩的,再用python3 tools/inflate.py解压(对应 RFC 1951 与 APPNOTE 两份规范);(可选)恢复口令:用
--bruteforce配合字符集(?l ?u ?d ?s ?a ?p ?b)与长度区间逐步逼近,tutorial 中最终从 12 位字母数字字符集里恢复了口令W4sF0rgotten,耗时仅十秒级——这正是 BK94 第三阶段与n^(l-6)复杂度的实际体现。
文档本身的生成方式也值得一提:doc/CMakeLists.txt 通过 Doxygen 将 doc 目录、include 头文件与 example 目录一起编译为 HTML 文档,doc/resources.md 中的\anchor BK94、\ref Coray2019、\ref hashcat等即用于在这些文档页面之间建立交叉引用。
七、小结
- 想理解攻击原理:从 BK94 论文出发(8 字节连续明文 →
2^38候选 → 过滤),再看 Stay 2002 的 12 字节改进与校验字节技巧;仓库中 include/Attack.hpp、src/Zreduction.cpp、src/Attack.cpp 是这些结论的一比一实现。 - 想理解口令恢复:BK94 第三阶段 + src/password.cpp 的"逆推 6 字节 + 前缀搜索"结构,必要时转向 hashcat / John the Ripper / libzc 等 GPU 或字典路线工具。
- 想理解文件格式:APPNOTE.TXT 定义 ZIP 结构(含 12 字节加密头与校验字节),RFC 1951 定义 deflate(配套 tools/inflate.py / tools/deflate.py),DOS 日期时间格式则关系到校验字节的推导(src/Zip.cpp)。
- 想快速动手:直接按 example/tutorial.md 对 example/secrets.zip 跑一遍完整流程,即可同时体验攻击、去密码、换密码与口令恢复四类操作。
以上资源路径与源码引用均位于当前仓库内,可据此继续深入阅读实现细节。
- 网络安全
- 密码学
- 渗透测试
【免费下载链接】bkcrack
Crack legacy zip encryption with Biham and Kocher's known plaintext attack.
相关推荐
bkcrack终极指南:深度解析ZipCrypto已知明文攻击技术
bkcrack终极指南:深度解析ZipCrypto已知明文攻击技术 在数字资产管理中,遗忘ZIP文件密码是常见的技术痛点。传统暴力破解方法在面对复杂密码时效率低
网络安全密码学渗透测试bkcrack:利用已知明文分析技术恢复传统ZIP加密的强大工具
在数据恢复和数字取证领域,经常会遇到因密码遗忘而被锁定的ZIP压缩文件。bkcrack正是为解决这一问题而生的专业工具,它基于Eli Biham和Paul C.
网络安全密码学渗透测试忘记ZIP密码怎么办?bkcrack已知明文恢复指南
当你面对一个重要的ZIP压缩文件却忘记了密码时,那种无助感确实令人沮丧。传统ZIP加密虽然保护了你的数据,但也可能成为数据恢复的障碍。幸运的是,bkcrack这
网络安全密码学渗透测试
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考