Python暴力破解RAR密码:从字典优化到多进程加速的实用技巧

📅 2026/7/23 8:50:26
Python暴力破解RAR密码:从字典优化到多进程加速的实用技巧
1. 项目概述与核心思路最近在论坛上看到不少朋友在讨论RAR压缩包密码忘了怎么办评论区总有人开玩笑说“等一个破解版”或者“蹲一个好心人分享密码”。说实话这种被动等待基本等于放弃。作为一个经常和数据、脚本打交道的人我处理过不少类似情况比如同事离职留下的加密文档或者自己多年前备份的、密码早已遗忘的私人资料。直接放弃太可惜而市面上那些所谓的“破解软件”要么收费昂贵要么捆绑病毒风险极高。其实用Python自己写一个暴力破解脚本是成本最低、最可控的方案。但很多人一听到“暴力破解”脑海里浮现的就是一个笨重的脚本从“000000”开始试到天荒地老觉得效率低下到毫无实用价值。这确实是最初级的实现方式。今天要聊的就是如何跳出这个“傻等”和“傻跑”的误区通过三个核心的优化技巧让你手中的Python脚本从一个玩具变成一个真正有可能解决问题的实用工具。我们的目标不是去破解那些高强度的随机密码那需要庞大的算力本就不现实而是针对我们日常可能设置的、有一定规律的密码大幅提升尝试的成功率和效率。简单来说这个项目的核心是利用Python自动化密码尝试过程并通过策略优化让“暴力”变得“聪明”起来从而在有限的时间和计算资源内最大化破解常见弱密码的可能性。它适合那些手头有加密RAR文件并且确信密码强度不高例如生日、简单单词、常见组合的用户。这更像是一个数字取证或数据自救的实用技巧而非黑客工具。2. 暴力破解的原理与效率瓶颈分析在讨论优化之前我们必须先理解传统暴力破解为何如此之慢。所谓暴力破解Brute-Force Attack本质上就是穷举法生成所有可能的密码组合并逐一尝试直到找到正确的那一个。2.1 密码空间与时间复杂度假设一个密码由小写字母26个和数字10个组成长度为6位。那么可能的密码总数为(26 10)^6 36^6 ≈ 21.7亿种组合。如果脚本每秒能尝试1000个密码这是一个比较乐观的本地性能估计那么穷举完所有组合需要21.7亿 / 1000 / 3600 / 24 ≈25天。这只是6位纯数字字母组合。如果密码长度增加到8位或者包含了大小写字母和符号这个时间会呈指数级增长到数百年甚至更久。这就是“暴力”的残酷现实——搜索空间Keyspace太大。2.2 传统脚本的流程与瓶颈一个最基础的Python暴力破解RAR脚本流程通常如下导入rarfile库用于处理RAR文件。指定目标RAR文件路径。定义一个密码生成器例如从itertools.product生成所有字符组合。循环遍历每一个生成的密码。对每一个密码使用rarfile.RarFile.extractall()或testrar()方法进行尝试。如果抛出rarfile.BadRarFile或RuntimeError密码错误则继续如果成功则跳出循环并输出密码。它的主要瓶颈在于I/O与计算密集每次尝试都需要调用RAR解压程序通过rarfile库底层调用UnRAR这是一个相对耗时的外部进程调用和文件操作。盲目搜索从“aaaaaa”开始按顺序尝试完全没有利用任何关于密码的先验知识比如人类设置密码的常见习惯。单线程运行通常一次只尝试一个密码无法利用现代多核CPU的并行计算能力。理解这些瓶颈就是我们进行优化的突破口。优化的核心思想就是减少不必要的尝试次数并提升单位时间内的尝试速度。3. 效率优化技巧一密码字典优先与智能生成第一个也是最重要的技巧就是彻底抛弃“从零开始穷举”的思维转向“基于概率的智能枚举”。密码字典Dictionary是我们最好的朋友。3.1 为何密码字典如此有效绝大多数人并非密码学专家设置的密码往往来源于常见弱密码如123456,password,admin,qwerty,111111等。个人信息相关生日19901231、姓名拼音zhangsan、手机号、车牌号。词典单词英文单词sunshine,dragon、中文拼音woaini及其简单变形如首字母大写、尾部加数字Sunshine123。模式化密码公司名年份Company2023、网站名通用密码baidu123。一个精心准备的密码字典可能只包含几万到几十万个条目但能覆盖现实中超过50%的弱密码场景。用字典攻击可能几秒或几分钟内就成功了而穷举法还在数亿种组合中徘徊。3.2 如何获取与制作高质量字典你可以从网上下载一些现成的通用字典包如rockyou.txt但请注意版权和安全来源但最好的字典往往是“定制化”的。制作针对性字典的Python示例import itertools def generate_targeted_dict(base_words, output_filemy_dict.txt): 基于已知信息生成针对性字典 :param base_words: 列表包含已知的姓名、生日、昵称、公司名等 :param output_file: 输出字典文件路径 common_suffixes [, 123, !, , 123456, 2024, 888] common_prefixes [, a, i, my] with open(output_file, w, encodingutf-8) as f: # 1. 基础词直接写入 for word in base_words: f.write(word \n) # 2. 基础词 常见后缀 for word, suffix in itertools.product(base_words, common_suffixes): f.write(word suffix \n) # 3. 基础词首字母大写变形 for word in base_words: f.write(word.capitalize() \n) for suffix in common_suffixes: f.write(word.capitalize() suffix \n) # 4. 组合基础词如姓名生日 # 这里简单演示两两组合 for w1, w2 in itertools.product(base_words, base_words): if w1 ! w2: f.write(w1 w2 \n) f.write(w1.capitalize() w2 \n) # 假设我们知道目标可能使用这些信息 known_info [zhangsan, 19900815, beijing, company] generate_targeted_dict(known_info)这个脚本会生成一个包含基础词及其常见变形的字典文件。在实战中字典的质量直接决定了破解速度。花时间分析目标如果是自己的文件就是回忆自己的习惯并制作一个精准的小字典远比用一个几十GB的通用大字典但99.999%都用不上要高效得多。注意rarfile库在处理非ASCII密码如中文时需要确保密码字符串的编码与压缩时一致通常尝试utf-8或gbk。在写入字典文件和传递密码时要特别注意编码问题。4. 效率优化技巧二多进程并行加速破解当我们有了一个字典哪怕有几百万条或者在一个较小的密钥空间内进行穷举时单线程顺序尝试仍然是主要的耗时瓶颈。现代CPU都是多核的让多个核心同时为我们工作能几乎线性地提升尝试速度。4.1 Python多进程 vs 多线程由于Python的全局解释器锁GIL的存在对于CPU密集型任务如我们的密码尝试虽然涉及I/O但核心的循环和生成是CPU计算使用multiprocessing多进程比threading多线程更能有效利用多核资源。每个进程有独立的Python解释器和内存空间可以真正并行运行。4.2 实现一个进程池破解器我们可以使用multiprocessing.Pool来创建一个进程池将字典列表分块分配给不同的工作进程同时尝试。import rarfile from multiprocessing import Pool, cpu_count import sys def try_password(args): 单个密码尝试函数将被多个进程调用。 设计为接收元组参数便于pool.map传递多个参数。 rar_path, password args try: # 每个进程内部创建自己的RarFile对象避免进程间资源冲突 with rarfile.RarFile(rar_path) as rf: # 尝试用密码访问第一个文件最快的方法 rf.testrar(pwdpassword) # 如果testrar没有抛出异常说明密码正确 return password except (rarfile.BadRarFile, RuntimeError): # 密码错误返回None return None except Exception as e: # 其他异常如文件损坏 print(f尝试密码 {password} 时发生异常: {e}, filesys.stderr) return None def parallel_rar_crack(rar_path, dict_file, max_processesNone): 并行RAR密码破解函数 :param rar_path: RAR文件路径 :param dict_file: 字典文件路径 :param max_processes: 最大进程数默认使用CPU核心数 # 读取字典 with open(dict_file, r, encodingutf-8, errorsignore) as f: passwords [line.strip() for line in f if line.strip()] if not passwords: print(字典文件为空) return print(f加载了 {len(passwords)} 个密码开始并行破解...) # 准备参数列表 task_args [(rar_path, pwd) for pwd in passwords] # 设置进程数不超过CPU核心数和密码总数 if max_processes is None: max_processes cpu_count() max_processes min(max_processes, len(passwords), cpu_count()) found_password None # 使用进程池 with Pool(processesmax_processes) as pool: # imap_unordered 可以更快地得到结果不保证顺序 for result in pool.imap_unordered(try_password, task_args, chunksize100): # chunksize可调整 if result is not None: found_password result pool.terminate() # 找到密码后立即终止所有进程 break if found_password: print(f\n[] 密码破解成功密码是: {found_password}) else: print(f\n[-] 很遗憾字典中未找到正确密码。) if __name__ __main__: # 确保在Windows下多进程能正确运行 rar_file encrypted.rar dictionary my_dict.txt parallel_rar_crack(rar_file, dictionary)关键点解析if __name__ __main__:这是多进程编程的黄金法则尤其在Windows系统上必须使用以防止子进程无限递归创建新进程。进程间通信每个进程独立运行try_password函数通过返回值与主进程通信。使用pool.terminate()可以在一个进程找到密码后立即优雅地关闭整个进程池避免无用的后续尝试。chunksize参数将任务参数分块传递给工作进程可以减少进程间通信开销提升效率。对于大量短任务适当增大chunksize如100或500通常有益。异常处理在子函数中妥善处理异常非常重要避免因为一个损坏的RAR文件或奇怪的密码导致单个进程崩溃进而影响整个任务。实操心得并行化带来的速度提升是显著的。在我的测试中8核CPU一个包含50万条密码的字典单进程需要约15分钟而8进程可以缩短到2分钟左右。但要注意进程数不是越多越好超过CPU物理核心数后会因进程切换开销导致收益递减。通常设置为cpu_count()或cpu_count()-1留一个核心给系统是比较好的选择。5. 效率优化技巧三利用GPU加速与更优的算法库对于追求极致速度或者需要攻击稍大一些密钥空间例如已知密码是7位纯数字的场景我们可以将计算密集型部分——即密码候选的生成与哈希校验环节——进行更底层的优化。虽然RAR解密本身最终要调用UnRAR但我们可以优化尝试的“前线”。5.1 理解RAR的加密与校验RAR文件使用的是一种基于AES-128/256的加密算法。当我们使用rarfile.testrar()时底层发生的是脚本将密码传递给UnRAR动态库或命令行工具。UnRAR使用该密码和文件中的盐值Salt等参数进行密钥派生。尝试解密文件头中的一小部分校验数据。如果解密出的校验值正确则返回成功否则返回密码错误。这个过程对于每个密码都是独立的。我们的多进程优化是让多个这样的过程并行。但每个过程内部依然是调用相对较慢的UnRAR。5.2 使用hashcat等外部工具进行协同一个更高级的思路是“分工协作”。我们可以用Python快速生成密码候选列表利用其灵活的字符串处理和字典组合能力然后将其传递给专业的、高度优化的离线密码恢复工具如hashcat或John the Ripper (JtR)。这些工具的特点极致优化用C/C编写针对特定算法包括RAR的汇编级别优化。GPU加速支持利用显卡GPU的数千个核心进行并行计算速度可能是CPU的数十倍甚至上百倍。规则引擎强大的密码变形规则系统可以动态地对字典进行各种变换无需预先生成庞大的字典文件。工作流程示例用Python准备攻击素材# 生成一个针对性的密码字典 # ... (同上文的字典生成代码) # 或者生成一个数字穷举列表 with open(numeric_6.txt, w) as f: for i in range(1000000): # 000000 到 999999 f.write(f{i:06d}\n)使用hashcat进行破解命令行操作# 首先需要从目标RAR文件中提取哈希值。 # 可以使用 rar2johnJohn the Ripper套件中的工具或 hashcat 的辅助工具。 # 例如用 rar2john 提取 # rar2john encrypted.rar rar_hash.txt # 提取出的哈希值类似于$RAR3$*1*adc83b19e793491b1c6ea0fd8b46cd9f*e9b8e*0*.... # 然后使用hashcat指定RAR算法模式-m 13000 for RAR3-hp, -m 23800 for RAR5 # 使用字典攻击模式-a 0和我们生成的字典 hashcat -m 13000 -a 0 rar_hash.txt my_dict.txt -o found_password.txt # 或者使用掩码攻击-a 3穷举6位数字 hashcat -m 13000 -a 3 rar_hash.txt ?d?d?d?d?d?d -o found_password.txt在这个流程中Python扮演了“策略制定者”和“后勤官”的角色负责生成精准的“弹药”字典而hashcat则是“重炮手”负责以最高效率进行火力倾泻。5.3 Python调用外部工具实现半自动化我们甚至可以用Python的subprocess模块将这个过程半自动化整合成一个更强大的工具。import subprocess import os import sys def crack_with_hashcat(rar_file, dict_fileNone, maskNone, hashcat_pathhashcat): 使用Python调用hashcat进行破解 :param rar_file: RAR文件路径 :param dict_file: 字典文件路径字典攻击 :param mask: 掩码字符串掩码攻击如 ?d?d?d?d?d?d :param hashcat_path: hashcat可执行文件路径 # 步骤1提取哈希这里需要rar2john或类似工具假设已安装并配置环境变量 hash_file temp_hash.txt try: subprocess.run([rar2john, rar_file], stdoutopen(hash_file, w), checkTrue) except FileNotFoundError: print(未找到 rar2john 工具请确保John the Ripper已安装并配置在PATH中。) sys.exit(1) except subprocess.CalledProcessError as e: print(f提取哈希失败: {e}) sys.exit(1) # 步骤2构建hashcat命令 cmd [hashcat_path, -m, 13000, --potfile-disable, -O, --force] # 基础参数 if dict_file: cmd.extend([-a, 0, hash_file, dict_file]) # 字典攻击 elif mask: cmd.extend([-a, 3, hash_file, mask]) # 掩码攻击 else: print(必须指定 dict_file 或 mask 参数。) return cmd.extend([-o, found.txt]) print(f运行命令: { .join(cmd)}) try: # 运行hashcat并实时输出其stdout process subprocess.Popen(cmd, stdoutsubprocess.PIPE, stderrsubprocess.STDOUT, textTrue) for line in process.stdout: print(line, end) # 实时显示hashcat进度 process.wait() # 检查结果 if os.path.exists(found.txt) and os.path.getsize(found.txt) 0: with open(found.txt, r) as f: lines f.readlines() if lines: # hashcat输出格式通常是 哈希值:密码 last_line lines[-1].strip() password last_line.split(:)[-1] print(f\n[] Hashcat破解成功密码是: {password}) return password print(\n[-] Hashcat未能破解。) return None except FileNotFoundError: print(f未找到hashcat可执行文件: {hashcat_path}) except Exception as e: print(f运行hashcat过程中出错: {e}) finally: # 清理临时文件 for f in [hash_file, found.txt, hashcat.potfile]: if os.path.exists(f): os.remove(f) # 使用示例 # crack_with_hashcat(encrypted.rar, dict_filemy_dict.txt) # crack_with_hashcat(encrypted.rar, mask?d?d?d?d?d?d)注意事项使用GPU加速工具需要相应的硬件NVIDIA或AMD显卡和驱动程序支持并且配置过程可能稍显复杂。但对于真正需要处理大量尝试的场景这是终极解决方案。Python脚本在这里的价值是灵活地生成攻击策略和调用这些专业工具实现“好钢用在刀刃上”。6. 实战脚本整合与性能对比让我们将前两个技巧字典多进程整合成一个更健壮、更实用的最终脚本并加入一些性能监控和用户体验的优化。import rarfile import itertools from multiprocessing import Pool, cpu_count, Manager import sys import time import signal import os class RarCracker: def __init__(self, rar_path): self.rar_path rar_path self.is_cracked False self.found_password None self.start_time None def try_password(self, password): 尝试单个密码 if self.is_cracked: # 快速失败检查 return None try: with rarfile.RarFile(self.rar_path) as rf: # 使用testrar()它比extractall()更快因为它只测试而不解压 rf.testrar(pwdpassword) return password except (rarfile.BadRarFile, RuntimeError, rarfile.PasswordRequired): return None except Exception as e: # 记录非密码错误的其他异常 print(f[!] 尝试密码 {password} 时遇到意外错误: {e}, filesys.stderr) return None def worker(self, args): 工作进程函数处理一批密码 pid, passwords args # print(f进程 {pid} 开始处理 {len(passwords)} 个密码) for pwd in passwords: if self.is_cracked: break result self.try_password(pwd) if result: self.is_cracked True self.found_password result return result return None def crack_with_dict_parallel(self, dict_file, max_workersNone, chunk_size500): 使用字典文件进行并行破解 :param dict_file: 字典文件路径 :param max_workers: 最大工作进程数 :param chunk_size: 每个进程一次处理的密码块大小 # 读取字典并去重 with open(dict_file, r, encodingutf-8, errorsignore) as f: all_passwords list(set(line.strip() for line in f if line.strip())) if not all_passwords: print([-] 字典文件为空或无效。) return False total len(all_passwords) print(f[*] 加载字典完成共有 {total} 个唯一密码。) print(f[*] 启动并行破解块大小: {chunk_size}...) self.start_time time.time() # 分割密码列表为块 password_chunks [all_passwords[i:i chunk_size] for i in range(0, total, chunk_size)] if max_workers is None: max_workers max(1, cpu_count() - 1) # 留一个核心给系统 # 准备进程池参数 pool_args [(i, chunk) for i, chunk in enumerate(password_chunks)] found False try: with Pool(processesmax_workers) as pool: # 使用imap_unordered获取结果 for i, result in enumerate(pool.imap_unordered(self.worker, pool_args), 1): if result: print(f\n[] 进程报告成功) self.found_password result found True pool.terminate() break # 可选每完成一定比例打印进度 if i % 10 0: elapsed time.time() - self.start_time speed (i * chunk_size) / elapsed if elapsed 0 else 0 print(f\r[*] 进度: {min(i*chunk_size, total)}/{total} | f速度: {speed:.1f} 密码/秒 | 耗时: {elapsed:.1f}秒, end) except KeyboardInterrupt: print(\n\n[!] 用户中断。) return False elapsed time.time() - self.start_time if found: print(f\n\n[] 破解成功) print(f[] 密码: {self.found_password}) print(f[] 总耗时: {elapsed:.2f} 秒) print(f[] 尝试密码数: {total if i*chunk_size total else i*chunk_size}) return True else: print(f\n\n[-] 破解失败字典中未找到正确密码。) print(f[-] 总耗时: {elapsed:.2f} 秒) return False def crack_with_mask(self, charset, min_len1, max_len6, max_workersNone): 使用掩码字符集和长度范围进行穷举并行破解 警告仅适用于非常小的搜索空间 :param charset: 字符串如 0123456789 或 abcdefghijklmnopqrstuvwxyz :param min_len: 最小密码长度 :param max_len: 最大密码长度 :param max_workers: 最大工作进程数 total_combinations sum(len(charset) ** l for l in range(min_len, max_len 1)) print(f[*] 字符集 {charset}长度 {min_len}-{max_len}) print(f[*] 总组合数: {total_combinations:,}) if total_combinations 10_000_000: # 一千万以上就太大了 print(f[!] 警告搜索空间过大 ({total_combinations:,})穷举可能不切实际。) print(f[!] 建议使用字典攻击或更精确的掩码。) if input(是否继续(y/N): ).lower() ! y: return False self.start_time time.time() # 生成所有密码组合这是一个内存消耗点对于大空间不合适 all_passwords [] for length in range(min_len, max_len 1): for combo in itertools.product(charset, repeatlength): all_passwords.append(.join(combo)) # 后续流程与字典攻击相同... # ... (这里可以复用上面的并行破解逻辑但更推荐流式生成避免内存爆炸) # 为简洁起见此处省略完整实现。实际应用中应使用itertools.product迭代器 # 并分块传递给工作进程而不是一次性生成所有组合。 print([-] 掩码穷举完整实现需处理内存问题建议对小空间使用或改用hashcat。) return False def signal_handler(signum, frame): print(\n[!] 接收到中断信号正在优雅退出...) sys.exit(0) if __name__ __main__: signal.signal(signal.SIGINT, signal_handler) # 捕获CtrlC if len(sys.argv) 3: print(用法: python rar_cracker.py RAR文件 字典文件 [进程数]) print(示例: python rar_cracker.py secret.rar passwords.txt 4) sys.exit(1) rar_file sys.argv[1] dict_file sys.argv[2] workers int(sys.argv[3]) if len(sys.argv) 3 else None if not os.path.exists(rar_file): print(f[-] 错误RAR文件 {rar_file} 不存在。) sys.exit(1) if not os.path.exists(dict_file): print(f[-] 错误字典文件 {dict_file} 不存在。) sys.exit(1) cracker RarCracker(rar_file) success cracker.crack_with_dict_parallel(dict_file, max_workersworkers) sys.exit(0 if success else 1)性能对比与选择建议方法优点缺点适用场景纯Python单线程字典简单依赖少易调试速度慢无法利用多核极小的字典1000条学习原理Python多进程字典显著提升速度利用多核纯Python实现进程间通信有开销管理稍复杂最常用中小型字典几万到百万级通用性强Python生成Hashcat终极速度GPU加速专业算法优化依赖外部工具配置复杂需特定硬件大型字典、掩码攻击追求极限速度有GPU设备纯Python掩码穷举灵活无需字典搜索空间爆炸内存/时间消耗大仅适用于已知格式的极短密码如6位纯数字对于绝大多数自用或普通场景“高质量定制字典 Python多进程”这个组合在易用性、效率和成功率之间取得了最佳平衡。它不需要额外硬件代码完全可控足以应对日常遇到的绝大多数“遗忘密码”情况。7. 常见问题、排查技巧与伦理边界在实际操作中你可能会遇到各种问题。这里记录一些典型的坑和解决方法。7.1 常见错误与排查rarfile.BadRarFile: File is not a RAR file或rarfile.NotRarFile原因文件损坏、不是RAR格式或者文件路径错误。排查用WinRAR或7-Zip等正规软件手动打开一下确认文件完好且确实是RAR格式。检查Python脚本中的文件路径是否正确建议使用绝对路径。RuntimeError: Bad password for file循环出现但脚本不停止原因这是密码错误的正常异常我们的脚本就是靠捕获这个异常来判断密码错误的。如果一直出现说明字典里的密码还没试完。确保你的字典文件没有空行或格式错误。UnicodeDecodeError或 中文密码无效原因密码或字典文件编码问题。解决在读取字典文件时指定正确的编码如encodingutf-8或encodinggbk。在尝试密码时如果密码包含非ASCII字符确保其以正确的编码格式传递给rarfile。有时需要尝试将字符串编码为字节pwd.encode(utf-8)。最稳妥的方法在创建RAR压缩包时如果密码包含中文最好记录下使用的编码。破解时可以尝试用不同编码生成密码候选。多进程脚本在Windows上报错或卡住原因Windows上多进程的启动方式与Unix不同。解决必须将主要逻辑放在if __name__ __main__:块中。确保没有在全局作用域进行文件操作或初始化复杂对象。速度远低于预期检查点字典太大先用一个很小的字典如10个密码测试确认脚本逻辑和速度基准。RAR文件本身加密算法RAR3, RAR5、压缩字典大小、文件数量都会影响单次尝试速度。RAR5通常比RAR3稍慢。硬件瓶颈如果是机械硬盘频繁读取大RAR文件会成为瓶颈。可以尝试将RAR文件放在SSD上运行。进程数过多过多的进程会导致CPU频繁切换反而降低效率。通常设置为CPU物理核心数或略少一点。chunksize不合适chunksize太小会导致进程间通信过于频繁太大会导致负载不均衡。对于密码尝试这种微任务通常设置100-1000之间进行测试。7.2 伦理与法律边界这是一个必须严肃讨论的部分。技术本身无罪但用途决定性质。合法用途破解自己创建但遗忘密码的加密文件。在获得明确授权的情况下进行安全审计或数字取证例如企业授权对离职员工留下的加密数据进行合规检查。教育学习与研究密码学强度。绝对禁止的用途未经授权破解他人的加密文件。这是明确的违法行为侵犯他人隐私和财产权。破解受版权保护的商业软件或资源。任何形式的黑客攻击、数据窃取。个人建议这个脚本和知识应该被视作一把“数字钥匙”用于打开你自己不小心锁上的“数字抽屉”。请务必将其用于正当目的并遵守所在地的法律法规。在分享代码时也应强调其伦理约束。真正的技术高手不仅懂得如何利用工具更懂得如何约束自己。最后再分享一个小心得对于非常重要的文件最好的“破解”方法是预防。使用密码管理器如Bitwarden、KeePass来生成并保存高强度、唯一的密码同时定期对重要加密文件进行备份并将密码妥善保存在多个安全的地方例如加密的笔记中或告诉可信赖的家人。技术是最后的防线良好的习惯才是根本的保障。