密码恢复这件事,外行看热闹,内行看门道。网上流传的教程大多只告诉你敲哪几行命令,却很少讲清楚为什么这么敲、什么情况下根本敲不通、以及跑起来之后机器为什么突然变慢甚至报错。我前后在几台不同配置的机器上折腾过压缩包密码恢复,踩过的坑比跑出来的密码还多。这篇内容就围绕Hashcat和John the Ripper这两款主流工具,讲清楚压缩包密码恢复的完整链路——从哈希提取、模式选择、显卡计算环境配置,到实测中的性能调优和常见报错处理。适合有一定命令行基础、想真正把这件事跑通而不是复制粘贴碰运气的读者。下面所有操作都建议在你自己的、有合法授权的文件上进行,这一点必须先说在前面。
1. 先搞清楚你在恢复什么:压缩包密码的验证机制
很多人一上来就找命令,结果连自己要处理的是哪种加密格式都没确认,跑半天没结果还以为是工具不行。压缩包密码恢复的第一步不是选工具,而是搞清楚目标文件的加密方式,因为这直接决定了后面哈希怎么提取、用哪种攻击模式。
1.1 ZIP的两种加密体系差别巨大
ZIP格式存在两套完全不同的加密方案,这是新手最容易混淆的地方。一套是流传很久的ZipCrypto(也叫传统加密),另一套是AES-256加密(WinZip AES)。两者在密码验证的数学结构上完全不同,恢复难度和工具支持也不一样。
ZipCrypto的验证机制相对薄弱:它用一个12字节的加密头来校验密码,密码错误时校验位对不上就直接判定失败。这个结构的特点是验证速度快,但存在已知的明文攻击弱点(这里不展开,因为那属于另一类技术路线)。对密码恢复来说,ZipCrypto的每次尝试计算量小,所以同样的硬件下每秒尝试次数(也就是常说的hash rate)会高很多。
AES-256则完全不同。它使用PBKDF2-HMAC-SHA1做密钥派生,默认迭代1000次(WinZip的实现),每次密码尝试都要完整跑一遍密钥派生流程。这意味着单次尝试的计算成本比ZipCrypto高出两到三个数量级。你在ZipCrypto上能跑到每秒几百万次尝试的机器,换到AES-256上可能只剩每秒几千次。这个差距必须提前有心理预期,否则很容易误判"工具是不是没跑起来"。
判断方法很简单,用zipinfo或者直接看文件头:
zipinfo -v target.zip | grep -i "encryption"输出里如果出现AES字样就是AES加密,出现traditional或ZipCrypto就是传统加密。另一个土办法是用7z尝试解压,报错信息里通常会点明加密类型。
1.2 RAR的版本差异同样关键
RAR的情况稍微统一一些,但版本差异依然影响巨大。RAR3(对应WinRAR 4.x及更早)和RAR5(WinRAR 5.x之后)的密钥派生算法不同。RAR3使用SHA-1为基础的派生流程,迭代次数相对可控;RAR5则用了更复杂的PBKDF2变体,迭代次数更高,单次尝试成本更大。
用unrar或者7z l -slt可以看出版本信息。这里有个实操细节:Hashcat对RAR3的支持成熟度高于RAR5,模式编号也不同(RAR3是-m 12500,RAR5是-m 13000)。选错模式会直接报"token encoding"或"signature"相关的错误,而不是给你一个友好的提示。
1.3 为什么必须先提取哈希而不是直接喂压缩包
这是很多人不理解的一步。Hashcat本身不直接读ZIP/RAR文件,它需要的是从文件里抽出来的、能独立验证密码的那段哈希数据。提取出来的哈希通常是一个特定格式的字符串,包含了加密头、校验值、盐值等必要信息。这样做的好处是:哈希文件极小,可以脱离原文件反复使用;而且提取过程本身会校验文件完整性,避免在损坏的文件上白跑。
John the Ripper则相对灵活,部分版本可以直接对压缩包操作(内部调用提取逻辑),但为了统一流程和可控性,我习惯先用专用脚本提取,再分别喂给两个工具。提取工具后面会具体讲。
2. 哈希提取:把压缩包变成工具能吃的格式
提取这一步看似简单,实际上是最容易出问题的地方。提取脚本版本不对、文件路径有空格、压缩包本身有多个加密成员,都会导致提取失败或提取出不完整的哈希。
2.1 ZIP哈希提取的两种脚本选择
针对ZIP,社区里常用的提取脚本有两个来源:一个是zip2john(John自带),另一个是Hashcat官方仓库里的zip2hashcat.py。两者输出的格式不同,分别对应各自工具的输入要求。
zip2john的用法:
zip2john target.zip > zip_hash.txt输出的是一个以$pkzip2$开头的长字符串,John能直接识别。这个脚本对ZipCrypto和AES都支持,但要注意它默认会尝试提取压缩包内所有加密成员,如果压缩包里有多个文件,输出会包含多段哈希。这时候喂给工具要确认工具是否支持多哈希并行,否则可能只处理了第一段。
Hashcat这边用zip2hashcat.py:
python3 zip2hashcat.py target.zip > zip_hash_hc.txt输出格式以$zip2$(ZipCrypto)或$zip2$带AES标识开头。这里有个坑:不同版本的脚本对AES的支持程度不一样,老版本可能直接报"unsupported encryption"。遇到这种情况先更新脚本到最新,再确认Python依赖(主要是pycryptodome)装好了。
2.2 RAR哈希提取的版本匹配问题
RAR的提取脚本是rar2john(John自带)或Hashcat仓库的rar2hashcat.py。同样存在版本匹配问题。
rar2john target.rar > rar_hash.txtRAR3提取出来是$RAR3$*0*...格式,RAR5是$rar5$*...格式。Hashcat对这两种格式的模式编号不同,喂进去之前务必确认哈希前缀和-m参数对得上。我见过有人把RAR5的哈希用-m 12500跑,工具不报错但永远跑不出结果,因为模式根本不匹配,验证逻辑走的是另一套。
提示:提取完成后,先用文本编辑器打开哈希文件看一眼前缀。
$pkzip2$、$zip2$、$RAR3$、$rar5$这几个前缀分别对应不同的处理路径,认错前缀是"跑不出结果"的头号原因。
2.3 提取失败的常见原因排查
提取阶段报错,按这个顺序查:
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| 脚本报"not a zip file" | 文件扩展名与实际格式不符 | 用file命令确认真实格式 |
| 输出为空 | 压缩包未加密或只有部分成员加密 | 用zipinfo确认加密标志 |
| 报"unsupported" | 加密算法版本过新或脚本过旧 | 更新脚本与依赖库 |
| 哈希长度异常短 | 提取被截断,常见于路径含特殊字符 | 把文件移到纯英文短路径重试 |
路径问题值得单独说一句。Windows下如果文件路径带中文或空格,某些Python脚本读取时会出问题,表现是提取到一半中断或输出乱码。最稳妥的做法是把目标文件复制到一个类似/tmp/work/或C:\work\的纯英文短路径下再操作。
3. 显卡计算环境:CUDA配置为什么总在这卡住
密码恢复的性能几乎完全取决于显卡。CPU跑和GPU跑,速度差距可能是几十倍到上百倍。而GPU要发挥作用,计算环境必须配对——这就是标题里说的"CUDA配置避坑"的核心。
3.1 驱动、运行时、工具链三者的版本关系
很多人以为装个显卡驱动就完事了,实际上Hashcat依赖的是CUDA运行时(runtime),而运行时又对驱动版本有最低要求。三者关系是:驱动版本 ≥ 运行时要求的最低驱动 ≥ 工具编译时依赖的运行时版本。任何一环不满足,表现都是Hashcat启动时报No devices found或者clGetPlatformIDs相关错误。
正确的检查顺序:
- 先看驱动版本:
nvidia-smi,右上角显示Driver Version。 - 再看CUDA运行时版本:
nvcc --version或nvidia-smi里显示的CUDA Version(注意这个显示的是驱动支持的最高运行时版本,不一定是你装的)。 - 最后确认Hashcat识别到的设备:
hashcat -I。
hashcat -I的输出会列出所有可用计算设备及其类型(GPU/CPU)。如果这里只看到CPU没看到GPU,说明CUDA运行时没被正确加载,问题一定在环境配置而不是Hashcat本身。
3.2 一个典型的版本错配场景
我遇到过最典型的情况:驱动是比较新的版本,但系统里装的CUDA运行时是旧版,Hashcat编译时链接的是新版运行时。结果就是hashcat -I能看到GPU,但一跑就报cuInit失败或者直接崩溃。
排查思路是看Hashcat启动时的详细日志:
hashcat -I --backend-ignore-cuda hashcat -I --backend-ignore-opencl分别禁用CUDA和OpenCL后端,看哪个后端能正常列出设备。如果禁用CUDA后OpenCL能列出GPU,说明CUDA运行时确实有问题,而OpenCL路径是通的。这时候有两个选择:修CUDA环境,或者干脆用OpenCL后端跑(性能可能略低但能用)。
修CUDA环境的稳妥做法是:卸载现有运行时,装一个与驱动版本匹配的运行时,装完重启,再用hashcat -I验证。不要试图在旧运行时上"打补丁",版本错配的坑补不完。
3.3 多显卡与显存不足的处理
多显卡机器上,Hashcat默认会用所有GPU。如果某张卡显存较小,跑大字典或复杂规则时可能报显存不足(Out of memory或Memory allocation error)。这时候用-d参数指定设备编号:
hashcat -I # 记下目标GPU的编号,比如1 hashcat -m 13000 -a 0 hash.txt wordlist.txt -d 1显存不足还有一个隐蔽原因:工作负载参数(workload profile)设得太高。-w 3或-w 4会显著增加显存占用换取速度,小显存卡上直接爆掉。默认-w 2在多数场景下是平衡点,先跑默认,稳定后再尝试调高。
注意:调高workload profile带来的速度提升在密码恢复后期(候选空间很大时)才有意义,前期字典攻击阶段收益不明显,反而增加不稳定风险。我的习惯是先用
-w 2跑通,确认稳定后再针对具体任务微调。
4. 攻击模式选择:字典、掩码、混合到底怎么选
工具跑起来只是开始,真正决定成败的是攻击模式。选错模式,再强的显卡也是白跑。这一节把三种主流模式的适用场景和参数写法讲透。
4.1 字典攻击:最常用但也最容易被低估
字典攻击(-a 0)是用一个词表逐个尝试。看起来最简单,实际上词表质量决定了一切。网上随便下的"万能字典"往往包含大量重复和无关词条,跑起来又慢命中率又低。
我的做法是分层准备词表:
- 基础层:常用密码排行(类似rockyou这类公开词表),覆盖最常见的弱密码。
- 场景层:根据目标可能的习惯定制,比如包含特定年份、常见名字变体、键盘模式(qwerty、1qaz2wsx这类)。
- 规则层:不直接堆词表,而是用规则引擎对基础词表做变形。
规则引擎是字典攻击的放大器。Hashcat的-r参数加载规则文件,一条基础密码经过规则变形可以生成几十上百个变体(大小写变换、追加数字、替换字符等)。这比单纯堆一个巨大的词表高效得多,因为规则是运行时展开的,不占额外存储。
hashcat -m 13000 -a 0 hash.txt base_wordlist.txt -r rules/best64.rulebest64.rule是Hashcat自带的经典规则集,64条规则覆盖了最常见的变形模式,作为起点很合适。跑完没结果再换更大的规则集,比如dive.rule(约十万条规则),但要注意规则越多,等效候选空间越大,耗时成倍增长。
4.2 掩码攻击:知道密码结构时的利器
掩码攻击(-a 3)适合你已经对密码结构有判断的场景,比如"8位纯数字"、"首字母大写加6位小写加2位数字"这种。掩码用占位符描述结构:
?d数字 0-9?l小写字母?u大写字母?s特殊符号?a全部可打印字符
一个8位纯数字密码的掩码就是?d?d?d?d?d?d?d?d,候选空间10的8次方,一亿个。这个量级在像样的显卡上几分钟到几十分钟能跑完(取决于加密类型)。
掩码的威力在于精准。如果你确定密码是"某单词+4位数字",用混合模式(-a 6或-a 7)比纯掩码更高效:
# -a 6: 字典在前,掩码在后 hashcat -m 13000 -a 6 hash.txt wordlist.txt ?d?d?d?d # -a 7: 掩码在前,字典在后 hashcat -m 13000 -a 7 hash.txt ?d?d?d?d wordlist.txt这里有个计算上的细节值得说清楚。假设词表有10万条,追加4位数字,等效候选空间是10万 × 1万 = 10亿。这个量级在AES-256加密上可能要跑很久,所以混合模式一定要配合对密码结构的合理判断,不能盲目上。
4.3 模式选择的决策逻辑
把选择逻辑整理成一张表更直观:
| 已知信息 | 推荐模式 | 理由 |
|---|---|---|
| 完全不知道 | 字典 + 规则(-a 0 -r) | 覆盖面广,先碰运气 |
| 知道是纯数字/纯字母 | 掩码(-a 3) | 精准,空间可控 |
| 知道是单词+数字组合 | 混合(-a 6/7) | 利用结构信息 |
| 有部分已知片段 | 掩码中嵌入固定字符 | 进一步缩小空间 |
| 字典跑完无果 | 换更大规则集或组合攻击 | 逐步扩大搜索 |
实际项目中,这几种模式往往是串联使用的:先字典加规则快速筛一遍,没结果再根据目标特征上掩码或混合。不要指望一种模式解决所有问题。
5. John the Ripper的差异化用法
Hashcat在GPU加速上优势明显,但John the Ripper在某些场景下更顺手,尤其是它的"自动检测"能力和对多种格式的统一处理。两者配合使用能覆盖更多情况。
5.1 John的自动格式识别与增量模式
John最大的便利是自动识别哈希格式,不需要手动指定模式编号。把提取好的哈希文件直接喂进去:
john --wordlist=wordlist.txt zip_hash.txtJohn会自己判断这是ZIP还是RAR、是哪种加密。这个特性在你不确定哈希格式时特别有用——先用John跑一下看它识别成什么,再决定要不要转到Hashcat上加速。
John的增量模式(incremental)是它的特色功能,本质是一种基于统计的智能掩码,会按字符出现频率排序尝试:
john --incremental zip_hash.txt这个模式适合完全不知道密码结构、但密码本身不太长的情况。它的候选顺序经过优化,短密码命中率不错,但长密码上不如精准掩码高效。
5.2 John的GPU支持与编译注意事项
John的GPU支持需要专门编译(--enable-opencl或--enable-cuda),发行版自带的二进制往往只编译了CPU版本。这意味着你从包管理器装的John可能根本用不上显卡,跑起来慢得让人怀疑人生。
验证方法:跑John时看它启动信息里有没有列出OpenCL/CUDA设备。没有的话就是CPU版本。要GPU加速得自己从源码编译,编译时确保计算环境已配好(和Hashcat那节的要求一致)。
我的实际取舍是:短字典快速验证用John(省去指定模式的麻烦),大规模跑用Hashcat(GPU利用更充分、参数更细)。两者不是替代关系,是互补关系。
5.3 恢复会话与进度管理
密码恢复可能跑很久,中途中断是常事。两个工具都支持会话恢复,但用法不同。
Hashcat用--session指定会话名,中断后用--restore恢复:
hashcat -m 13000 -a 0 hash.txt wordlist.txt --session myjob # 中断后 hashcat --restore --session myjobJohn则用--session配合--restore,但它默认会自动保存进度到~/.john/目录下:
john --session=myjob --wordlist=wordlist.txt zip_hash.txt # 恢复 john --restore=myjob提示:Hashcat的恢复依赖
.restore文件,这个文件默认写在当前工作目录。如果你在不同目录下启动恢复,会找不到进度。养成习惯:跑长任务时固定在一个目录下操作,或者用--restore-file-path显式指定路径。
6. 实测中的性能调优与踩坑记录
前面讲的都是"应该怎么做",这一节讲"实际做的时候会遇到什么"。这些经验大多来自反复试错,文档里不会写。
6.1 温度墙与降频:跑得快不如跑得稳
GPU长时间满载,温度上去之后会触发降频保护,hash rate断崖式下跌。我见过一张卡刚开始跑每秒几十万次,十分钟后掉到几万次,就是因为散热跟不上。
监控温度用nvidia-smi -l 1(每秒刷新)。如果温度持续逼近显卡的温度上限(不同卡不同,通常在80-90度区间),要么改善散热,要么用--hwmon-temp-abort设置一个温度阈值让Hashcat自动暂停:
hashcat -m 13000 -a 0 hash.txt wordlist.txt --hwmon-temp-abort=85这个参数的意思是温度到85度就中止,保护硬件。跑长任务时建议加上,宁可慢一点也别把卡跑坏。
6.2 字典顺序对命中时间的影响
字典攻击是按词表顺序逐个尝试的。如果高频密码排在词表后面,就要等很久才轮到。所以词表内部的排序很重要——把最可能的密码放前面。
实操上,我会把词表按"可能性"分层拼接:先放针对目标定制的少量高概率候选,再放通用高频密码,最后放全量词表。这样即使全量部分要跑很久,前面的高概率部分几分钟内就能出结果(如果命中)。
6.3 一个容易被忽略的细节:哈希文件里的多段数据
前面提过,一个压缩包里有多个加密成员时,提取出的哈希文件可能包含多段。Hashcat默认只处理第一段(或者说按行处理,但同一文件的多段需要确认格式)。如果密码其实对应的是第二段成员,就会漏掉。
处理办法是先看哈希文件有几行有效数据:
grep -c '^\$' zip_hash.txt如果大于1,说明有多段。这时候要么分别提取成多个文件逐个跑,要么确认工具是否支持多哈希模式(Hashcat的--username和某些模式支持批量,但压缩包哈希的批量支持要看具体版本)。稳妥起见,我倾向于拆分成单段分别处理,避免遗漏。
6.4 关于"跑不出结果"的系统性排查
跑完没结果,按这个链路查,基本能定位问题:
- 哈希提取是否正确:拿一个你知道密码的测试压缩包,用同样流程提取并跑,能跑出来说明流程通。
- 模式编号是否匹配:哈希前缀和
-m参数是否对应,这是最高频的错误。 - 候选空间是否覆盖:密码结构判断是否准确,掩码或规则是否覆盖了真实密码的形态。
- 是否真的跑完了:看Hashcat的
Status是否为Exhausted,中途中断或报错不算跑完。 - 硬件是否稳定:温度、显存、驱动报错都可能导致中途静默失败。
这个排查顺序是从"流程正确性"到"参数正确性"再到"硬件稳定性",逐层排除。我踩过的坑里,前两层占了八成以上。
7. 合法边界与负责任的使用
技术本身中性,但使用场景有边界。压缩包密码恢复的正当用途包括:恢复自己遗忘密码的备份文件、在获得明确授权的前提下对自有资产做安全评估、取证场景下对合法持有的数据做分析。超出这些范围的使用不在本文讨论之列,也不应该尝试。
从防御角度看,理解这套流程反而能帮你做出更好的保护决策。比如:知道ZipCrypto的验证机制薄弱、单次尝试成本低,就应该避免用它保护敏感数据,改用AES-256;知道密码长度和字符集直接决定候选空间大小,就应该在密码强度上留足余量——一个12位以上、混合大小写数字符号的密码,其候选空间足以让任何硬件在可接受时间内放弃。这些判断比单纯记几条命令有价值得多。
我在实际配置环境时最大的体会是:工具跑通只是起点,真正花时间的是环境匹配和参数判断。CUDA版本、驱动版本、哈希格式、攻击模式,这四样任何一样对不上,表现都是"跑不出结果"这种没有明确报错的沉默失败。所以每次开新任务前,我都会先用一个已知密码的小文件做端到端验证,确认整条链路通了再上真实目标。这个习惯帮我省下的时间,远比多背几个参数多得多。