目 录CONTENT

文章目录

【PDF的查看密码破解】从thonny暴力破解到 hash 碰撞

JIN
JIN
2026-03-09 / 0 评论 / 1 点赞 / 1 阅读 / 0 字
广告 广告

【硬核实战】从 Python 单线程到 GPU 满载:记一次 PDF 密码的暴力破解与性能优化

前言:

这几天翻出了一个重要的加密 PDF 文件,密码忘了,但脑海中隐约记得密码的规律:“一个大写字母打头,后面跟着5位数字”

总搜索空间很好算:26个字母 $\times$ $10^5$ 种数字组合 = $2,600,000$ 次(260万次)。

260 万次并不多,我的第一反应是写个 Python 脚本硬算。但实操后发现,由于对底层计算体系架构的忽视,我绕了一个巨大的弯路。这篇文章将记录我是如何从一段“画蛇添足”的冗长代码,一步步转移到榨干 GPU 算力的工业级爆破方案。


一、 反面教材:被 I/O 拖垮的 Python 脚本

最开始,我基于 pikepdf 库写了下面这段代码,试图用 Python 直接遍历破解:

Python

import pikepdf

pdf_path = r"C:\Users\JinRC\Downloads\eSim (1).pdf"

for num in range(100000):
    password = f"D{num:05d}"
    try:
        pdf = pikepdf.open(pdf_path, password=password)
        print("密码找到:", password)
        pdf.close()
        break
    except:
        pass

1.1 架构级缺陷分析

从计算机组成原理和操作系统的视角来看,这段代码存在极大的资源浪费:

  • 单线程阻塞(GIL限制): Python 的 for 循环是单线程串行执行的。密码哈希碰撞是典型的 CPU 密集型任务,而这段代码完全没有利用到现代处理器的多核并发能力。
  • 灾难性的磁盘 I/O: 每次调用 pikepdf.open(),程序不仅在做哈希校验,还在请求操作系统分配文件句柄、进行磁盘 I/O 读取、解析 PDF 头部和交叉引用表(XREF)。
  • 结论: 将“计算密集型的哈希匹配”与“I/O 密集型的文件解析”强行耦合,导致 CPU 大量时钟周期全部浪费在等待内存和硬盘调度上。对于 260 万次的遍历,这种跑法可能需要挂机数天。

二、 核心重构:提取哈希与计算分离

正确的破译逻辑,必须将特征提取碰撞计算彻底分离。用 CPU 剥离文件外壳,用 GPU 处理高并发的纯粹数学运算。

2.1 提取 PDF 哈希值

通过开源的 pdf2john.py 脚本,我们不需要再读取原始 PDF 文件,而是直接提取出它的密码加密特征(Hash)。

DOS

python pdf2john.py "eSim (1).pdf" > raw_hash.txt

2.2 数据清洗

提取出的内容会带有文件名,例如 eSim (1).pdf:$pdf$5*6*256*...

专业的运算工具无法识别带有文件名的格式,必须手动删掉冒号及之前的所有内容,只保留 $pdf$ 开头的纯净 ASCII 字符串,另存为 hash.txt

💡 避坑小贴士:

文本清洗必须做到“一字不差”,文件末尾绝不能有任何空行、回车或中文句号。否则后续加载时会直接报错 Token length exception


三、 显卡出战:使用 Hashcat 掩码攻击

这里我们请出密码学爆破界的核武器 —— Hashcat。它能直接调度显卡的计算核心(如 AMD 的 MCU 或 NVIDIA 的 CUDA)执行并发计算。

3.1 确定哈希协议模式 (Hash Mode)

观察我们提取出的哈希:$pdf$5*6*256*...

  • 5 代表加密版本号 (V=5)
  • 6 代表加密修订版本 (R=6)
  • 256 代表采用了 256-bit AES 加密

在 PDF 规范中,R=6 对应的是 PDF 1.7 Extension Level 8,内部嵌套了多轮 SHA-256 迭代,属于典型的“慢哈希”。在 Hashcat 的模块映射字典中,它严格对应的参数是 -m 10700。(如果错写成 10500,程序会直接闪退拒绝执行)。

3.2 第一次执行:被忽视的寄存器浪费

基于我的记忆前提(1位大写字母+5位数字),构造掩码规则 ?u?d?d?d?d?d,开始执行:

DOS

hashcat.exe -m 10700 -a 3 hash.txt ?u?d?d?d?d?d -w 3

运行结果: 算力拉跨。

两组 AMD Radeon Graphics 并发,哈希率仅有可怜的 541 H/s。系统预估跑完这 260 万次需要 1 小时 18 分钟

缺陷指出:

日志中抛出了一行警告:ATTENTION! Pure (unoptimized) backend kernels selected.

程序默认加载了“纯内核”,它为了兼容长达 127 字节的超长密码,强行给每个线程分配了大量的 GPU 寄存器空间。而我们的密码明明只有 6 位,大量的寄存器资源被死死占满却处于空载状态,导致并发线程数断崖式下跌。

3.3 第二次执行:开启内核优化(性能飙升 8 倍)

立即按下 q 中止任务,在命令末尾追加大写的 -O 参数(Optimized Kernel),强制将密码最大长度限制在 16 字节以内,释放冗余寄存器。

DOS

hashcat.exe -m 10700 -a 3 hash.txt ?u?d?d?d?d?d -w 3 -O
状态 内核模式 显卡占用率 算力速率 预计总耗时
优化前 Pure Kernel (0-127 bytes) - 541 H/s 1 小时 18 分
优化后 Optimized Kernel (0-16 bytes) 97% 4712 H/s 9 分 11 秒

此时底层硬件调度彻底释放,速率飙升至 4712 H/s,性能直接翻了近 8.7 倍。


四、 成果与总结

在满载运行仅仅 3 分 51 秒后(遍历进度到达 32.57% 时),终端输出绿字:

Status.........: Cracked

最后一行成功打印出了明文密码:J97421

技术复盘:

  1. 不要用高级 API 解决底层计算问题: 单线程 Python 调库做文件级爆破是极其业余的,必须将哈希提取与 GPU 并发运算解耦。
  2. 硬件性能取决于资源分配: 面对“短掩码”时,-O 优化参数是榨干 GPU 并发性能的决定性开关。省下寄存器,就是成倍扩充并发线程池。

专业的事情,一定要交给专业的工具去做。

1
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin
广告 广告

评论区