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
     
     
### `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, 二进制分析, 云安全监控, 云安全运维, 云资产清单, 反调试绕过, 反逆向, 密码学, 恶意软件分析基础, 手动系统调用, 时间闸门, 汇编分析, 注册机, 漏洞分析, 破解入门, 破解分析, 路径探测, 软件安全, 逆向工程, 静态分析