GKLBB

当你经历了暴风雨,你也就成为了暴风雨

导航

将IL2CPP APK反编译为Unity工程的详细指南

 

⚠️ 重要声明:完全恢复原始Unity工程是不可能的,只能尽量还原代码逻辑和资源。

📋 整体流程图

text
APK文件
    ├─► 1. 解包APK
    │       │
    │       ├─► assets/bin/Data/        (Unity资源)
    │       ├─► lib/arm64-v8a/libil2cpp.so  (编译后的代码)
    │       └─► assets/bin/Data/Managed/Metadata/global-metadata.dat (元数据)
    ├─► 2. 提取资源 (AssetStudio)
    │       │
    │       └─► 贴图、模型、音频、动画、场景等
    ├─► 3. 反编译代码 (Il2CppDumper + Cpp2IL)
    │       │
    │       └─► C#伪代码 / DLL
    └─► 4. 手动重建Unity工程

🛠️ 所需工具

工具用途下载链接
APKTool 解包APK https://ibotpeaches.github.io/Apktool/
7-Zip 解压文件 https://7-zip.org/
Il2CppDumper 提取IL2CPP元数据 https://github.com/Perfare/Il2CppDumper
Cpp2IL 重建IL代码 https://github.com/SamboyCoding/Cpp2IL
AssetStudio 提取Unity资源 https://github.com/Perfare/AssetStudio
UABE 编辑Unity资源 https://github.com/SeriousCache/UABE
dnSpy 查看C#代码 https://github.com/dnSpy/dnSpy
IDA Pro/Ghidra 分析二进制代码 https://ghidra-sre.org/

📝 详细步骤

第一步:解包APK

Bash
# 方法1:使用APKTool
apktool d game.apk -o output_folder

# 方法2:直接用7-Zip解压(将.apk改为.zip)
7z x game.apk -o"output_folder"

解包后的关键文件:

text
output_folder/
├── lib/
│   ├── arm64-v8a/
│   │   └── libil2cpp.so          # 64位编译代码 ⭐重要
│   └── armeabi-v7a/
│       └── libil2cpp.so          # 32位编译代码
├── assets/
│   └── bin/
│       └── Data/
│           ├── Managed/
│           │   └── Metadata/
│           │       └── global-metadata.dat  # IL2CPP元数据 ⭐重要
│           ├── level0            # 场景文件
│           ├── level1
│           ├── resources.assets  # 资源文件
│           ├── sharedassets0.assets
│           └── ...

第二步:使用Il2CppDumper提取代码结构

Bash
# 运行Il2CppDumper
Il2CppDumper.exe libil2cpp.so global-metadata.dat output_dir

输出文件:

text
output_dir/
├── dump.cs                # 所有类、方法、字段的C#定义 ⭐
├── script.json            # 用于IDA/Ghidra的脚本数据
├── stringliteral.json     # 字符串常量
├── DummyDll/              # 空壳DLL文件
│   ├── Assembly-CSharp.dll
│   ├── UnityEngine.dll
│   └── ...
└── il2cpp.h               # C++头文件

dump.cs 示例内容:

csharp
// Namespace: 
public class BossClawAi : MonoBehaviour
{
    // Fields
    public Vector3 _homePosition; // 0x18
    public Vector2 patrolXz; // 0x24
    public float patrolFrequency; // 0x2C
    public NavMeshAgent _navAgent; // 0x30
    
    // Methods
    // RVA: 0x4EB1A0 Offset: 0x4E99A0 VA: 0x4EB1A0
    private void AiTick() { }
    
    // RVA: 0x4EB8C0 Offset: 0x4EA0C0 VA: 0x4EB8C0
    public void SetActive() { }
}

📌 注意:这只给出了类结构,方法体是空的!


第三步:使用Cpp2IL重建IL代码

Bash
# 基本用法
Cpp2IL --game-path "path/to/extracted/apk" --experimental-enable-il-to-assembly-please

# Android APK专用命令
Cpp2IL --input-as "lib/arm64-v8a/libil2cpp.so" --metadata-path "assets/bin/Data/Managed/Metadata/global-metadata.dat" --experimental-enable-il-to-assembly-please

