Unity游戏逆向进阶 - IL2CPP逆向技术详解
字数 3767
更新时间 2026-02-06 04:38:50

Unity IL2CPP逆向技术详解教学文档

1. IL2CPP技术原理

1.1 编译流程

IL2CPP(Intermediate Language To C++)是Unity的一种脚本后端技术,其工作流程如下:

  1. C#代码编译:将C#源代码编译为IL(Intermediate Language)中间语言
  2. IL转C++:通过IL2CPP工具将IL代码转换为C++代码
  3. 原生编译:使用平台特定的C++编译器将C++代码编译为机器码

1.2 技术优势

  • 性能提升:AOT(Ahead-Of-Time)编译,运行时无需JIT编译
  • 安全性增强:代码编译为机器码,逆向难度显著增加
  • 平台兼容性:支持多平台原生代码编译

1.3 核心文件结构

  • GameAssembly.dll(Windows)或libil2cpp.so(Android/Linux):包含所有机器码
  • global-metadata.dat:位于Data/il2cpp_data/Metadata目录,存储元数据信息

2. IL2CPP游戏识别方法

2.1 文件特征识别

  • IL2CPP特征

    • 根目录存在GameAssembly.dll文件(Windows)
    • Data目录下包含il2cpp_data文件夹
    • il2cpp_data/Metadata/global-metadata.dat文件存在
  • Mono特征

    • Data/Managed文件夹包含Assembly-CSharp.dll等完整DLL文件

2.2 文件大小特征

GameAssembly.dll文件体积通常为几十MB到几百MB,包含游戏全部代码和依赖库

3. Il2CppDumper工具详解

3.1 工具概述

  • 项目地址:https://github.com/Perfare/Il2CppDumper
  • 功能:从GameAssembly.dll和global-metadata.dat提取符号信息
  • 支持平台:Windows、Linux、Android、iOS、macOS
  • 支持架构:x86、x64、ARM、ARM64

3.2 使用模式

  1. 自动模式(Auto):自动识别平台和架构
  2. 手动模式(Manual):用户手动指定平台信息
  3. 自动加强模式(Auto(Advanced)):增强识别算法

3.3 命令格式

Il2CppDumper.exe <executable-file> <global-metadata> <output-directory>

示例:

Il2CppDumper.exe GameAssembly.dll global-metadata.dat output

3.4 输出文件详解

3.4.1 DummyDll文件夹

  • 包含还原的DLL文件
  • 可使用dnSpy、ILSpy等工具查看
  • 保留完整的类结构和方法签名
  • 方法体为空,但包含完整的元数据信息

3.4.2 dump.cs文件

  • 纯文本格式的完整类定义
  • 包含继承关系、字段、属性、方法等信息
  • 支持文本搜索关键功能点

3.4.3 script.json文件

  • JSON格式的函数地址-名称映射
  • 用于IDA、Ghidra等反汇编工具
  • 实现函数重命名功能

3.4.4 il2cpp.h文件

  • IL2CPP运行时结构体定义
  • 包含Il2CppObject、Il2CppString等关键结构
  • 提升IDA反编译可读性

3.4.5 stringliteral.json文件

  • 字符串常量地址映射
  • 快速定位关键字符串引用

3.4.6 脚本文件

  • ida.py/ida_with_struct.py:IDA脚本
  • ghidra.py/ghidra_wasm.py:Ghidra脚本

4. IDA静态分析技术

4.1 分析流程

  1. 使用IDA打开GameAssembly.dll
  2. 等待自动分析完成
  3. 加载Il2CppDumper生成的脚本文件
  4. 导入符号信息和结构体定义

4.2 脚本加载方法

  • File → Script file 选择ida.py或ida_with_struct.py
  • 选择对应的script.json文件
  • 如使用增强版,还需选择il2cpp.h文件

4.3 分析技巧

4.3.1 字符串搜索

  • 利用stringliteral.json定位字符串地址
  • 在IDA中查找字符串引用
  • 快速定位关键功能函数

4.3.2 符号搜索

  • 通过恢复的符号信息搜索特定类和方法
  • 使用IDA的函数列表搜索功能
  • 结合DummyDll理解程序结构

4.3.3 结构体应用

  • 导入il2cpp.h增强反编译可读性
  • 正确识别Il2CppString、Il2CppArray等类型
  • 理解Unity特定的数据结构

5. Cheat Engine动态分析

5.1 内存搜索技术

  • 精确值搜索:已知具体数值时使用
  • 变化值搜索:通过数值变化规律定位地址
  • 数据类型支持:整数、浮点数、字符串、字节数组

5.2 高级功能应用

5.2.1 地址访问追踪

  • "Find out what accesses this address":追踪读取操作
  • "Find out what writes to this address":追踪写入操作
  • 定位修改关键变量的代码位置

5.2.2 函数调用

  • 通过script.json获取函数地址
  • 使用CE的"Call function"功能
  • 需要正确设置参数和调用约定

5.2.3 脚本功能

  • Lua脚本:自动化内存操作
  • Auto Assembler脚本:代码注入和修改
  • 实现复杂的内存操作逻辑

6. 实战案例:2024极客大挑战

6.1 游戏分析阶段

