monahand1023/pdfcracker
GitHub: monahand1023/pdfcracker
专为 macOS Apple Silicon 优化的高性能 PDF 密码恢复工具,通过 Metal GPU 与 ARM NEON 加速支持所有 PDF 加密版本的破解。
Stars: 1 | Forks: 0
# pdfcracker
[](https://github.com/monahand1023/pdfcracker/releases) [](.) [](.) [](.) [](LICENSE)
专为 macOS 设计的快速 PDF 密码破解工具,针对 Apple Silicon 优化。支持所有 PDF 加密版本(R2–R6)、多种攻击模式、跨多台机器的分布式破解,并在启动时自动选择最快的加速引擎。
## 演示
`--fingerprint` 模式会检测加密方式,对所有可用的引擎进行基准测试,挑选出最快的引擎,并扫荡约 130 万个可能的密码(常见密码、键盘走位、日期、PIN 码)——在这里,它在 M4 Pro 上不到一秒钟就恢复了密码:
```
$ pdfcrack -f encrypted.pdf --fingerprint
Crypto : direct MD5+RC4 (R3, 128-bit key)
Metal : initialized on Apple M4 Pro (max batch: 262144)
Bench : scalar 51659/s, NEON 86608/s, GPU 91917/s (per-core) — GPU+NEON selected (1304432/s est.)
Target : encrypted.pdf
Threads: 14 + GPU + NEON SIMD
Mode : fingerprint (common passwords, keywalks, dates, PINs, ~1.3M candidates)
Phase 1: common passwords (68)...
User password found: test123
```
其他模式 —— `-d` 字典(+ `-R` 规则 / `-H` 混合)、`-b` 暴力破解、`-m` 掩码(`test?d?d?d`)、`--smart` 多阶段,以及 `--prince`:
```
$ pdfcrack -f encrypted.pdf -m "test?d?d?d"
Mode : mask attack ("test?d?d?d", keyspace 1000)
[####...............................] 12.4% 124/1000 248/s 1s
User password found: test123
```
## 环境要求
- macOS(推荐 Apple Silicon;也支持 Intel)
- Xcode Command Line Tools:`xcode-select --install`
无需任何外部依赖。所有功能均使用 macOS 内置的 CommonCrypto、CoreGraphics 和 Metal。
## 编译
```
git clone && cd pdfcracker
make # builds pdfcrack, server, client
make test # run all unit suites (test_all 80 assertions + saslprep + test_crypto)
bash test_integration.sh # run end-to-end integration tests (45 tests)
bash bench.sh # quick per-engine benchmark across R2–R6 (run on an idle machine)
```
## 架构
```
flowchart TD
subgraph main ["pdfcrack.c"]
modes["Attack modes:
brute, dict, mask, rules, hybrid, PRINCE,
smart, combinator, toggle, Markov,
leet, mutate, date, fingerprint, auto"] subgraph workers ["Worker threads"] bw["brute_worker
(+ _neon variant)"] dw["dict_worker
(+ _neon variant)"] rw["rule_worker
(+ gpu variant)"] end modes --> bw modes --> dw modes --> rw bw --> counter["shared atomic g_next_idx counter"] dw --> counter rw --> counter end counter --> cpu counter --> gpu subgraph cpu ["pdf_encrypt.c — CPU"] cpuv["pdf_verify_user_password()
pdf_verify_user_batch4() — NEON 4-way
md5 / rc4 / sha256 / sha512 / aes _simd.h"] end subgraph gpu ["metal_keygen.m — GPU"] gpuv["MD5 key-derivation (R2–R4)
SHA-256 verify (R5)
Algorithm 2.B KDF (R6)
pdf_md5.metal — Metal shader"] end ``` ### 关键文件 | 文件 | 作用 | |------|------| | `pdfcrack.c` | 独立破解器:包含所有攻击模式、工作线程、进度显示与检查点 | | `pdf_encrypt.c` | PDF 加密解析器及所有加密验证(R2–R6) | | `pdf_encrypt.h` | 解析器/加密层的公共 API | | `md5_simd.h` | ARM NEON 4 路并行 MD5(仅头文件) | | `rc4_inline.h` | 替代 CommonCrypto 的内联 RC4;包含 `rc4_first_byte` 提前退出机制 | | `sha256_simd.h` | ARM NEON SHA-256 指令集(仅头文件) | | `sha512_simd.h` | ARM NEON SHA-384/512 指令集(仅头文件) | | `aes_simd.h` | ARM Crypto Extensions AES-128-CBC(仅头文件) | | `metal_keygen.m` | Objective-C Metal 流水线:MD5 (R2–R4)、SHA-256 (R5)、Algorithm 2.B (R6) | | `metal_keygen.h` | Metal 流水线公共 API | | `pdf_md5.metal` | 用于 MD5 密钥派生的 Metal GPU 计算着色器 | | `saslprep.c` | 针对用于 R5/R6 密码的 SASLprep Unicode 规范化 | | `server.c` | 分布式协调器:基于租约的工作分发 + 本地破解 | | `client.c` | 分布式工作节点:支持所有 GPU 加速 | | `protocol.h` | 用于服务器↔客户端通信的文本行 TCP 协议 | | `rules.c` / `rules.h` | 兼容 Hashcat 的规则引擎(破解器和 Fuzzer 共享) | | `pdf_gpu_types.h` | Metal 主机和着色器共享的 GPU 参数结构体 | | `fuzz_rules.c` | 针对规则引擎的 libFuzzer 测试桩(链接真实的 `rules.c`) | | `test_parse_fuzz.c` | 针对 PDF 加密解析器的 ASan/UBSan libFuzzer 测试桩 | | `test_all.c` | 单元测试套件:覆盖 8 种 PDF 变体的 80 个断言(CoreGraphics + NEON/标量交叉验证) | | `test_integration.sh` | 45 个端到端集成测试(包含分布式回环测试) | | `bench.sh` | 可重复的跨 R2–R6 各引擎基准测试 | | `.github/workflows/ci.yml` | CI:构建、单元测试 + 集成测试、ASan/UBSan、Fuzzer 冒烟测试(macOS Apple Silicon) | | `Makefile` | 构建系统;`make test` 聚合测试、`pgo` 目标、Fuzzer 目标 | ## PDF 加密原理 PDF 使用了五种不同的加密方案,每一种都比前一种更强。 ### R2 — 40-bit RC4 (PDF 1.1–1.3) 1. 使用固定的填充常量将候选密码填充至 32 字节。 2. 对拼接了文档元数据(O 值、权限、文件 ID)的填充密码进行 MD5 哈希计算。 3. 截断为 5 字节 → 加密密钥。 4. 使用该密钥对 32 字节的填充常量进行 RC4 加密。 5. 将结果与存储的 `/U` 值进行比较。 速度快:一次 MD5 + 一次 RC4 处理。按现代标准来看极其脆弱。 ### R3/R4 — 128-bit RC4 或 AES-128 (PDF 1.4–1.6) 与 R2 相同,但使用 16 字节密钥,并对密钥字节进行 **50 次额外的 MD5 迭代**,然后进行 **20 次 RC4 处理**,使用经过 XOR 修改的密钥进行最终比较。50 次 MD5 迭代和 20 次 RC4 处理是多核扩展的瓶颈。 ### R5 — AES-256 / SHA-256 (PDF 1.7 ext3) 简单:将 `SHA-256(password + validation_salt)` 与存储的哈希值进行比较。无迭代,无 RC4。对于能够并行运行数千次 SHA-256 操作的 GPU 来说速度非常快。 ### R6 — AES-256 / SHA-256 + 迭代 KDF (PDF 2.0) 刻意增加计算成本。Algorithm 2.B 运行一个由 SHA-256/384/512 + AES-CBC 操作组成的循环,其中每轮的迭代次数(64 次以上)由前一轮的哈希输出决定。每次验证大约需要 60–70 微秒,使得大规模暴力破解变得不切实际。每一轮使用的具体哈希变体(SHA-256、384 或 512)也会变化,因此需要实现全部三种算法。 ### 所有者密码与用户密码 PDF 加密存储了两个密码: - **用户密码**(R2–R4):通过加密一个已知常量并与 `/U` 比较来验证。 - **所有者密码**(R2–R4):作为独立的密钥派生(Algorithm 3)存储 —— 所有者密钥解密 `/O` 值以恢复用户密码,然后再将其与 `/U` 进行验证。这就是为什么 GPU 派生的用户密钥不能直接用于所有者密码检查的原因。 ## 加速架构 ### 引擎选择 在启动时,pdfcracker 会在实际的 PDF 上对所有三种引擎进行基准测试,并挑选出最佳组合: ``` Bench: scalar 49K/s, NEON 82K/s, GPU 87K/s (per-core) — GPU+NEON selected (1.32M/s est.) ``` | 版本 | 最佳引擎 | 原因 | |----------|-------------|-----| | R2 | NEON | 对于 40 位加密,GPU MD5 比 14×NEON 慢 | | R3/R4 | GPU + NEON(同时) | GPU 处理大批量任务;NEON 填补空隙 | | R5 | GPU | 完全在片上进行 SHA-256;CPU 无法竞争 | | R6 | GPU + CPU 协同 | 共享工作计数器;双方共同贡献力量 | ### NEON 4 路并行 MD5 (`md5_simd.h`) ARM NEON 寄存器包含 4 × 32 位通道。`md5_x4()` 同时运行四个独立的 MD5 计算——每个通道一个——在密钥派生步骤上实现比标量计算高约 4 倍的吞吐量。对于 R3/R4,由于受限于串行的 20 次 RC4 验证,其增益被限制在比 14 个标量核心整体快约 1.5 倍。 `pdf_encrypt.c` 中的 `pdf_verify_user_batch4()` / `pdf_verify_owner_batch4()` 是支持 NEON 加速的入口点。它们接受 4 个密码,运行 4 路 SIMD MD5,然后串行验证每个 RC4 结果。 ### 内联 RC4 (`rc4_inline.h`) 原始实现在每个密码上调用 CommonCrypto 的 `CCCrypt(kCCAlgorithmRC4)`,导致每个 R3/R4 候选密码需要进行约 20 次函数调用。`rc4_inline.h` 使用仅包含头文件的实现取代了它: - `rc4_encrypt()` —— 通用目的 - `rc4_encrypt_16()` —— 针对 R3/R4 内部循环的 16 字节专用版本 - `rc4_first_byte()` —— 仅计算第一个输出字节;无需运行完整的 RC4,即可瞬间拒绝约 255/256 的错误候选密码 这种提前退出机制本身在 R2 中消除了 99.6% 错误候选密码的完整 RC4 计算,并且受到保护以正确跳过所有者密码检查(GPU 派生的用户密钥对于所有者候选密码总是错误的——无论如何,检查必须到达 `pdf_verify_owner_password()`)。 ### Metal GPU 流水线 (`metal_keygen.m`, `pdf_md5.metal`) 三个独立的 Metal 流水线共享同一个 `.metallib`: | 流水线 | 用于 | GPU 任务 | CPU 任务 | |----------|----------|----------|----------| | `metal_keygen` | R2–R4 | Algorithm 2 MD5 密钥派生 | RC4 验证 | | `metal_sha256` | R5 | 完整的 Algorithm 3.2 SHA-256 验证 | 无 | | `metal_r6` | R6 | 完整的 Algorithm 2.B KDF | 溢出的候选密码 | 这三个流水线都使用 **异步双缓冲调度**:当 GPU 处理第 N 批次时,CPU 正在准备第 N+1 批次并验证第 N−1 批次。对于 R6,子批次调度会拆分每个 GPU 批次,以便 CPU 可以在批次处理期间检测到匹配并提前中止。 ### 共享工作计数器 GPU 工作线程和 CPU/NEON 工作线程竞争同一个 `g_next_idx` 原子计数器。每个 NEON 工作线程每次获取 `NEON_WORK_CHUNK` (2048) 个候选密码;GPU 每次获取 `GPU_BATCH_SIZE`(最多 262,144 个)。这消除了专门的调度线程,并允许两个引擎根据其自然吞吐量进行自调度。 ### NEON SHA-256/384/512 指令集 (`sha256_simd.h`, `sha512_simd.h`) 用于 R6 的 CPU 路径。Algorithm 2.B KDF 内部循环根据中间哈希值调用 SHA-256、SHA-384 或 SHA-512。ARM Crypto Extensions(`vsha256h_u32` 以及等效的 SHA-512 指令)在硬件中运行这些操作,使得 CPU 端的 R6 破解吞吐量比 CommonCrypto 提高约 11%。 ### NEON AES (`aes_simd.h`) AES-128-CBC 用于 R6 KDF。ARM Crypto Extensions(`vaeseq_u8`、`vaesmcq_u8`)使用直接的硬件指令取代了查表 AES。 ## 攻击模式 | 模式 | 标志 | 描述 | |------|------|-------------| | 字典 | `-d` | 尝试字典中的每个单词,可选择使用 `--reverse` |
| 暴力破解 | `-b [-l ] [-c ]` | 枚举所有组合;默认字符集 a–z A–Z 0–9 |
| 掩码 | `-m ` | `?l`=小写 `?u`=大写 `?d`=数字 `?s`=特殊字符 `?a`=全部 `?w`=字典单词 |
| 规则 | `-R ` | 将兼容 Hashcat 的规则应用于字典单词 |
| 混合 | `-H ` 或 `-H ` | 将 N 字符暴力破解或掩码模式附加到字典单词后 |
| PRINCE | `-P` | 从字典对中生成概率单词链 |
| Smart | `--smart` | 多阶段智能攻击(见下文) |
| 组合器 | `--combinator ` | 两个字典的笛卡尔积 |
| 大小写切换 | `--toggle` | 字典单词的所有大小写变体 |
| 掩码 + 规则 | `-m -R ` | 将规则应用于掩码生成的候选密码 |
| Markov | `-I -M ` | 根据训练模型概率排序的暴力破解 |
| 变异 | `--mutate` | 对字典单词进行常见替换(a→@、e→3 等) |
| Leet | `--leet` | 对字典单词进行扩展的 leet-speak 替换 |
| 日期 | `--date` | 1940–2026 年的所有日期格式(YYYYMMDD、DDMMYYYY 等) |
| 指纹 | `--fingerprint` | 常见弱模式:日期、键盘走位、PIN 码格式 |
| 自动 | `-A` | 串联攻击:字典 → 规则 → 频率暴力破解 1–6 → 暴力破解 7–max |
| 反转 | `--reverse` | 在字典模式下同时也尝试反转的单词 |
| 去重 | `--dedup` | 在应用规则后跳过重复的候选密码 |
### Smart 模式 (`--smart`)
一种 Passware 风格的多阶段攻击,按现实世界的概率排序:
1. **元数据种子** —— 从 PDF 作者、标题、文件名派生的密码
2. **常见密码** —— 包含 68 个高频密码的精选列表
3. **种子变异** —— 大小写变体、追加数字、l33t 替换、反转
4. **用户字典 + 反转** —— 如果提供了 `-d`,通过 GPU+NEON 尝试单词和 `reverse(word)` *(提前执行,这样小型的定向字典就不会被淹没在 1.11 亿个 PIN 码之下)*
5. **PIN 码** —— 所有 1–8 个字符的纯数字字符串(1.11 亿个候选)
6. **日期模式** —— 1940–2026 年的所有格式(约 19.1 万个候选)
7. **键盘走位** —— 常见模式(qwerty、qaz 等)
8. **姓名 + 后缀** —— 带有数字/年份/符号后缀的常见姓名
9. **姓名 + 日期组合** —— 姓名 × 完整日期的交叉组合
10. **短时暴力破解** —— 小写字母 1–6 位,字母数字 1–5 位,全字符 6–7 位
## 选项参考
| 标志 | 描述 |
|------|-------------|
| `-f ` | 要破解的 PDF 文件(必填) |
| `-d ` | 字典文件 |
| `-b` | 暴力破解模式 |
| `-l ` | 暴力破解的最大密码长度(默认:4) |
| `-c ` | 自定义字符集 |
| `-t ` | CPU 线程数(默认:所有核心) |
| `-G` | 禁用 GPU 加速 |
| `-O` / `-U` | 仅破解所有者 / 用户密码(默认:两者皆破) |
| `-r` | 从检查点恢复 |
| `-F` | 按频率排序的字符集(常见字符优先) |
| `-B` | 基准测试模式:测量并报告速度,然后退出 |
| `-i` | 交互模式 —— 提示输入密码线索 |
| `--no-pot` | 不读取或写入 pot 文件 |
| `--pot-file ` | 自定义 pot 文件位置 |
| `--progress-file ` | 写入 JSON 进度,用于外部监控 |
| `--max-rounds ` | 限制 R6 KDF 轮次(加快破解速度,但可能会漏掉一些) |
| `--gpu-batch ` | 覆盖 GPU 批次大小 |
| `--json` | JSON 输出模式 |
| `--session ` | 命名会话(用作检查点前缀) |
| `--dedup` | 在规则扩展后对候选密码进行去重 |
| `--reverse` | 在字典模式下同时也尝试单词反转 |
| `--metadata-seeds` | 将 PDF 元数据词汇添加到字典中 |
| `--markov-train ` | 从字典训练 Markov 模型 |
| `--markov-output ` | 训练模型的输出路径 |
## 检查点
任何攻击模式(Ctrl+C 或网络断开)都会在 PDF 旁边保存一个检查点。使用 `-r` 恢复:
```
./pdfcrack -f document.pdf -b -l 8 -r # resume brute-force
./pdfcrack -f document.pdf -m "?u?u?d?d?d?d" -r # resume mask
./pdfcrack -f document.pdf -d words.txt -A -r # resume auto mode
```
检查点存储:攻击模式、当前位置(单词索引或暴力破解的索引+长度)、字符集、掩码模式、混合后缀、自动模式阶段,以及反转/去重标志。
## 性能
在 M4 Pro(14 核 + 20 核 GPU)、Apple Silicon Mac mini 2024 上测量。速度数据来自实际攻击运行期间的实时进度计。
| 版本 | 算法 | 最佳速度 | 引擎 |
|----------|-----------|-----------|--------|
| R2 | 40-bit RC4 | **~5.5M/s** | 14 核 NEON SIMD |
| R3 | 128-bit RC4 | **~265K/s** | GPU + 14 核 NEON |
| R4 | AES-128 | **~245K/s** | GPU + 14 核 NEON |
| R5 | AES-256/SHA-256 | **~45M/s** | Metal GPU |
| R6 | AES-256/SHA-256+KDF | **~15.6K/s** | GPU+CPU 协同 |
R2 速度快是因为 MD5 能够很好地通过 NEON 并行化,并且只有一次 RC4 处理。
R3/R4 较慢是因为 20 次 RC4 处理是串行的且受限于内存,将 NEON 4× MD5 的整体增益限制在了约 1.5 倍。
R5 在绝对意义上速度最快,因为 SHA-256 完全在片上运行,没有 CPU 的往返开销。
R6 在设计上是刻意放慢的 —— 无论硬件如何,KDF 每个候选密码都需要约 65 微秒。
### 单核与 CoreGraphics API 对比
| 版本 | 直接加密 | CoreGraphics | 提速 |
|----------|--------------|--------------|---------|
| R2 | ~960K/s | ~20K/s | **~48×** |
| R3 | ~50K/s | ~5.3K/s | **~9×** |
| R4 | ~50K/s | ~5.2K/s | **~10×** |
| R5 | ~22M/s | ~20K/s | **~1,100×** |
| R6 | ~3.3K/s | ~580/s | **~5.7×** |
### 破解时间估算(单台 M4 Pro)
**R2 @ 265K/s,62 字符字符集:**
| 长度 | 密钥空间 | 耗时 |
|--------|----------|------|
| 4 | 15M | ~57 秒 |
| 5 | 931M | ~1 小时 |
| 6 | 57.7B | ~60 小时 |
| 7 | 3.5T | ~154 天 |
**R5 @ 45M/s,62 字符字符集:**
| 长度 | 密钥空间 | 耗时 |
|--------|----------|------|
| 5 | 931M | ~21 秒 |
| 6 | 57.7B | ~21 分钟 |
| 7 | 3.5T | ~22 小时 |
| 8 | 221T | ~57 天 |
**R6 @ 15.6K/s,62 字符字符集:**
| 长度 | 密钥空间 | 耗时 |
|--------|----------|------|
| 4 | 15M | ~16 分钟 |
| 5 | 931M | ~17 小时 |
| 6 | 57.7B | ~43 天 |
有关完整的引擎对比表和详细方法论,请参见 `BENCHMARKS.md`。
## 分布式破解
对于大型密钥空间,同一网络上的多台 Mac 可以共享工作。服务器协调所有工作并在本地进行破解;客户端加入并增加计算能力。
### 安全模型
**此协议仅设计用于受信任的局域网(LAN)。**
- 工作协议未经身份验证:任何可以访问服务器端口的机器都可以注册为工作节点并接收部分密钥空间。
- 目标 PDF 文件和下载的 `client` 二进制文件均通过明文 HTTP 在网络中传输。
- 请勿将服务器端口暴露给不受信任的网络。
- **首选引导方式**:尽可能使用 `deploy.sh`(SSH 推送)而不是 `curl|bash` HTTP 拉取 —— SSH 会对二进制文件和 PDF 进行加密。
- 如果必须使用 HTTP,请在 VPN 或受信任的子网内运行会话,并使用 `--auth-token` 至少对仪表板和 API endpoint 进行访问控制。
- `join.sh` 引导脚本特意免除了 `--auth-token` 检查(它是新工作节点的未经身份验证的入口点),因此它只能部署在受信任的网络中。
### 协议
服务器↔客户端协议(`protocol.h`)是基于文本行的 TCP 协议:
```
Client → HELLO
Server → CONFIG BRUTE / CONFIG DICT
CHARSET
PDF
Client → READY
--- work loop ---
Client → GETWORK
Server → BRUTE
or DICT + word lines
or FOUND / DONE / ABORT
Client → HEARTBEAT
Server → OK / ABORT
Client → COMPLETE
or FOUND
```
工作以带有截止时间的 **租约区块** 形式分发。如果客户端断开连接或超过心跳间隔保持静默,该区块将自动重新排队。客户端会以指数退避算法重新连接,并从其上次报告的位置恢复。
### 启动分布式会话
**在作为服务器的 Mac 上:**
```
./server -f document.pdf -b -l 10 # brute-force
./server -f document.pdf -d wordlist.txt # dictionary
./server -f document.pdf -b -l 10 -p 8888 # custom port (default: 9999)
```
**从另一台 Mac 加入(拉取):**
```
curl http://:9999/join.sh | bash
```
客户端二进制文件通过 HTTP 传输并自动启动。它将安装到 `~/.pdfcracker/`。
**或者从服务器推送(需要 SSH):**
```
./deploy.sh user@other-mac.local
./deploy.sh user@mac1.local & ./deploy.sh user@mac2.local & wait # parallel
```
**重启后恢复:**
```
./server -f document.pdf -b -l 10 -R document.pdf.server.ckpt
```
每个客户端都有一个持久的 UUID(`~/.pdfcracker_id`),因此服务器能够识别重连并避免重新分发已经完成的工作。
## 测试
```
make test # all unit suites: test_all (80) + saslprep + test_crypto (6)
bash test_integration.sh # 45 end-to-end tests (R2–R6)
make fuzz-parse && ./fuzz_parse corpus # ASan/UBSan fuzz of the PDF parser
```
CI (`.github/workflows/ci.yml`) 会在每次推送时运行构建、所有单元测试套件、集成测试套件、ASan/UBSan 任务以及 Fuzzer 冒烟测试。
`test_all.c` 根据苹果的 CoreGraphics API 验证每个验证函数,并按通道将 NEON batch4 路径与标量结果进行交叉验证。`test_integration.sh` 涵盖了端到端的所有攻击模式,包括检查点(损坏处理 + 文档不匹配拒绝)、GPU↔CPU 一致性、smart 模式、分布式服务器↔客户端回环以及边缘情况。
## 支持的加密
| 版本 | 标准 | 算法 | 状态 |
|----------|----------|-----------|--------|
| R2 | PDF 1.1–1.3 | 40-bit RC4 | ✓ 直接加密 |
| R3 | PDF 1.4–1.5 | 128-bit RC4 | ✓ 直接加密 |
| R4 | PDF 1.6 | 128-bit RC4 或 AES-128 | ✓ 直接加密 |
| R5 | PDF 1.7 ext3 | AES-256 / SHA-256 | ✓ 直接加密 + GPU |
| R6 | PDF 2.0 | AES-256 / SHA-256+KDF | ✓ 直接加密 + GPU |
brute, dict, mask, rules, hybrid, PRINCE,
smart, combinator, toggle, Markov,
leet, mutate, date, fingerprint, auto"] subgraph workers ["Worker threads"] bw["brute_worker
(+ _neon variant)"] dw["dict_worker
(+ _neon variant)"] rw["rule_worker
(+ gpu variant)"] end modes --> bw modes --> dw modes --> rw bw --> counter["shared atomic g_next_idx counter"] dw --> counter rw --> counter end counter --> cpu counter --> gpu subgraph cpu ["pdf_encrypt.c — CPU"] cpuv["pdf_verify_user_password()
pdf_verify_user_batch4() — NEON 4-way
md5 / rc4 / sha256 / sha512 / aes _simd.h"] end subgraph gpu ["metal_keygen.m — GPU"] gpuv["MD5 key-derivation (R2–R4)
SHA-256 verify (R5)
Algorithm 2.B KDF (R6)
pdf_md5.metal — Metal shader"] end ``` ### 关键文件 | 文件 | 作用 | |------|------| | `pdfcrack.c` | 独立破解器:包含所有攻击模式、工作线程、进度显示与检查点 | | `pdf_encrypt.c` | PDF 加密解析器及所有加密验证(R2–R6) | | `pdf_encrypt.h` | 解析器/加密层的公共 API | | `md5_simd.h` | ARM NEON 4 路并行 MD5(仅头文件) | | `rc4_inline.h` | 替代 CommonCrypto 的内联 RC4;包含 `rc4_first_byte` 提前退出机制 | | `sha256_simd.h` | ARM NEON SHA-256 指令集(仅头文件) | | `sha512_simd.h` | ARM NEON SHA-384/512 指令集(仅头文件) | | `aes_simd.h` | ARM Crypto Extensions AES-128-CBC(仅头文件) | | `metal_keygen.m` | Objective-C Metal 流水线:MD5 (R2–R4)、SHA-256 (R5)、Algorithm 2.B (R6) | | `metal_keygen.h` | Metal 流水线公共 API | | `pdf_md5.metal` | 用于 MD5 密钥派生的 Metal GPU 计算着色器 | | `saslprep.c` | 针对用于 R5/R6 密码的 SASLprep Unicode 规范化 | | `server.c` | 分布式协调器:基于租约的工作分发 + 本地破解 | | `client.c` | 分布式工作节点:支持所有 GPU 加速 | | `protocol.h` | 用于服务器↔客户端通信的文本行 TCP 协议 | | `rules.c` / `rules.h` | 兼容 Hashcat 的规则引擎(破解器和 Fuzzer 共享) | | `pdf_gpu_types.h` | Metal 主机和着色器共享的 GPU 参数结构体 | | `fuzz_rules.c` | 针对规则引擎的 libFuzzer 测试桩(链接真实的 `rules.c`) | | `test_parse_fuzz.c` | 针对 PDF 加密解析器的 ASan/UBSan libFuzzer 测试桩 | | `test_all.c` | 单元测试套件:覆盖 8 种 PDF 变体的 80 个断言(CoreGraphics + NEON/标量交叉验证) | | `test_integration.sh` | 45 个端到端集成测试(包含分布式回环测试) | | `bench.sh` | 可重复的跨 R2–R6 各引擎基准测试 | | `.github/workflows/ci.yml` | CI:构建、单元测试 + 集成测试、ASan/UBSan、Fuzzer 冒烟测试(macOS Apple Silicon) | | `Makefile` | 构建系统;`make test` 聚合测试、`pgo` 目标、Fuzzer 目标 | ## PDF 加密原理 PDF 使用了五种不同的加密方案,每一种都比前一种更强。 ### R2 — 40-bit RC4 (PDF 1.1–1.3) 1. 使用固定的填充常量将候选密码填充至 32 字节。 2. 对拼接了文档元数据(O 值、权限、文件 ID)的填充密码进行 MD5 哈希计算。 3. 截断为 5 字节 → 加密密钥。 4. 使用该密钥对 32 字节的填充常量进行 RC4 加密。 5. 将结果与存储的 `/U` 值进行比较。 速度快:一次 MD5 + 一次 RC4 处理。按现代标准来看极其脆弱。 ### R3/R4 — 128-bit RC4 或 AES-128 (PDF 1.4–1.6) 与 R2 相同,但使用 16 字节密钥,并对密钥字节进行 **50 次额外的 MD5 迭代**,然后进行 **20 次 RC4 处理**,使用经过 XOR 修改的密钥进行最终比较。50 次 MD5 迭代和 20 次 RC4 处理是多核扩展的瓶颈。 ### R5 — AES-256 / SHA-256 (PDF 1.7 ext3) 简单:将 `SHA-256(password + validation_salt)` 与存储的哈希值进行比较。无迭代,无 RC4。对于能够并行运行数千次 SHA-256 操作的 GPU 来说速度非常快。 ### R6 — AES-256 / SHA-256 + 迭代 KDF (PDF 2.0) 刻意增加计算成本。Algorithm 2.B 运行一个由 SHA-256/384/512 + AES-CBC 操作组成的循环,其中每轮的迭代次数(64 次以上)由前一轮的哈希输出决定。每次验证大约需要 60–70 微秒,使得大规模暴力破解变得不切实际。每一轮使用的具体哈希变体(SHA-256、384 或 512)也会变化,因此需要实现全部三种算法。 ### 所有者密码与用户密码 PDF 加密存储了两个密码: - **用户密码**(R2–R4):通过加密一个已知常量并与 `/U` 比较来验证。 - **所有者密码**(R2–R4):作为独立的密钥派生(Algorithm 3)存储 —— 所有者密钥解密 `/O` 值以恢复用户密码,然后再将其与 `/U` 进行验证。这就是为什么 GPU 派生的用户密钥不能直接用于所有者密码检查的原因。 ## 加速架构 ### 引擎选择 在启动时,pdfcracker 会在实际的 PDF 上对所有三种引擎进行基准测试,并挑选出最佳组合: ``` Bench: scalar 49K/s, NEON 82K/s, GPU 87K/s (per-core) — GPU+NEON selected (1.32M/s est.) ``` | 版本 | 最佳引擎 | 原因 | |----------|-------------|-----| | R2 | NEON | 对于 40 位加密,GPU MD5 比 14×NEON 慢 | | R3/R4 | GPU + NEON(同时) | GPU 处理大批量任务;NEON 填补空隙 | | R5 | GPU | 完全在片上进行 SHA-256;CPU 无法竞争 | | R6 | GPU + CPU 协同 | 共享工作计数器;双方共同贡献力量 | ### NEON 4 路并行 MD5 (`md5_simd.h`) ARM NEON 寄存器包含 4 × 32 位通道。`md5_x4()` 同时运行四个独立的 MD5 计算——每个通道一个——在密钥派生步骤上实现比标量计算高约 4 倍的吞吐量。对于 R3/R4,由于受限于串行的 20 次 RC4 验证,其增益被限制在比 14 个标量核心整体快约 1.5 倍。 `pdf_encrypt.c` 中的 `pdf_verify_user_batch4()` / `pdf_verify_owner_batch4()` 是支持 NEON 加速的入口点。它们接受 4 个密码,运行 4 路 SIMD MD5,然后串行验证每个 RC4 结果。 ### 内联 RC4 (`rc4_inline.h`) 原始实现在每个密码上调用 CommonCrypto 的 `CCCrypt(kCCAlgorithmRC4)`,导致每个 R3/R4 候选密码需要进行约 20 次函数调用。`rc4_inline.h` 使用仅包含头文件的实现取代了它: - `rc4_encrypt()` —— 通用目的 - `rc4_encrypt_16()` —— 针对 R3/R4 内部循环的 16 字节专用版本 - `rc4_first_byte()` —— 仅计算第一个输出字节;无需运行完整的 RC4,即可瞬间拒绝约 255/256 的错误候选密码 这种提前退出机制本身在 R2 中消除了 99.6% 错误候选密码的完整 RC4 计算,并且受到保护以正确跳过所有者密码检查(GPU 派生的用户密钥对于所有者候选密码总是错误的——无论如何,检查必须到达 `pdf_verify_owner_password()`)。 ### Metal GPU 流水线 (`metal_keygen.m`, `pdf_md5.metal`) 三个独立的 Metal 流水线共享同一个 `.metallib`: | 流水线 | 用于 | GPU 任务 | CPU 任务 | |----------|----------|----------|----------| | `metal_keygen` | R2–R4 | Algorithm 2 MD5 密钥派生 | RC4 验证 | | `metal_sha256` | R5 | 完整的 Algorithm 3.2 SHA-256 验证 | 无 | | `metal_r6` | R6 | 完整的 Algorithm 2.B KDF | 溢出的候选密码 | 这三个流水线都使用 **异步双缓冲调度**:当 GPU 处理第 N 批次时,CPU 正在准备第 N+1 批次并验证第 N−1 批次。对于 R6,子批次调度会拆分每个 GPU 批次,以便 CPU 可以在批次处理期间检测到匹配并提前中止。 ### 共享工作计数器 GPU 工作线程和 CPU/NEON 工作线程竞争同一个 `g_next_idx` 原子计数器。每个 NEON 工作线程每次获取 `NEON_WORK_CHUNK` (2048) 个候选密码;GPU 每次获取 `GPU_BATCH_SIZE`(最多 262,144 个)。这消除了专门的调度线程,并允许两个引擎根据其自然吞吐量进行自调度。 ### NEON SHA-256/384/512 指令集 (`sha256_simd.h`, `sha512_simd.h`) 用于 R6 的 CPU 路径。Algorithm 2.B KDF 内部循环根据中间哈希值调用 SHA-256、SHA-384 或 SHA-512。ARM Crypto Extensions(`vsha256h_u32` 以及等效的 SHA-512 指令)在硬件中运行这些操作,使得 CPU 端的 R6 破解吞吐量比 CommonCrypto 提高约 11%。 ### NEON AES (`aes_simd.h`) AES-128-CBC 用于 R6 KDF。ARM Crypto Extensions(`vaeseq_u8`、`vaesmcq_u8`)使用直接的硬件指令取代了查表 AES。 ## 攻击模式 | 模式 | 标志 | 描述 | |------|------|-------------| | 字典 | `-d
标签:Apple Silicon, CVE监控, DOS头擦除, Metal, PDF处理, SysWhispers, 客户端加密, 密码破解, 用户模式钩子绕过, 高性能计算