MoriartyPuth-Labs/Willy-Wonka-Chocolate-Factory-Lab

GitHub: MoriartyPuth-Labs/Willy-Wonka-Chocolate-Factory-Lab

一份完整的crackme逆向工程writeup,详细记录了ChocolateFactory.exe四阶段加密验证算法的破解分析与注册机实现过程。

Stars: 0 | Forks: 0

# 🍫 ChocolateFactory.exe ### Crackme 逆向工程与注册机 — crackmes.one Chocolate Factory Banner
![Platform](https://img.shields.io/badge/crackmes.one-3a3a3a?style=for-the-badge&logo=hackthebox&logoColor=white) ![Format](https://img.shields.io/badge/PE32%2B-x86__64-0071C5?style=for-the-badge&logo=intel&logoColor=white) ![OS](https://img.shields.io/badge/Windows_64--bit-0078D4?style=for-the-badge&logo=windows11&logoColor=white) ![Type](https://img.shields.io/badge/Type-Static_Analysis-8A2BE2?style=for-the-badge) ![Anti-Debug](https://img.shields.io/badge/Anti--Debug-IsDebuggerPresent_%2B_PEB-red?style=for-the-badge) ![Flag](https://img.shields.io/badge/Golden_Ticket-Forged_🎫-2EA44F?style=for-the-badge)
### `PE32+ · x86-64 · 6 个节 · Anti-Debug · 时间门 · 4 阶段验证`
## 📌 关于 **ChocolateFactory.exe** 是一个 64 位 Windows 控制台 crackme,提示用户输入格式为 `XXXX-XXXX-XXXX-XXXX` 的 **16 位 "Golden Ticket"(金券)**。该二进制文件通过四个独立的加密检查来验证金券,每个检查都以巧克力工厂中的一个车间命名。所有四个检查都必须通过才能打印 `PASS`。 | | | |---|---| | 🎯 **目标** | `ChocolateFactory.exe` | | 👤 **作者** | CrackNotMe | | 🌐 **平台** | [crackmes.one](https://crackmes.one) | | ⚙️ **格式** | PE32+ executable (console) x86-64 | | 🛡️ **保护机制** | Anti-debug (`IsDebuggerPresent` + `PEB.NtGlobalFlag`),时间门 | | 📦 **下载** | [69b4768cf2d49d8512f649ff](https://crackmes.one/download/crackme/69b4768cf2d49d8512f649ff) | | 🔑 **密码** | `crackmes.one` | | 🎫 **Golden Ticket** | `Ch0c-M1lk-CrMe-!(L>` | ## 🗺️ 逆向流程 ``` ┌──────────────┐ ┌──────────────┐ ┌─────────────────────┐ │ file + │ │ Input Parse │ │ Anti-Debug │ │ strings │───▶│ & Guards │───▶│ Bypass Analysis │ │ (Recon) │ │ 0x140002870 │ │ (IsDebuggerPresent)│ └──────────────┘ └──────────────┘ └──────────┬──────────┘ │ ┌─────────────────────────────────────┘ │ ▼ ┌────────────────────────────────────────────────────────────┐ │ 4-Stage Validation │ │ │ │ [S-Box]──▶[Dot-Product]──▶[Hash Transform]──▶[CRC-16] │ │ Ch0c M1lk CrMe !(L> │ └──────────────────────────────┬─────────────────────────────┘ │ ▼ ┌───────────────────────┐ │ Keygen + PASS 🎫 │ │ Ch0c-M1lk-CrMe-!(L> │ └───────────────────────┘ ``` ## 🔬 技术分析 ### 1️⃣ 初始侦察 ``` # 识别二进制格式 $ file ChocolateFactory.exe PE32+ executable (console) x86-64, for MS Windows, 6 sections # 搜寻嵌入字符串 $ strings ChocolateFactory.exe | grep -i ticket Enter your Golden Ticket (16 characters, format XXXX-XXXX-XXXX-XXXX): ``` **恢复的关键字符串:** | 字符串 | 作用 | |---|---| | `HELPHELPHELPHELP` / `HELP` | 黑名单输入 | | `WONKWONKWONKWONK` | 彩蛋 — 打印提示,不参与破解 | | `Cocoa Plantation` | 验证站 1 | | `Milk River` | 验证站 2 | | `Caramel Oven` | 验证站 3 | | `Packaging Line` | 验证站 4 | | `PASS` / `FAIL` | 结果字符串 | ### 2️⃣ 输入解析与检查 所有验证逻辑位于 **`VA 0x140002870`**。在四次检查运行之前,输入会经过一系列的检查关卡进行过滤: | 检查 | 详情 | |---|---| | 🧹 **规范化** | 剔除连字符 (`0x2D`) 和空格 (`0x20`) | | 📏 **长度检查** | 剔除后的输入必须恰好为 **16 个字符** | | 🥚 **彩蛋** | `WONKWONKWONKWONK` → 打印提示,退出且不进行破解 | | 🚫 **黑名单** | `HELPHELPHELPHELP`、`HELP`、全零字符串 — 通过 `strcasecmp` 拒绝 | | ⏱️ **时间门** | `GetTickCount()` — 必须在启动后的 **120 秒**内完成破解 | 检查通过后,16 个字节被排列在内存中(相对于 `rsp`): ``` rsp+0x30..0x33 → ticket[ 0.. 3] Group 1 rsp+0x34..0x37 → ticket[ 4.. 7] Group 2 rsp+0x38..0x3B → ticket[ 8..11] Group 3 rsp+0x3C..0x3F → ticket[12..15] Group 4 ``` ### 3️⃣ 验证站 #### 🍫 验证站 1 — Cocoa Plantation `S-Box 替换` **组 1** 中的 4 个字节每一个都会在位于 `VA 0x14001B560` 的 256 字节双射 S-Box 中进行查找: ``` r14d = (r14d << 8) | LUT[ ticket[i] XOR mask ] ``` **⚠️ Anti-Debug 陷阱:** XOR 掩码派生自 `IsDebuggerPresent()` + `PEB.NtGlobalFlag`: - 正常运行 → 掩码 = `0x00`(无混淆) - 调试器下运行 → 掩码 = `0x42` → 每次查找的结果都会改变 → 检查 1 **始终失败** **目标常量:** `0xC3811DEB` 逐字节逆向 S-Box 双射: | 目标字节 | `LUT⁻¹` | ASCII | |---|---|---| | `0xC3` | 67 | `C` | | `0x81` | 104 | `h` | | `0x1D` | 48 | `0` | | `0xEB` | 99 | `c` | ``` ✅ GROUP 1 = "Ch0c" (unique valid ASCII solution) ``` #### 🥛 验证站 2 — Milk River `点积 mod 256` 使用 **SSE4.1 `PMULLD`** 求解 **ℤ/256ℤ** 上的 4 个联立线性方程: ``` 3·t4 + 7·t5 + 2·t6 + 5·t7 ≡ 0x2D (mod 256) 5·t4 + 3·t5 + 8·t6 + 1·t7 ≡ 0xDF (mod 256) 2·t4 + 9·t5 + 1·t6 + 4·t7 ≡ 0x6B (mod 256) 6·t4 + 1·t5 + 4·t6 + 7·t7 ≡ 0x9C (mod 256) ``` 位于 `VA 0x14001B660` 的系数表:`[3,7,2,5, 5,3,8,1, 2,9,1,4, 6,1,4,7]` 对可打印 ASCII 进行暴力破解得出唯一解: | 变量 | 十进制 | ASCII | |---|---|---| | t4 | 77 | `M` | | t5 | 49 | `1` | | t6 | 108 | `l` | | t7 | 107 | `k` | ``` ✅ GROUP 2 = "M1lk" (unique valid printable ASCII solution) ``` #### 🍮 验证站 3 — Caramel Oven `哈希变换` 对 **组 3** 字节进行多步 16 位变换,包含 `rotl16`、XOR 混合和字节交换: ``` # 注意:字节 8–11 以交换形式存储(rsp+0x20 处为 b10,b11) r8d = (b10 << 8) | b11 t89 = (b8 << 8) | b9 temp = (r8d - 0x3502) & 0xFFFF temp = rotl16(temp, 5) temp = (temp * 0x7A69) & 0xFFFF cx = temp edx = t89 ^ (cx >> 7) ^ cx edx2 = (edx & 0xFFFF) << 16 temp2 = (edx - 0x3F40) & 0xFFFF temp2 = rotl16(temp2, 5) temp2 = (temp2 * 0x7A69) & 0xFFFF ebx = temp2 ^ (temp2 >> 7) ^ r8d | edx2 # 目标:ebx == 0x016CB7CB ``` 对可打印 ASCII 进行暴力破解: | 变量 | 十进制 | ASCII | |---|---|---| | b8 | 67 | `C` | | b9 | 114 | `r` | | b10 | 77 | `M` | | b11 | 101 | `e` | ``` ✅ GROUP 3 = "CrMe" (unique valid printable ASCII solution) ``` #### 📦 验证站 4 — Packaging Line `CRC-16/CCITT` CRC 种子由前三组字节和的异或结果派生而来: ``` init = (sum(G1) ^ sum(G2) ^ sum(G3)) & 0xFF # = 0x0C cx = (~init) & 0xFFFF # = 0xFFF3 ``` 组 4 的每个字节都经过一步 CRC-16/CCITT 处理(多项式 `0x1021`,迭代 8 次): ``` def crc16_step(val): for _ in range(8): if val & 0x8000: val = ((val << 1) ^ 0x1021) & 0xFFFF else: val = (val << 1) & 0xFFFF return val ``` **目标:** 最终残差必须等于 `0x0000` **关键洞察:** `crc16_step(0) = 0` — 因此在处理 `G4[0..2]` 之后,中间变量 `cx2` 必须具有零低位字节。接着 `G4[3] = cx2 >> 8`,迫使最后一步处理 `0x0000`。 | 字节 | 十六进制 | ASCII | |---|---|---| | G4[0] | `0x21` | `!` | | G4[1] | `0x28` | `(` | | G4[2] | `0x4C` | `L` | | G4[3] | `0x3E` | `>` | ``` ✅ GROUP 4 = "!(L>" (~1,200+ valid solutions exist; 202 are pure alphanumeric) ``` ## ⚙️ 注册机算法 组 1–3 是**完全确定性的**(唯一的 ASCII 解)。组 4 可以从任意种子生成: ``` # Fixed groups G1 = [0x43, 0x68, 0x30, 0x63] # "Ch0c" G2 = [0x4D, 0x31, 0x6C, 0x6B] # "M1lk" G3 = [0x43, 0x72, 0x4D, 0x65] # "CrMe" def generate_g4(b12, b13): init = (sum(G1) ^ sum(G2) ^ sum(G3)) & 0xFF cx = crc16_step((~init & 0xFFFF) ^ (b12 << 8)) ax = crc16_step((b13 << 8) ^ cx) # Scan for b14 such that low byte of result == 0 for b14 in range(256): cx2 = crc16_step((b14 << 8) ^ ax) if (cx2 & 0xFF) == 0: b15 = (cx2 >> 8) & 0xFF return [b12, b13, b14, b15] # 构建最终序列号 ticket = G1 + G2 + G3 + generate_g4(0x21, 0x28) serial = f"{''.join(chr(b) for b in G1)}-{''.join(chr(b) for b in G2)}-" \ f"{''.join(chr(b) for b in G3)}-{''.join(chr(b) for b in ticket[12:])}" print(serial) # → Ch0c-M1lk-CrMe-!(L> ``` ## 🏆 Golden Ticket
``` ╔══════════════════════════════════════════════════════════╗ ║ ║ ║ Station Group Algorithm Status ║ ║ ───────────────────────────────────────────────────── ║ ║ Cocoa Plantation Ch0c S-Box 0xC3811DEB ✓ ║ ║ Milk River M1lk Dot-Product mod 256 ✓ ║ ║ Caramel Oven CrMe Hash 0x016CB7CB ✓ ║ ║ Packaging Line !(L> CRC-16 residual 0x0 ✓ ║ ║ ║ ║ Ch0c-M1lk-CrMe-!(L> ║ ║ PASS 🎫 ║ ╚══════════════════════════════════════════════════════════╝ ```
## 🧰 使用的工具 | 工具 | 用途 | |---|---| | 🔍 `objdump` | 反汇编和节映射 | | 🐍 Python 3 | 约束求解,暴力破解,注册机 | | 📐 Static Analysis | ISA 追踪,anti-debug 绕过识别 | | 🌐 `ChocolateFactory_keygen.html` | 独立的基于浏览器的注册机 | ## ⚠️ 免责声明
标签:Crackme, CTF练习, IsDebuggerPresent, Keygen, PE32+, PEB.NtGlobalFlag, TLS抓取, x86-64, 二进制分析, 云安全监控, 云安全运维, 云资产清单, 反调试绕过, 反逆向, 密码学, 恶意软件分析基础, 手动系统调用, 时间闸门, 汇编分析, 注册机, 漏洞分析, 破解入门, 破解分析, 路径探测, 软件安全, 逆向工程, 静态分析