更详细的命令:

Bash
Cpp2IL.exe ^
  --input-as "libil2cpp.so" ^
  --metadata-path "global-metadata.dat" ^
  --unity-version "2021.3.1" ^
  --experimental-enable-il-to-assembly-please ^
  --output-as "dummydll" ^
  --output-to "./cpp2il_output"

输出:

text
cpp2il_output/
└── DummyDll/
    ├── Assembly-CSharp.dll    # 包含反编译的代码
    ├── UnityEngine.CoreModule.dll
    └── ...

第四步:用dnSpy查看反编译的代码

  1. 打开 dnSpy
  2. 拖入 Assembly-CSharp.dll
  3. 浏览代码

可能看到的结果:

✅ 成功反编译的方法:

csharp
public void SetActive()
{
    this._isActive = true;
    this._lastAiTickTime = Time.time;
    this.SwitchMentalState(MentalState.Patrol);
}

❌ 失败的方法:

csharp
private void AiTick()
{
    throw new AnalysisFailedException("CPP2IL failed to recover any usable IL for this method.");
}

第五步:用IDA/Ghidra分析未能反编译的代码

对于Cpp2IL无法恢复的方法,需要手动分析汇编:

Bash
# 1. 打开Ghidra,创建新项目
# 2. 导入libil2cpp.so
# 3. 运行Il2CppDumper生成的ghidra脚本来重命名函数

在Ghidra中:

text
1. File → Import File → 选择 libil2cpp.so
2. 选择语言: ARM:LE:64:v8A (或 ARM:LE:32:v7 for 32位)
3. 分析完成后: Window → Script Manager
4. 运行 ghidra_with_struct.py (Il2CppDumper生成的)

手动分析汇编示例:

