muhammadrizwan87/il2cppdumper

GitHub: muhammadrizwan87/il2cppdumper

一款无需 root 的 Android IL2CPP 运行时 dumper,直接在目标进程内从内存中提取 Unity IL2CPP 应用的类、方法和字段信息并生成 dump.cs。

Stars: 12 | Forks: 3

# Il2Cpp Self‑Dumper ## 📖 概述 **一个**无需 Zygisk、无需 root** 的 il2cpp 运行时 dumper,它直接**在目标进程内部**运行。通过 `system.loadlibrary()` 加载后,它会自动查找 `libil2cpp.so`,解析所有 Unity il2cpp API,并将 `dump.cs` 写入应用自身的文件目录。** *直接从运行中的 IL2CPP 运行时内存中,提取每种托管类型(类、结构体、枚举、接口)的类 C# 伪源码,以及字段偏移量和方法地址。* ## 📋 目录 1. [特殊优势](#-1-special-advantages) 1.1 [支持加密 Metadata](#-encrypted-metadata-support) 1.2 [容器 / 虚拟机原生支持](#-container--vm-native-support) 1.3 [防崩溃安全操作](#-crash-safe-operation) 1.4 [对应用行为零影响](#-zero-impact-on-app-behaviour) 1.5 [多策略枚举](#-multi-strategy-enumeration) 2. [局限性](#-2-limitations) 3. [安全性视角](#%EF%B8%8F-3-security-perspective) 3.1 [本库可以访问的内容](#-what-this-library-can-access) 3.2 [本库不会执行的操作](#-what-this-library-does-not-do) 3.3 [政策合规性](#%EF%B8%8F-policy-compliance) 4. [输出位置与回退顺序](#-4-output-locations--fallback-order) 5. [自定义输出路径](#-5-customising-the-output-path) 6. [使用指南](#-6-usage-guide) 6.1 [前置条件](#-prerequisites) 6.2 [构建说明](#%EF%B8%8F-build-instructions) 6.3 [集成说明](#-implementation-instructions) 7. [致谢](#-7-acknowledgments) ## 🚀 1. 特殊优势 ### ✅ 支持加密 Metadata 本库**不会解密任何内容**。它会等待 IL2CPP 自身将解密后的 metadata 加载到内存中,然后再 dump 活动状态。适用于任何加密方案——无需提取密钥,无需解析文件。 ### ✅ 容器 / 虚拟机原生支持 ### ✅ 防崩溃安全操作 所有 IL2CPP 调用都在备用栈上使用信号处理程序(`SIGSEGV`/`SIGBUS`)进行了包装。如果函数指针有误,崩溃将被捕获并记录,dump 线程会干净地退出——宿主应用绝不会崩溃。 ### ✅ 对应用行为零影响 - ❎ 无方法 Hook - ❎ 无字节码修改 - 🧵 dump 线程以默认的 `SCHED_OTHER` 优先级分离运行 - ❄️ 所有轮询循环均使用 `sleep(1)`——无 CPU 忙等待,不耗电 - 😑 本库作为被动观察者加载,游戏的 FPS、网络和 UI 均不受影响 ### ✅ 多策略枚举 dumper 会自动尝试三种枚举方法,如果一种不可用,则会优雅地失败并回退到下一种: 1. **基于 Image** – `il2cpp_image_get_class`(快速,结构良好) 2. **基于回调** – `il2cpp_class_for_each`(较新的 IL2CPP 构建版本) 3. **基于反射** – `Assembly.Load` + `GetTypes()`(即使在被剥离/混淆的构建版本上也能保证工作,但速度较慢) 这保证了在从 Unity 2017.4 到最新的 6000.x 版本上都能成功 dump。 ## ⛔ 2. 局限性 - **泛型类型参数显示**:泛型类显示为 `List\`1` 而不是 `List`。完整的实例化细节需要解析 `Il2CppGenericInst`,该功能已计划但尚未实现。 - **XOR/自定义加密的运行时符号**:如果内存中的 `methodPointer` 值被混淆(不仅仅是 metadata 文件被混淆),RVA/VA 注释将显示错误的地址。 - **2017.1 之前的 Unity 版本**:非常旧的 IL2CPP ABI 可能具有不同的结构体布局;在这种情况下,本库会尽最大努力生成部分 dump。 - **反混淆**:dumper **不会**重命名符号、解密字符串或恢复控制流。它输出的完全是引擎所看到的原始 metadata。 ## 🛡️ 3. 安全性视角 ### 🔑 本库可以访问的内容 本库**完全在目标进程现有的安全边界内**运作。它: - ✅ 读取 `/proc/self/maps` 和 `/proc/self/cmdline` — 根据系统设计,每个进程均可访问 - ✅ 读取进程自身映射的内存 — 因为它就在进程内部 - ✅ 写入应用自身的文件目录 — 使用的是进程已经拥有的存储空间 - ✅ 使用应用自身的 `JavaVM` 进行 JNI 调用 — 标准 Android API **未发出任何应用自身无法进行的系统调用。** ### ❎ 本库不会执行的操作 - ❌ 不提升权限 - ❌ 不通过网络进行通信 - ❌ 不访问其他应用的数据 - ❌ 不修改**任何**内存(无 Hook、无补丁、无代码注入) - ❌ 在进程退出后不进行任何驻留 - ❌ 不请求额外的 Android 权限 ### 🏛️ 政策合规性 由于本库是在应用的 UID 下作为应用自身进程的一部分加载的,因此它完全在 Android 的标准应用沙箱内运行。没有违反任何安全策略。本库在功能上等同于一个应用检查自身的运行时状态——这是一种正常且被允许的操作。 ## 📁 4. 输出位置与回退顺序 本库按以下顺序**依次**尝试这些目录。如果其中一个失败(例如,权限被拒绝、挂载命名空间问题),它会转向下一个。最终文件始终命名为 `dump.cs`。 | 步骤 | 策略 | 示例路径 | |------|--------------------------------------------|----------------------------------------------------------------| | 1 | JNI `Context.getFilesDir()` | `/data/data//files/il2cpp_dump/` | | 2 | 硬编码 `/data/data//files/` | `/data/data//files/il2cpp_dump/` | | 3 | `/sdcard/il2cpp_dump/`(包名未知) | `/sdcard/il2cpp_dump/` | | 4* | 限定作用域的外部存储 (Android 10+) | `/sdcard/Android/data//files/il2cpp_dump/` | | 5* | 完整模拟路径 | `/storage/emulated/0/Android/data//files/il2cpp_dump/` | | 6* | 最终的 `/sdcard` 回退 | `/sdcard/il2cpp_dump/` | *步骤 4‑6 仅在主 `fopen()` 失败时尝试,此时会使用从原始路径中提取的包名。它们是 dump 函数内部的次要回退方案。 ## 📁 5. 自定义输出路径 你可以通过编辑 `jni_entry.c` 来硬编码一个自定义目录。 例如,要始终写入到: `/storage/emulated/0/Android/data/com.example.vm/rootfs/storage/emulated/0/il2cpp_dump//dump.cs` 请将 `dump_thread()` 函数中的 `output_dir` 构建代码块替换为: ``` char output_dir[PATH_MAX] = {0}; if (pkg[0] && strcmp(pkg, "unknown") != 0) { snprintf(output_dir, sizeof(output_dir), "/storage/emulated/0/Android/data/com.example.vm/rootfs" "/storage/emulated/0/il2cpp_dump/%s", pkg); mkdir_p(output_dir); LOGI("Output dir (custom): %s", output_dir); } else { snprintf(output_dir, sizeof(output_dir), "/storage/emulated/0/Android/data/com.example.vm/rootfs" "/storage/emulated/0/il2cpp_dump/unknown"); mkdir_p(output_dir); LOGW("Output dir (custom, unknown pkg): %s", output_dir); } ``` 重新构建库后,dump 将准确地生成在该硬编码路径下。 ## 💡 6. 使用指南 ### 📝 前置条件 - Android NDK(用于原生编译) - Termux 应用(用于在设备上构建) ### 🛠️ 构建说明 ``` # Clone 仓库 git clone https://github.com/muhammadrizwan87/il2cppdumper.git cd il2cppdumper # 设置 NDK 路径 export NDK_HOME=/path/to/your/ndk # export NDK_HOME=/data/data/com.termux/files/home/android-sdk/ndk/24.0.8215888 # 为所有架构构建 $NDK_HOME/ndk-build NDK_PROJECT_PATH=. NDK_APPLICATION_MK=./jni/Application.mk # 输出将在 libs/ 中 ls libs/ # armeabi-v7a/ arm64-v8a/ x86/ x86_64/ ``` ### 🔀 集成说明 原生库必须**尽早加载**——理想情况下是在应用的 `Application` 类静态初始化器或其对应的 Smali 代码中。 #### 选项 A:修补现有的 APK (Smali) **1. 加载库的 Smali 代码:** ``` .method static constructor ()V .registers 1 const-string v0, "il2cppdumper" invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V return-void .end method ``` **2. 添加原生库:** ``` lib/armeabi-v7a/libil2cppdumper.so lib/arm64-v8a/libil2cppdumper.so lib/x86/libil2cppdumper.so lib/x86_64/libil2cppdumper.so ``` #### 选项 B:集成到你自己的 Android 项目中 **1. 添加到你的 Application 类中:** ``` public class MyApp extends Application { static { System.loadLibrary("il2cppdumper"); // note: correct spelling from Android.mk } @Override public void onCreate() { super.onCreate(); // Dump starts automatically when library loads } } ``` **2. 更新 `build.gradle`:** ``` android { sourceSets { main { jniLibs.srcDirs = ['libs'] } } } ``` ## 🤝 7. 致谢 *基于 Perfare 的 [Zygisk-Il2CppDumper](https://github.com/Perfare/Zygisk-Il2CppDumper) 基础构建。*
标签:Android安全, App安全检测, C#伪代码生成, Hook工具, IL2CPP逆向, libil2cpp.so, Native库, SO库分析, Unity游戏逆向, 云资产清单, 内存Dump, 加密元数据处理, 安卓注入, 客户端加密, 无需Root, 流量嗅探, 游戏安全, 移动安全工具, 移动端脱壳, 网络安全, 进程内注入, 逆向工程, 隐私保护