136 lines
5.3 KiB
Markdown
136 lines
5.3 KiB
Markdown
# [种子] Unity IL2CPP 游戏逆向 → 还原元数据 + 修改逻辑
|
||
|
||
## 场景分类
|
||
游戏安全 / 移动逆向
|
||
|
||
## 目标概述
|
||
一个 Unity 打包的 Android 游戏(IL2CPP 模式),游戏内购或核心算法在 C# 编写但已编译成 native。需要还原方法名、定位关键逻辑、改动 / hook 实现修改。
|
||
|
||
## 完整执行链路
|
||
|
||
1. 拆包 APK,确认是 IL2CPP
|
||
```bash
|
||
unzip target.apk -d apk
|
||
ls apk/lib/arm64-v8a/ # 看到 libil2cpp.so 即 IL2CPP
|
||
ls apk/assets/bin/Data/Managed/Metadata/
|
||
# 关键文件: global-metadata.dat
|
||
```
|
||
2. 用 **Il2CppDumper** 还原元数据
|
||
```bash
|
||
Il2CppDumper libil2cpp.so global-metadata.dat output/
|
||
# 产物:DummyDll/ + script.json + il2cpp.h + dump.cs
|
||
```
|
||
3. 把 IDA 的 IL2CPP 脚本(`ida_with_struct.py`)跑一遍
|
||
- 加载 libil2cpp.so → File → Script File → 选 ida_with_struct.py → 选 script.json
|
||
- IDA 现在能看到 C# 方法名、签名、字符串
|
||
4. 在 dump.cs 里按业务关键字搜(`AddCoin` / `OnPurchase` / `Verify` / `IsVip` / `CheckSign`)
|
||
5. 拿到关键方法的偏移 → IDA 跳过去看反汇编 / 反编译
|
||
6. 选择修改方式:
|
||
- **静态 patch**:直接 IDA 把判断改成 `mov w0, #1; ret`
|
||
- **动态 hook**:Frida 接 il2cpp 方法(用 Frida-Il2CppBridge)
|
||
7. 重打包验证 / 注入验证
|
||
|
||
## 踩坑记录
|
||
|
||
| 问题 | 原因 | 解决方案 | 耗时 |
|
||
|------|------|---------|------|
|
||
| Il2CppDumper 报 metadata 版本不支持 | 新版 Unity 改了 metadata 格式 | 升级 Il2CppDumper 到最新 / 用 Il2CppInspectorRedux 替代 | 30min |
|
||
| global-metadata.dat 加密了 | 用了 AntiCheatToolkit / 自定义加密 | 找游戏初始化时的解密函数(通常在 il2cpp_init 周围)→ Frida 在 mmap 后 dump | 2h |
|
||
| dump.cs 看到方法名但 IDA 没匹配 | script.json 与 so 不一致 | 必须用同一次 dump 的产物;换 IDA 时清缓存 | 20min |
|
||
| Frida hook IL2CPP 方法报错 | IL2CPP 方法不是标准 Java/ObjC,要算 method offset | 用 frida-il2cpp-bridge 库,不要硬写 Interceptor.attach | 1h |
|
||
| Patch 后游戏闪退 | 校验文件 hash 或 anti-tamper | 找 hash 校验逻辑也 patch 掉,或用 hook 不改文件 | 2h |
|
||
| 重打包后启动崩溃 | apksigner v2 签名不能改字节后再签 | 删 META-INF + apktool b + apksigner sign 一气 | 30min |
|
||
|
||
## 工具链发现
|
||
|
||
- **Il2CppDumper** 老牌但仍是默认选择
|
||
- **Il2CppInspectorRedux** 更现代,支持新 Unity,能输出 IDA / Ghidra / Binary Ninja 多种插件脚本
|
||
- **frida-il2cpp-bridge** 是 IL2CPP 上 hook 的事实标准,比裸 Frida 强 N 倍
|
||
- **DnSpy** / **dnSpyEx** 用于看 DummyDll(dump 出来的伪 .NET assembly)
|
||
- **UnityCheat** 系列辅助工具(GameGuardian 系不展开)
|
||
|
||
## 关键代码/命令
|
||
|
||
frida-il2cpp-bridge hook 示例:
|
||
|
||
```typescript
|
||
// hook.ts
|
||
import "frida-il2cpp-bridge";
|
||
|
||
Il2Cpp.perform(() => {
|
||
const Assembly = Il2Cpp.domain.assembly("Assembly-CSharp").image;
|
||
|
||
// hook static method
|
||
const PlayerData = Assembly.class("PlayerData");
|
||
PlayerData.method("AddCoin").implementation = function (n: number) {
|
||
console.log("[+] AddCoin called with:", n);
|
||
return this.method("AddCoin").invoke(99999); // 改成 99999
|
||
};
|
||
|
||
// hook instance method
|
||
const Purchase = Assembly.class("Purchase");
|
||
Purchase.method("VerifyReceipt").implementation = function () {
|
||
console.log("[+] VerifyReceipt → always true");
|
||
return true;
|
||
};
|
||
});
|
||
```
|
||
|
||
```bash
|
||
# 编译 + 注入
|
||
npm install frida-il2cpp-bridge
|
||
frida-compile hook.ts -o hook.js
|
||
frida -U -f com.target.game -l hook.js --no-pause
|
||
```
|
||
|
||
IDA 静态 patch:
|
||
|
||
```text
|
||
1. 打开 libil2cpp.so,跑 il2cpp_load_metadata.py
|
||
2. 跳到 dump.cs 中 IsPurchaseValid 对应的偏移
|
||
3. 函数开头改成 MOV W0, #1; RET(ARM64)
|
||
4. Apply Patches → Save → 替换回 APK → 重签名
|
||
```
|
||
|
||
## 对本包的改进建议
|
||
|
||
- `reverse-engineering/SKILL.md` 已覆盖 Unity,但缺 IL2CPP **完整工作链** 案例
|
||
- `reverse-engineering/references/il2cpp-cheatsheet.md` 单独成文:dump 工具对比、frida-bridge 模板、加密 metadata 处理
|
||
- bootstrap manifest 增加 frida-il2cpp-bridge
|
||
|
||
## 可复用的模式/脚本片段
|
||
|
||
**IL2CPP 标准流程**:
|
||
|
||
```text
|
||
1. 确认 IL2CPP(看 lib/abi 下有无 libil2cpp.so)
|
||
2. 找到 metadata(assets/bin/Data/Managed/Metadata/global-metadata.dat 或被加密)
|
||
3. Il2CppDumper / Inspector 还原
|
||
4. IDA + 脚本带回元信息
|
||
5. dump.cs 搜业务关键词
|
||
6. 选择 patch 还是 hook
|
||
7. 验证(启动 + 实际场景)
|
||
```
|
||
|
||
**加密 metadata 处理**:
|
||
|
||
```text
|
||
1. Frida 在 fopen/open 系调用上挂钩,看谁读 global-metadata.dat
|
||
2. 在 mmap/read 后 dump 内存里已解密的元数据
|
||
3. 把 dump 出来的内存当 metadata 喂给 Il2CppDumper
|
||
```
|
||
|
||
## 进化动作
|
||
- [ ] reverse-engineering/references 增加 il2cpp 完整章节
|
||
- [ ] bootstrap-manifest 加入 frida-il2cpp-bridge / Il2CppInspectorRedux
|
||
- [x] 路由矩阵已含 Unity / IL2CPP
|
||
|
||
## 环境信息
|
||
- Windows / macOS(运行 Il2CppDumper 用),目标设备 Android arm64
|
||
- IDA Pro 7.7+ 或 Ghidra 11+
|
||
- frida-tools 16.x, frida-il2cpp-bridge 0.9+
|
||
- Unity 版本: 2019.x - 2022.x(不同版本 metadata 格式略异)
|
||
|
||
## 脱敏要求
|
||
本条目为种子数据,基于公开技术模式编写,不涉及任何真实游戏。包名 `com.target.game` 为占位符。
|