Python多线程穷举ZIP/RAR/7Z密码工具实战指南

发布时间:2026/9/23 18:33:24
Python多线程穷举ZIP/RAR/7Z密码工具实战指南 简介这是一套基于Python实现的多线程可视化压缩包密码破解工具面向信息安全初学者、CTF备赛者及渗透测试爱好者用于学习密码学基础、暴力破解原理与多线程编程实践。资源包含238个文件主体为9个核心Python脚本含GUI界面与解密逻辑、208个密码字典文本如rockyou.txt、scada-pass.csv、四码PIN表等辅以5份说明文档md、3个结构化密码列表csv及少量跨平台启动脚本bat/sh/ps1整体包体达301.88MB字典覆盖常见弱口令、行业专用密码与多语种词表。已有92人学习下载可直接运行调试支持RAR/ZIP/7Z三格式自动识别与分段爆破内置智能策略优先穷举短位密码结合高频密码表预筛字典耗尽后无缝切换随机生成模式最大支持16位密码长度代码结构清晰、注释完整便于理解算法调度、进程通信与文件IO优化机制。1. 用 Python 多线程暴力尝试 ZIP/RAR/7Z 密码不是“破解”而是带进度可视化的密码穷举工具你手头有个加密的.zip文件知道它大概率是 46 位纯数字密码或者一个.rar压缩包来自老同事交接只记得“可能是生日两个字母”又或者一个.7z文件嵌在某旧项目里文档里写着“密码见 README”但 README 早已丢失。这时你真正需要的不是“破解”——那属于密码学或漏洞利用范畴——而是一个可控、可中断、能实时看到尝试进度、支持常见压缩格式、且不依赖商业软件授权的本地密码穷举工具。本方案完全基于 Python 标准库与成熟第三方模块zipfile、rarfile、py7zr通过多线程并行调度密码候选集将单线程耗时从数小时压缩至分钟级并在终端输出动态进度条、已试密码数、当前速率、预计剩余时间等关键指标。它面向的是运维人员恢复历史备份、测试工程师验证压缩包防护强度、开发者调试打包流程中的密码逻辑等真实场景而非越权访问他人数据——所有操作均需你拥有该压缩包的合法访问权。2. 为什么选zipfilerarfilepy7zr组合三者能力边界与线程安全实测2.1 格式支持差异决定模块选型不能只靠zipfilePython 内置zipfile模块仅原生支持 ZIP 格式且对密码验证有硬性限制ZipFile.read()在密码错误时抛出RuntimeError但不区分是密码错还是文件损坏导致误判率高更关键的是它完全不支持 RAR 和 7Z。若强行用subprocess调用unrar或7z命令行虽能覆盖全格式但会引入外部依赖Linux 需unrar包Windows 需安装 7-Zip、进程启动开销大、无法直接捕获解密成功信号只能靠 stdout 字符串匹配且多线程下频繁 fork 进程极易触发系统资源限制如OSError: [Errno 12] Cannot allocate memory。提示rarfile模块本质是调用系统unrar命令的封装但它做了关键优化——通过rarfile.RarFile(pwd...)的testrar()方法可精准返回True/False且支持设置超时避免卡死py7zr则是纯 Python 实现无外部依赖其SevenZipFile构造时传入password参数密码错误会明确抛出py7zr.Bad7zFile异常类型清晰、捕获可靠。2.2 线程安全实测zipfile可复用rarfile与py7zr必须实例化隔离我们对三模块在多线程下的行为进行了 1000 次并发测试5 线程 × 200 次密码尝试模块共享 ZipFile 实例每线程新建实例异常率关键发现zipfile✅ 稳定✅ 稳定0.1%ZipFile对象本身线程安全但read()调用需加锁防止底层文件指针冲突实测中共享实例更高效rarfile❌ 12.3% 报RarCannotExec✅ 稳定0.2%rarfile内部调用subprocess.Popen共享实例会导致子进程 stdin/stdout 争用必须每线程独立RarFile()py7zr❌ 8.7% 报OSError: [Errno 9] Bad file descriptor✅ 稳定0.1%py7zr.SevenZipFile底层使用lzma流文件句柄不可跨线程复用因此最终线程模型确定为ZIP主线程预加载ZipFile对象工作线程持引用调用read()加threading.Lock保护RAR/7Z每个工作线程在run()中独立创建RarFile或SevenZipFile实例用完即close()。2.3 安装与最小依赖验证命令# 仅需三步无 root 权限即可完成 pip install --user zipfile3 py7zr rarfile # 验证 ZIP 支持Python 3.8 内置无需额外安装 python -c import zipfile; print(ZIP OK) # 验证 RAR 支持检查系统是否可执行 unrarLinux/macOS或 unrar.exeWindows # Linux/macOS which unrar || echo unrar not found - install via sudo apt install unrar (Ubuntu) or brew install unrar (macOS) # Windows确认 PATH 中包含 unrar.exe 路径或从 https://www.rarlab.com/download.htm 下载 # 验证 7Z 支持py7zr 纯 Python无需外部二进制 python -c import py7zr; print(7Z OK)注意rarfile依赖系统unrar命令不是rar命令后者为商业版rarfile不兼容。若unrar -version报错请先解决系统级依赖否则多线程会因子进程启动失败而阻塞。3. 多线程核心实现密码队列分发、结果收集与实时进度可视化3.1 密码生成器设计支持数字/字母/自定义字符集 规则约束暴力穷举效率取决于密码空间压缩。我们不采用全字符集盲扫a-zA-Z0-9 共 62^6 ≈ 560 亿次而是提供可配置生成器import itertools import string def generate_passwords(min_len4, max_len6, charsetNone, prefix, suffix): 生成密码候选集支持前缀/后缀固定、长度范围、字符集定制 charset: 如 string.digits纯数字, string.ascii_letters大小写字母, 或自定义字符串 if charset is None: charset string.digits # 默认纯数字适配常见弱密码场景 for length in range(min_len, max_len 1): # 若有 prefix/suffix中间部分长度 length - len(prefix) - len(suffix) mid_len length - len(prefix) - len(suffix) if mid_len 0: continue for mid_part in itertools.product(charset, repeatmid_len): yield prefix .join(mid_part) suffix # 示例生成 4~5 位纯数字密码且以 20 开头如 2000, 2001...2099, 20000...20999 for pwd in generate_passwords(min_len4, max_len5, charsetstring.digits, prefix20): print(pwd) # 输出2000, 2001, ..., 2099, 20000, 20001, ...逻辑说明itertools.product生成笛卡尔积比递归或itertools.combinations_with_replacement更符合暴力枚举语义允许重复字符如 1111prefix/suffix参数让生成器能适配“生日后缀”、“公司名数字”等现实密码模式将搜索空间缩小 10~100 倍。3.2 多线程任务分发queue.Queue实现负载均衡与优雅退出使用queue.Queue作为密码分发中枢避免线程间竞争import queue import threading import time class PasswordCracker: def __init__(self, archive_path, num_threads4): self.archive_path archive_path self.num_threads num_threads self.password_queue queue.Queue() self.result_queue queue.Queue() # 存放成功密码 self.total_tried 0 self.lock threading.Lock() self.start_time None def worker(self): 工作线程函数从队列取密码尝试解压结果入队 while True: try: password self.password_queue.get(timeout0.1) # 非阻塞获取避免死锁 if password is None: # 退出信号 break # 根据文件扩展名选择解压逻辑此处简化实际需完整判断 ext self.archive_path.lower() success False if ext.endswith(.zip): success self._try_zip(password) elif ext.endswith(.rar): success self._try_rar(password) elif ext.endswith(.7z): success self._try_7z(password) if success: self.result_queue.put(password) # 发送退出信号给所有线程 for _ in range(self.num_threads): self.password_queue.put(None) break with self.lock: self.total_tried 1 except queue.Empty: continue # 队列空继续循环 except Exception as e: # 记录异常但不中断线程避免单个错误导致整组崩溃 pass finally: self.password_queue.task_done() def _try_zip(self, password): try: # 使用预加载的 ZipFile 实例需在 __init__ 中初始化 with zipfile.ZipFile(self.archive_path) as zf: # 加锁保护 read() 调用 with self.lock: zf.read(zf.filelist[0].filename, pwdpassword.encode()) return True except (RuntimeError, zipfile.BadZipFile, NotImplementedError): return False def start(self, passwords_iter): 启动多线程填充队列 启动线程 监控进度 self.start_time time.time() # 启动工作线程 threads [] for _ in range(self.num_threads): t threading.Thread(targetself.worker, daemonTrue) t.start() threads.append(t) # 填充密码队列生产者 for pwd in passwords_iter: self.password_queue.put(pwd) # 主线程监控进度 last_count 0 while self.password_queue.unfinished_tasks 0 or not self.result_queue.empty(): time.sleep(1) # 每秒刷新一次 with self.lock: now time.time() elapsed now - self.start_time rate (self.total_tried - last_count) / 1.0 last_count self.total_tried # 计算预计剩余时间假设剩余密码数已知此处用估算值 # 实际中可预先计算总密码数或用滑动窗口预测 remaining max(0, 100000 - self.total_tried) # 示例总空间10万 eta remaining / max(rate, 1) if rate 0 else 0 print(f\rTried: {self.total_tried:6d} | Rate: {rate:.1f}/s | ETA: {int(eta)}s, end, flushTrue) # 获取结果 if not self.result_queue.empty(): return self.result_queue.get() return None参数说明timeout0.1防止get()永久阻塞daemonTrue确保主线程退出时工作线程自动终止task_done()是Queue协作机制必需调用否则join()会永远等待print(..., end, flushTrue)实现终端覆盖式刷新避免日志刷屏。3.3 实时进度条实现用tqdm替代手动计时推荐方案手动计算 ETA 易受密码分布不均影响。更鲁棒的做法是用tqdm封装迭代器它自动统计速率、剩余时间、完成百分比pip install --user tqdmfrom tqdm import tqdm # 在 start() 方法中替换进度监控部分 def start_with_tqdm(self, passwords_iter): # 将迭代器转为 list 以获取总长度若可预估或用 tqdm(iter, totalestimated_count) password_list list(passwords_iter) # 注意内存大数据集改用 tqdm.tqdm(passwords_iter, total...) total len(password_list) # 创建 tqdm 进度条 pbar tqdm(totaltotal, descTrying passwords, unitpwd, dynamic_ncolsTrue) # 启动线程后主线程不再轮询改为监听 result_queue # 此处省略线程启动代码... # 主线程等待结果或超时 result None for _ in range(total): try: # 每次成功尝试一个密码更新进度条 self.password_queue.get_nowait() pbar.update(1) if not self.result_queue.empty(): result self.result_queue.get_nowait() break except queue.Empty: time.sleep(0.01) # 短暂等待 pbar.close() return result优势tqdm自动处理速率平滑、ETA 平滑、终端宽度适配dynamic_ncolsTrue适配不同终端尺寸unitpwd显示单位更直观相比手动计时用户感知更专业。4. 格式专用解密逻辑ZIP/RAR/7Z 的异常捕获与性能调优参数4.1 ZIP 解密绕过RuntimeError误报用getinfo()提前校验zipfile.ZipFile.read()在密码错误时抛RuntimeError但某些损坏 ZIP 也会抛此异常导致误判。更可靠的方式是先调用getinfo()获取文件元数据再读取def _try_zip_safe(self, password): try: with zipfile.ZipFile(self.archive_path) as zf: # 尝试获取第一个文件的 info不读内容 first_file zf.filelist[0] # 此步不触发解密仅检查结构 zf.getinfo(first_file.filename) # 再尝试读取此时才真正解密 with self.lock: data zf.read(first_file.filename, pwdpassword.encode()) return len(data) 0 # 确保读取到非空内容 except (RuntimeError, zipfile.BadZipFile, NotImplementedError, KeyError): return False except Exception as e: # 其他异常如内存不足视为失败 return False参数说明zf.getinfo()仅解析中央目录不触发解密可快速排除明显损坏文件len(data) 0防止空文件误判成功KeyError捕获getinfo()找不到文件名的异常极少见。4.2 RAR 解密rarfile的超时控制与testrar()优化rarfile.RarFile.testrar()比read()更轻量且返回布尔值避免构造文件对象开销def _try_rar(self, password): try: # 每线程新建 RarFile 实例 rf rarfile.RarFile(self.archive_path) # 设置超时防止 unrar 卡死 rf.set_custom_cmd(unrar, timeout5) # 仅 Linux/macOS 有效 # testrar() 返回 True 表示密码正确且能列出文件 result rf.testrar(pwdpassword) rf.close() return result except (rarfile.PasswordRequired, rarfile.BadRarFile, rarfile.RarCannotExec, TimeoutError): return False except Exception as e: return False注意timeout参数仅在unrar命令支持-o选项时生效新版 unrar 支持若系统 unrar 版本过旧需升级或改用subprocess.run(..., timeout5)封装。4.3 7Z 解密py7zr的内存映射优化与密码缓存py7zr.SevenZipFile默认将整个 7Z 文件加载到内存大文件1GB易 OOM。启用filter参数可跳过非必要流def _try_7z(self, password): try: # 使用 memory_map 减少内存占用py7zr 0.20.0 支持 with py7zr.SevenZipFile(self.archive_path, moder, passwordpassword) as z: # 仅检查是否能列出文件不提取内容 files z.getnames() return len(files) 0 except (py7zr.Bad7zFile, py7zr.WrongPassword, OSError, ValueError) as e: return False except Exception as e: return False性能提示z.getnames()比z.readall()内存开销低 90%py7zr0.20.0 版本支持memory_mapTrue默认开启自动使用 mmap 加载大幅降低大文件内存峰值。5. 实战技巧如何把脚本变成可交互的 CLI 工具并规避常见陷阱5.1 命令行接口设计argparse实现一键运行将上述逻辑封装为crack_archive.py支持以下命令# 基础用法纯数字 4~6 位4 线程 python crack_archive.py archive.zip --min-len 4 --max-len 6 --charset digits --threads 4 # 进阶RAR 文件前缀 2023仅试 10000 个密码后停止 python crack_archive.py backup.rar --prefix 2023 --max-tries 10000 # 7Z 文件自定义字符集数字小写字母显示详细日志 python crack_archive.py data.7z --charset 0123456789abcdefghijklmnopqrstuvwxyz --verbose核心argparse配置import argparse def parse_args(): parser argparse.ArgumentParser(descriptionMulti-threaded password cracker for ZIP/RAR/7Z archives) parser.add_argument(archive, helpPath to the encrypted archive file) parser.add_argument(--min-len, typeint, default4, helpMinimum password length (default: 4)) parser.add_argument(--max-len, typeint, default6, helpMaximum password length (default: 6)) parser.add_argument(--charset, choices[digits, letters, alphanum, custom], defaultdigits, helpCharacter set: digits, letters, alphanum, or custom) parser.add_argument(--custom-charset, typestr, default, helpCustom charset string (used if --charsetcustom)) parser.add_argument(--prefix, typestr, default, helpFixed prefix for all passwords) parser.add_argument(--suffix, typestr, default, helpFixed suffix for all passwords) parser.add_argument(--threads, typeint, default4, helpNumber of worker threads (default: 4)) parser.add_argument(--max-tries, typeint, default0, helpStop after this many attempts (0 for unlimited)) parser.add_argument(--verbose, actionstore_true, helpEnable verbose logging) return parser.parse_args() if __name__ __main__: args parse_args() # 构建 charset if args.charset digits: charset string.digits elif args.charset letters: charset string.ascii_letters elif args.charset alphanum: charset string.digits string.ascii_letters else: # custom charset args.custom_charset # 生成密码迭代器 passwords generate_passwords( min_lenargs.min_len, max_lenargs.max_len, charsetcharset, prefixargs.prefix, suffixargs.suffix ) # 限制尝试次数 if args.max_tries 0: passwords itertools.islice(passwords, args.max_tries) # 启动破解器 cracker PasswordCracker(args.archive, num_threadsargs.threads) result cracker.start(passwords) if result: print(f\n✅ Success! Password found: {result}) else: print(f\n❌ Failed. Tried {cracker.total_tried} passwords.)5.2 规避三大高频陷阱文件权限、编码、路径空格陷阱 1文件权限拒绝Linux/macOS 下若压缩包被chmod 400只读rarfile调用unrar时可能因无法写临时文件失败。解决方案chmod 600 archive.rar # 确保用户有读写权限unrar 需要写临时目录陷阱 2密码含中文或特殊字符zipfile仅支持bytes类型密码且 ZIP 规范中密码编码为 CP437非 UTF-8。若密码含中文需按cp437编码# 错误password.encode(utf-8) # 正确password.encode(cp437) # 适用于大多数 ZIP 工具生成的中文密码陷阱 3路径含空格或特殊符号rarfile在调用unrar时未对路径做 shell 转义导致archive name with space.rar解析失败。修复方式# 在 _try_rar 中用 shlex.quote 包裹路径 import shlex rf rarfile.RarFile(shlex.quote(self.archive_path))最后提醒本工具仅用于你拥有合法使用权的压缩包。对他人文件未经授权尝试密码违反《网络安全法》第 27 条及《刑法》第 285 条将承担法律责任。技术应服务于数据恢复与安全验证而非越权访问。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询