rev-u3d-dump
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineserev-u3d-dump - Unity IL2CPP Symbol Dumper
rev-u3d-dump - Unity IL2CPP符号导出工具
Extract C# method names, addresses, and type definitions from Unity IL2CPP builds for IDA/Ghidra analysis.
从Unity IL2CPP构建包中提取C#方法名、地址及类型定义,用于IDA/Ghidra分析。
Overview
概述
Unity IL2CPP compiles C# to native code. The original class/method names are stripped from the binary but preserved in . This skill recovers the mapping between native function addresses and their original C# names.
global-metadata.datUnity IL2CPP会将C#代码编译为原生代码。二进制文件中会剥离原始的类/方法名,但这些信息会保留在中。本技能可恢复原生函数地址与其原始C#名称之间的映射关系。
global-metadata.datKey Files in Unity Build
Unity构建包中的关键文件
| File | Location | Purpose |
|---|---|---|
| Native binary | iOS: | Compiled C# code (Mach-O / ELF) |
| Metadata | | All type/method/string info |
| 文件 | 位置 | 用途 |
|---|---|---|
| 原生二进制文件 | iOS: | 编译后的C#代码(Mach-O / ELF格式) |
| 元数据 | | 包含所有类型、方法、字符串信息 |
Tool Selection
工具选择
Il2CppDumper (recommended for metadata v39+)
Il2CppDumper(推荐用于元数据v39+版本)
Use the v39 fork for Unity 6+ builds:
- Repo: (branch:
https://github.com/roytu/Il2CppDumper)v39 - Supports metadata v24–v39
- Outputs with function addresses — ready for IDA/Ghidra import
script.json
The original Il2CppDumper () only supports up to v29.
https://github.com/Perfare/Il2CppDumper针对Unity 6+构建包,请使用v39分支:
- 仓库地址: (分支:
https://github.com/roytu/Il2CppDumper)v39 - 支持元数据v24–v39版本
- 输出包含函数地址的文件,可直接导入IDA/Ghidra
script.json
原版Il2CppDumper()仅支持最高v29版本。
https://github.com/Perfare/Il2CppDumperCpp2IL (alternative)
Cpp2IL(替代工具)
- Repo:
https://github.com/SamboyCoding/Cpp2IL - Supports metadata v39, but dummy DLLs lack attributes
[Address] - Useful for C# source reconstruction, not ideal for IDA import
- 仓库地址:
https://github.com/SamboyCoding/Cpp2IL - 支持元数据v39版本,但生成的虚拟DLL缺少属性
[Address] - 适用于C#源代码还原,但不适合导入IDA
Step-by-Step Workflow
分步操作流程
Step 1: Locate IL2CPP Files
步骤1:定位IL2CPP文件
iOS (IPA):
bash
undefinediOS(IPA包):
bash
undefinedUnzip IPA
解压IPA包
unzip -o app.ipa -d .
unzip -o app.ipa -d .
Binary
二进制文件路径
BINARY="Payload/<AppName>.app/Frameworks/UnityFramework.framework/UnityFramework"
BINARY="Payload/<AppName>.app/Frameworks/UnityFramework.framework/UnityFramework"
Metadata
元数据文件路径
METADATA="Payload/<AppName>.app/Data/Managed/Metadata/global-metadata.dat"
**Android (APK):**
```bashMETADATA="Payload/<AppName>.app/Data/Managed/Metadata/global-metadata.dat"
**Android(APK包):**
```bashUnzip APK
解压APK包
unzip -o app.apk -d .
unzip -o app.apk -d .
Binary (pick target arch)
二进制文件路径(选择目标架构)
BINARY="lib/arm64-v8a/libil2cpp.so"
BINARY="lib/arm64-v8a/libil2cpp.so"
Metadata
元数据文件路径
METADATA="assets/bin/Data/Managed/Metadata/global-metadata.dat"
undefinedMETADATA="assets/bin/Data/Managed/Metadata/global-metadata.dat"
undefinedStep 2: Check Metadata Version
步骤2:检查元数据版本
bash
undefinedbash
undefinedFirst 8 bytes: magic (4) + version (4), little-endian
前8字节:魔数(4字节) + 版本(4字节),小端序
xxd -l 8 "$METADATA"
xxd -l 8 "$METADATA"
Expected: af1b b1fa 2700 0000 → magic OK, version = 0x27 = 39
示例输出:af1b b1fa 2700 0000 → 魔数验证通过,版本 = 0x27 = 39
| Version | Unity | Tool |
|---------|-------|------|
| ≤ 29 | Unity 2021 and earlier | Original Il2CppDumper |
| 31 | Unity 2022 | Original Il2CppDumper (partial) |
| 39 | Unity 6 (6000.x) | **roytu/Il2CppDumper v39 fork** |
| 版本 | 对应Unity版本 | 推荐工具 |
|---------|-------|------|
| ≤ 29 | Unity 2021及更早版本 | 原版Il2CppDumper |
| 31 | Unity 2022 | 原版Il2CppDumper(部分支持) |
| 39 | Unity 6 (6000.x) | **roytu/Il2CppDumper v39分支** |Step 3: Build & Run Il2CppDumper (v39 fork)
步骤3:构建并运行Il2CppDumper(v39分支)
bash
undefinedbash
undefinedClone v39 fork
克隆v39分支代码
git clone -b v39 https://github.com/roytu/Il2CppDumper.git
git clone -b v39 https://github.com/roytu/Il2CppDumper.git
Build
构建项目
cd Il2CppDumper
DOTNET_ROLL_FORWARD=LatestMajor dotnet build -c Release
cd Il2CppDumper
DOTNET_ROLL_FORWARD=LatestMajor dotnet build -c Release
Run (use net8.0 framework)
运行工具(使用net8.0框架)
DOTNET_ROLL_FORWARD=LatestMajor dotnet run
--project Il2CppDumper/Il2CppDumper.csproj
-c Release --framework net8.0
-- "$BINARY" "$METADATA" output_dir
--project Il2CppDumper/Il2CppDumper.csproj
-c Release --framework net8.0
-- "$BINARY" "$METADATA" output_dir
**Notes:**
- `DOTNET_ROLL_FORWARD=LatestMajor` allows running on .NET 9/10 even though the project targets .NET 6/8
- Exit code 134 is normal in non-interactive mode (caused by `Console.ReadKey()` at the end)
- On macOS, if the binary gets SIGKILL'd, ad-hoc sign it: `codesign -s - <binary>`DOTNET_ROLL_FORWARD=LatestMajor dotnet run
--project Il2CppDumper/Il2CppDumper.csproj
-c Release --framework net8.0
-- "$BINARY" "$METADATA" output_dir
--project Il2CppDumper/Il2CppDumper.csproj
-c Release --framework net8.0
-- "$BINARY" "$METADATA" output_dir
**注意事项:**
- `DOTNET_ROLL_FORWARD=LatestMajor` 参数允许在.NET 9/10环境中运行,即使项目目标框架是.NET 6/8
- 非交互式模式下退出码134为正常现象(由末尾的`Console.ReadKey()`导致)
- 在macOS上,如果二进制文件被SIGKILL终止,可进行临时签名:`codesign -s - <binary>`Step 4: Verify Output
步骤4:验证输出结果
Successful run produces these files in the output directory:
| File | Size (typical) | Purpose |
|---|---|---|
| 50–100 MB | Function addresses + names + signatures (IDA/Ghidra import) |
| 10–30 MB | C# class dump with RVA/VA addresses |
| 50–100 MB | C struct definitions for type import |
| ~2 KB | IDA Python import script |
Check format:
script.jsonjson
{
"ScriptMethod": [
{
"Address": 40865744,
"Name": "ClassName$$MethodName",
"Signature": "ReturnType ClassName__MethodName (args...);",
"TypeSignature": "viii"
}
]
}Check format:
dump.cscsharp
// RVA: 0x1A2B3C4 Offset: 0x1A2B3C4 VA: 0x1A2B3C4
public void MethodName() { }运行成功后,输出目录中会生成以下文件:
| 文件 | 典型大小 | 用途 |
|---|---|---|
| 50–100 MB | 包含函数地址、名称、签名(用于导入IDA/Ghidra) |
| 10–30 MB | 包含RVA/VA地址的C#类导出文件 |
| 50–100 MB | 用于类型导入的C结构体定义 |
| ~2 KB | IDA Python导入脚本 |
检查格式:
script.jsonjson
{
"ScriptMethod": [
{
"Address": 40865744,
"Name": "ClassName$$MethodName",
"Signature": "ReturnType ClassName__MethodName (args...);",
"TypeSignature": "viii"
}
]
}检查格式:
dump.cscsharp
// RVA: 0x1A2B3C4 Offset: 0x1A2B3C4 VA: 0x1A2B3C4
public void MethodName() { }Step 5: Import into IDA
步骤5:导入至IDA
- Open the native binary in IDA (UnityFramework / libil2cpp.so)
- Place and
script.jsonin the same directoryida_py3.py - → select
File → Script file...ida_py3.py - The script reads and renames all functions automatically
script.json - Optional: → select
File → Load file → Parse C header file...for struct typesil2cpp.h
- 在IDA中打开原生二进制文件(UnityFramework / libil2cpp.so)
- 将和
script.json放在同一目录下ida_py3.py - 点击→ 选择
文件 → 脚本文件...ida_py3.py - 脚本会读取并自动重命名所有函数
script.json - 可选操作:→ 选择
文件 → 加载文件 → 解析C头文件...导入结构体类型il2cpp.h
Step 5 (alt): Import into Ghidra
步骤5(替代方案):导入至Ghidra
- Open the binary in Ghidra
- Use the or
ghidra.pyscript from Il2CppDumperghidra_with_struct.py - with
Window → Script Manager → Runin the same directoryscript.json
- 在Ghidra中打开二进制文件
- 使用Il2CppDumper提供的或
ghidra.py脚本ghidra_with_struct.py - 点击,确保
窗口 → 脚本管理器 → 运行在同一目录下script.json
Troubleshooting
故障排除
| Error | Cause | Fix |
|---|---|---|
| Using original Il2CppDumper | Switch to roytu/Il2CppDumper v39 fork |
| Exit code 137 (SIGKILL) | macOS unsigned binary | |
| Non-interactive console | Ignore — dump completed successfully |
| .NET version mismatch | Set |
| Empty output | Wrong binary/metadata pair | Verify both files are from the same build |
| 错误 | 原因 | 解决方法 |
|---|---|---|
| 使用了原版Il2CppDumper | 切换至roytu/Il2CppDumper v39分支 |
| 退出码137(SIGKILL) | macOS下二进制文件未签名 | 执行 |
| 非交互式控制台环境 | 可忽略该错误,导出操作已成功完成 |
| .NET版本不匹配 | 设置环境变量 |
| 输出内容为空 | 二进制文件与元数据文件不匹配 | 验证两个文件是否来自同一构建包 |
Output Usage Tips
输出文件使用技巧
- is the quickest reference — search for class/method names with RVA addresses
dump.cs - Address values are decimal — convert to hex for IDA:
script.json→hex(40865744)0x26F8FD0 - Field offsets in (e.g.,
dump.cs) are relative to object base, useful for memory inspection with Frida// 0x20
- 是最快捷的参考文件——可搜索带有RVA/VA地址的类/方法名
dump.cs - 中的Address值为十进制,需转换为十六进制后在IDA中使用:
script.json→hex(40865744)0x26F8FD0 - 中的字段偏移(如
dump.cs)是相对于对象基地址的偏移量,可结合Frida用于内存检查// 0x20