6.1.1 文件识别

  • 确认GameAssembly.dll存在
  • 定位global-metadata.dat文件
  • 确定为IL2CPP打包方式

6.1.2 符号提取

Il2CppDumper.exe GameAssembly.dll global-metadata.dat output

6.1.3 DummyDll分析

  • 使用dnSpy分析Assembly-CSharp.dll
  • 发现hOOK类及其SYC方法
  • 理解金钱触发机制

6.2 动态修改阶段

6.2.1 CE内存修改

  1. 附加CE到游戏进程
  2. 搜索当前金币数值
  3. 通过数值变化精确定位地址
  4. 修改金币值为1000000
  5. 触发SYC方法执行

6.2.2 文件生成

  • SYC方法生成Data.txt文件
  • 文件包含十六进制格式的PE文件
  • 存储位置为游戏根目录

6.3 二进制分析阶段

6.3.1 文件转换

Python转换脚本:

with open('Data.txt', 'r') as f:
    hex_data = f.read().strip()

with open('final.exe', 'wb') as f:
    f.write(bytes.fromhex(hex_data))

6.3.2 IDA反编译分析

加密逻辑分析:

  1. 凯撒加密:20轮偏移,只影响字母字符
  2. 异或加密:使用"GEEK"密钥循环异或
  3. 十六进制转换:字节数组转十六进制字符串

6.4 解密算法实现

6.4.1 加密流程

明文 → 凯撒加密(偏移20) → 异或加密(密钥"GEEK") → 十六进制转换 → 密文

6.4.2 解密脚本

def decrypt_flag():
    cipher_hex = "0A161230300C2D0A2B303D2428233005242C2D26182206233E097F133A"
    cipher_bytes = bytes.fromhex(cipher_hex)
    key = b"GEEK"
    
    # 异或解密
    xor_decrypted = bytes([cipher_bytes[i] ^ key[i % len(key)] for i in range(len(cipher_bytes))])
    
    # 凯撒解密(反向偏移20)
    plaintext = ""
    for byte in xor_decrypted:
        if 97 <= byte <= 122:  # 小写字母
            plaintext += chr((byte - 97 - 20) % 26 + 97)
        elif 65 <= byte <= 90:  # 大写字母
            plaintext += chr((byte - 65 - 20) % 26 + 65)
        else:
            plaintext += chr(byte)
    
    return plaintext

7. IL2CPP逆向难点与解决方案

7.1 技术难点

7.1.1 调用约定理解

  • x64架构使用Microsoft x64调用约定
  • 前4个参数通过RCX、RDX、R8、R9传递
  • 成员方法的this指针通过RCX传递

7.1.2 字符串处理

  • Il2CppString非标准C字符串
  • 包含长度字段和字符数据
  • 需要通过结构体偏移访问内容

7.1.3 类型信息丢失

  • 局部变量类型信息不完整
  • 需要通过上下文推断变量类型
  • 结合DummyDll签名信息辅助分析

7.2 保护措施应对

7.2.1 代码混淆

  • 控制流平坦化:转换为状态机结构
  • 虚拟机保护:自定义指令集执行
  • 应对策略:动态调试、符号执行

7.2.2 元数据保护

  • global-metadata.dat文件加密
  • 字符串常量加密存储
  • 需要先解密再使用Il2CppDumper

7.3 分析策略建议

  1. 先高层后底层:先分析DummyDll了解整体结构
  2. 动静结合:静态分析配合动态调试
  3. 关键词搜索:利用字符串和符号信息快速定位
  4. 参考文档:查阅Unity官方源码和文档

8. IL2CPP与Mono技术对比

8.1 逆向难度对比

特性 Mono IL2CPP
代码形式 IL字节码 机器码
反编译工具 dnSpy(源码级) IDA(汇编级)
符号信息 完整保留 需要工具恢复
修改难度 直接修改IL 修改机器码或Hook

8.2 开发选择考量

8.2.1 Mono优势

  • 快速编译迭代
  • 完整调试支持
  • 热重载功能

8.2.2 IL2CPP优势

  • 更好的运行性能
  • 更高的代码安全性
  • 更好的平台兼容性

8.3 混合开发策略

  • 开发阶段使用Mono快速迭代
  • 发布阶段切换为IL2CPP打包
  • 注意反射等特性兼容性问题

9. 总结与最佳实践

9.1 技术掌握要点

  1. 熟练掌握Il2CppDumper工具链使用
  2. 具备IDA静态分析能力
  3. 掌握CE等动态分析工具
  4. 理解IL2CPP运行时特性

9.2 分析流程标准化

  1. 识别阶段:确认打包方式和文件结构
  2. 提取阶段:使用Il2CppDumper恢复符号
  3. 静态分析:结合DummyDll和IDA分析
  4. 动态验证:使用CE等工具验证分析结果
  5. 算法还原:理解并实现加解密逻辑

9.3 持续学习建议

  • 关注Unity技术更新和变化
  • 学习新的逆向技术和工具
  • 参与安全社区交流分享
  • 遵守法律法规和道德规范

本教学文档详细介绍了IL2CPP逆向的完整技术体系,从基础原理到实战应用,涵盖了工具使用、分析方法、难点解决等各个方面,为深入学习Unity游戏逆向技术提供了完整的学习路径。

 全屏