assembly
; BossClawAi.AiTick() at 0x4EB1A0
sub_4EB1A0:
    stp     x29, x30, [sp, #-0x10]!
    mov     x29, sp
    ldr     x8, [x0, #0x18]      ; 加载 _homePosition
    bl      Random_get_value      ; 调用 Random.value
    fmul    s0, s0, s1           ; 乘法运算
    ; ... 继续分析

第六步:提取Unity资源

使用AssetStudio:

  1. 打开AssetStudio
  2. File → Load Folder → 选择 assets/bin/Data/
  3. 等待加载完成
  4. 在Asset List中查看所有资源

可提取的资源类型:

text
├── Texture2D        → .png, .jpg
├── Sprite           → .png
├── AudioClip        → .wav, .ogg
├── Mesh             → .obj, .fbx
├── AnimationClip    → .anim
├── TextAsset        → .txt, .json, .xml
├── Shader           → .shader (通常无法完全恢复)
├── Material         → 部分信息
├── MonoBehaviour    → 序列化数据
└── GameObject/Scene → 层级结构

导出资源:

text
1. 选择要导出的资源
2. Export → Selected assets
3. 选择导出格式和目录

第七步:重建Unity工程

这是最困难的部分,需要手动完成:

text
1. 创建新Unity项目(匹配原版本)
   
2. 导入提取的资源
   Assets/
   ├── Textures/
   ├── Models/
   ├── Audio/
   ├── Animations/
   └── ...

3. 根据反编译的代码重写脚本
   Assets/
   └── Scripts/
       ├── BossClawAi.cs
       ├── PlayerController.cs
       └── ...

4. 重建场景
   - 使用AssetStudio查看场景层级
   - 手动在Unity中重建GameObject结构

5. 重建预制体(Prefab)

6. 配置项目设置
   - Player Settings
   - Quality Settings
   - 等

🔧 实用脚本和命令

一键处理脚本 (Windows Batch)

batch
@echo off
set APK_PATH=game.apk
set OUTPUT=output

echo [1/4] 解压APK...
7z x %APK_PATH% -o"%OUTPUT%\apk_extracted"

echo [2/4] 运行Il2CppDumper...
Il2CppDumper.exe ^
  "%OUTPUT%\apk_extracted\lib\arm64-v8a\libil2cpp.so" ^
  "%OUTPUT%\apk_extracted\assets\bin\Data\Managed\Metadata\global-metadata.dat" ^
  "%OUTPUT%\il2cpp_dump"

echo [3/4] 运行Cpp2IL...
Cpp2IL.exe ^
  --input-as "%OUTPUT%\apk_extracted\lib\arm64-v8a\libil2cpp.so" ^
  --metadata-path "%OUTPUT%\apk_extracted\assets\bin\Data\Managed\Metadata\global-metadata.dat" ^
  --experimental-enable-il-to-assembly-please ^
  --output-to "%OUTPUT%\cpp2il_output"

echo [4/4] 完成!
echo - 代码结构: %OUTPUT%\il2cpp_dump\dump.cs
echo - 反编译DLL: %OUTPUT%\cpp2il_output\DummyDll\
pause

Python辅助脚本(解析dump.cs)

Python
import re
import os

def parse_dump_cs(dump_path, output_dir):
    """将dump.cs分割成单独的类文件"""
    
    with open(dump_path, 'r', encoding='utf-8') as f:
        content = f.read()
    
    # 匹配类定义
    pattern = r'(// Namespace: .*?\n)?public class (\w+).*?^}'
    matches = re.findall(pattern, content, re.MULTILINE | re.DOTALL)
    
    os.makedirs(output_dir, exist_ok=True)
    
    for namespace, class_name, class_body in matches:
        file_path = os.path.join(output_dir, f"{class_name}.cs")
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(f"// Auto-generated from dump.cs\n")
            f.write(f"using UnityEngine;\n\n")
            if namespace:
                f.write(namespace)
            f.write(f"public class {class_name}\n{{\n{class_body}\n}}")
        print(f"Created: {file_path}")

# 使用
parse_dump_cs("dump.cs", "output_scripts")

⚠️ 常见问题和解决方案

问题1:Il2CppDumper报错 "Metadata version not supported"

Bash
# 解决:使用最新版Il2CppDumper,或尝试不同版本
# 或手动指定Unity版本
Il2CppDumper.exe libil2cpp.so global-metadata.dat output --unity-version 2021.3

问题2:Cpp2IL成功率很低

Bash
# 尝试不同选项
Cpp2IL.exe \
  --input-as libil2cpp.so \
  --metadata-path global-metadata.dat \
  --use-processor attributeinjector \
  --output-as isil

问题3:找不到global-metadata.dat

text
可能的位置:
- assets/bin/Data/Managed/Metadata/global-metadata.dat
- assets/Managed/Metadata/global-metadata.dat
- 有时会被加密或混淆

问题4:libil2cpp.so被加密

一些游戏会加密libil2cpp.so,需要:

  1. 使用Frida在运行时dump解密后的so
  2. 分析加密算法并解密
JavaScript
// Frida脚本示例 - dump解密后的libil2cpp.so
Java.perform(function() {
    var System = Java.use("java.lang.System");
    System.loadLibrary.implementation = function(libName) {
        console.log("Loading: " + libName);
        this.loadLibrary(libName);
        
        if(libName.includes("il2cpp")) {
            // Dump memory
            var module = Process.findModuleByName("libil2cpp.so");
            // ... dump logic
        }
    };
});

📊 能恢复多少?

内容恢复程度说明
类/方法/字段名称 ✅ 100% 元数据完整保留
方法实现代码 ⚠️ 30-70% 取决于Cpp2IL成功率
资源文件 ✅ 90%+ 大部分可完整提取
场景结构 ⚠️ 50-70% 可查看,需手动重建
Shader代码 ❌ ~10% 编译后难以恢复
项目设置 ❌ 很少 需要手动配置
注释/原始格式 ❌ 0% 完全丢失

📚 推荐学习资源

  1. Il2CppDumper Wiki: https://github.com/Perfare/Il2CppDumper/wiki
  2. Cpp2IL文档: https://github.com/SamboyCoding/Cpp2IL/wiki
  3. Unity逆向教程: https://katyscode.wordpress.com/
  4. ARM汇编学习: https://azeria-labs.com/writing-arm-assembly-part-1/

如果需要更详细地了解某个具体步骤,请告诉我!

 
 

posted on 2026-01-09 02:59  GKLBB  阅读(1319)  评论(1)    收藏  举报