Unity il2cpp字符串加密提取:Il2CppDumper字符串提取技巧
前言:il2cpp字符串加密的痛点与解决方案
你是否在逆向Unity游戏时遇到过字符串被加密的情况?作为Unity游戏逆向工程中的常见挑战,字符串加密严重阻碍了代码分析和逻辑理解。本文将系统讲解如何利用Il2CppDumper工具提取il2cpp字符串,通过5个实战步骤,帮助你从加密的二进制文件中完整获取原始字符串。
读完本文你将获得:
- 理解il2cpp字符串加密的原理和常见模式
- 掌握使用Il2CppDumper进行字符串提取的完整流程
- 学习自定义解密脚本开发,应对复杂加密场景
- 获取高效字符串分析与验证的实用技巧
一、il2cpp字符串加密原理深度解析
1.1 Unity il2cpp编译流程中的字符串处理
Unity的il2cpp(中间语言转C++)编译过程中,字符串通常会经历以下处理流程:
在默认情况下,il2cpp会将字符串以明文形式存储在二进制文件的.data或.rodata段中。但许多开发者为了保护内容,会对这些字符串进行加密处理。
1.2 常见的il2cpp字符串加密模式
通过分析大量Unity游戏样本,我们总结出以下几种常见的字符串加密模式:
| 加密模式 | 特征 | 难度 | 出现频率 |
|---|---|---|---|
| XOR加密 | 固定或动态密钥的异或运算 | 低 | ★★★★★ |
| 自定义算法 | 游戏开发者编写的特殊加密 | 中-高 | ★★★☆☆ |
| 加密库集成 | 使用第三方加密库(如AES) | 高 | ★★☆☆☆ |
| 虚拟机保护 | 字符串在自定义虚拟机中解密 | 极高 | ★☆☆☆☆ |
其中,XOR加密是最常见的形式,通常使用一个或多个字节作为密钥对字符串进行简单异或运算。
1.3 加密字符串在内存中的表现形式
加密字符串在二进制文件中通常表现为:
- 无明显可读字符的字节序列
- 位于可执行段(.text)而非数据段
- 附近有解密函数调用或密钥数据
- 可能通过某种标记(如特定前缀)标识
二、Il2CppDumper字符串提取核心功能解析
2.1 Il2CppDumper的字符串提取机制
Il2CppDumper通过分析il2cpp二进制文件和元数据,实现字符串提取功能。其核心原理如下:
关键代码位于Il2CppExecutor.cs的GetConstantValueFromBlob方法,该方法负责从元数据中提取字符串常量:
public bool GetConstantValueFromBlob(Il2CppTypeEnum type, BinaryReader reader, out BlobValue value)
{
value = new BlobValue { il2CppTypeEnum = type };
switch (type)
{
case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
int length;
if (il2Cpp.Version >= 29)
{
length = reader.ReadCompressedInt32();
if (length == -1)
{
value.Value = null;
}
else
{
value.Value = Encoding.UTF8.GetString(reader.ReadBytes(length));
}
}
else
{
length = reader.ReadInt32();
value.Value = reader.ReadString(length);
}
return true;
// 其他数据类型处理...
default:
value = null;
return false;
}
}
2.2 字符串提取相关的关键组件
Il2CppDumper中与字符串提取相关的核心组件包括:
- Metadata类:负责解析il2cpp元数据,提供字符串索引访问
- Il2CppExecutor类:处理元数据中的常量值提取,包括字符串
- ScriptJson类:用于将提取的字符串导出为JSON格式
- Il2CppDecompiler类:生成C#代码时处理字符串常量
这些组件协同工作,从元数据和二进制文件中提取并还原字符串数据。
三、使用Il2CppDumper提取字符串的完整流程
3.1 准备工作与环境配置
使用Il2CppDumper提取字符串前,需要准备以下工具和文件:
- 下载最新版Il2CppDumper:
git clone https://gitcode.com/gh_mirrors/il/Il2CppDumper - 游戏的
libil2cpp.so或GameAssembly.dll文件 - 对应的
global-metadata.dat文件 - .NET Core 3.1或更高版本运行环境
编译Il2CppDumper:
cd /data/web/disk1/git_repo/gh_mirrors/il/Il2CppDumper
dotnet build Il2CppDumper/Il2CppDumper.csproj -c Release
3.2 基础字符串提取步骤
使用Il2CppDumper进行基础字符串提取的命令如下:
dotnet Il2CppDumper/bin/Release/netcoreapp3.1/Il2CppDumper.dll \
libil2cpp.so global-metadata.dat output_dir
执行上述命令后,Il2CppDumper会在output_dir目录下生成多个文件,其中与字符串相关的包括:
script.json:包含所有提取的字符串信息dump.cs:反编译的C#代码,包含字符串常量
查看script.json中的字符串数据:
{
"ScriptString": [
{
"Address": 144115207285808,
"Value": "HelloWorld"
},
{
"Address": 144115207285824,
"Value": "PlayerHealth"
},
// 更多字符串...
]
}
3.3 高级选项:自定义字符串提取配置
Il2CppDumper提供了多种命令行选项,用于处理复杂的字符串加密情况:
# 强制使用特定版本的il2cpp
dotnet Il2CppDumper.dll libil2cpp.so global-metadata.dat output_dir --version 29
# 启用详细日志,辅助调试加密问题
dotnet Il2CppDumper.dll libil2cpp.so global-metadata.dat output_dir --verbose
# 仅提取字符串数据
dotnet Il2CppDumper.dll libil2cpp.so global-metadata.dat output_dir --only-strings
四、应对复杂加密场景的解决方案
4.1 识别加密字符串的技巧
当遇到复杂的字符串加密时,可以通过以下方法识别加密特征:
- 静态分析:在二进制文件中搜索字符串引用模式
- 动态调试:在字符串使用处下断点,观察解密过程
- 元数据分析:检查
global-metadata.dat中的字符串元数据
使用Il2CppDumper的搜索功能定位可能的加密字符串:
// 伪代码:搜索可能的加密字符串引用
var sectionHelper = il2Cpp.GetSectionHelper();
var searchPattern = new byte[] { 0xXX, 0xXX, 0xXX, 0xXX }; // 加密特征
var results = sectionHelper.SearchBytes(searchPattern);
foreach (var result in results)
{
Console.WriteLine($"Found potential encrypted string at 0x{result:X}");
}
4.2 开发自定义解密脚本
对于Il2CppDumper无法直接提取的字符串,我们可以开发自定义解密脚本。以下是一个XOR解密的示例:
// 自定义XOR解密脚本示例
public class CustomDecryptor
{
private Il2CppDumper dumper;
public CustomDecryptor(Il2CppDumper dumper)
{
this.dumper = dumper;
}
// XOR解密方法
public string XORDecrypt(byte[] encryptedData, byte key)
{
byte[] decryptedData = new byte[encryptedData.Length];
for (int i = 0; i < encryptedData.Length; i++)
{
decryptedData[i] = (byte)(encryptedData[i] ^ key);
}
return Encoding.UTF8.GetString(decryptedData);
}
// 批量解密字符串
public void DecryptAllStrings(byte key)
{
foreach (var scriptString in dumper.ScriptJson.ScriptString)
{
// 检查是否为加密字符串(简单示例)
if (IsEncrypted(scriptString.Value))
{
byte[] encryptedBytes = Encoding.UTF8.GetBytes(scriptString.Value);
scriptString.Value = XORDecrypt(encryptedBytes, key);
}
}
}
private bool IsEncrypted(string value)
{
// 根据实际情况实现加密字符串检测逻辑
return value.All(c => c < 0x20 || c > 0x7E);
}
}
4.3 结合Ghidra/IDA进行深度分析
对于高度复杂的加密方案,我们需要结合逆向工程工具进行深度分析:
- 使用Il2CppDumper导出函数信息:
script.json包含所有函数地址和签名 - 在Ghidra/IDA中加载
libil2cpp.so并导入函数信息 - 搜索字符串解密函数(通常引用
il2cpp_string_new或类似函数) - 分析解密算法并实现对应的解密代码
五、字符串提取结果验证与应用
5.1 验证提取字符串的完整性
提取完成后,我们需要验证结果的完整性和正确性:
- 数量验证:比较提取前后的字符串数量
- 内容验证:检查是否存在明显不合理的字符串
- 上下文验证:结合代码逻辑判断字符串是否合理
以下是一个简单的验证脚本:
public class StringValidator
{
public bool ValidateStrings(List<ScriptString> decryptedStrings)
{
int invalidCount = 0;
foreach (var str in decryptedStrings)
{
if (!IsValidString(str.Value))
{
Console.WriteLine($"Invalid string: {str.Value} at 0x{str.Address:X}");
invalidCount++;
}
}
Console.WriteLine($"Validation complete. {invalidCount} invalid strings found.");
return invalidCount == 0;
}
private bool IsValidString(string value)
{
// 简单验证规则示例
if (string.IsNullOrEmpty(value))
return false;
// 检查控制字符比例
int controlChars = value.Count(c => char.IsControl(c));
if (controlChars > value.Length / 2)
return false;
return true;
}
}
5.2 提取字符串在逆向工程中的应用
提取后的字符串在逆向工程中有多种应用:
- 函数识别:根据字符串提示理解函数功能
- 逻辑分析:通过字符串推断代码执行流程
- 本地化修改:修改游戏文本内容
- 辅助调试:定位关键功能字符串用于内存搜索
例如,提取后的"PlayerHealth"字符串可能帮助我们快速定位玩家生命值相关的代码。
六、总结与进阶技巧
6.1 常见问题与解决方案
| 问题 | 解决方案 |
|---|---|
| 部分字符串提取失败 | 检查是否为动态加密,尝试动态调试获取密钥 |
| 提取后的字符串乱码 | 尝试不同的编码方式(UTF-8, UTF-16等) |
| Il2CppDumper崩溃 | 更新到最新版本,提供详细日志报告问题 |
| 性能问题 | 使用--only-strings选项只提取字符串 |
6.2 高级优化技巧
- 多线程提取:对于大量字符串,实现并行提取提高效率
- 密钥自动识别:开发算法自动识别常见加密的密钥
- 模式匹配:建立常见加密模式库,自动应用相应解密算法
- 内存中直接提取:开发工具直接在内存中提取并导出字符串
6.3 未来展望
随着Unity和il2cpp技术的不断发展,字符串加密技术也在不断演进。未来的提取技术可能需要:
- 更智能的静态分析算法
- 动态执行跟踪解密过程
- 机器学习辅助识别加密模式
通过持续学习和实践,我们可以不断提升应对新型加密技术的能力。
附录:Il2CppDumper字符串相关配置参考
config.json中与字符串相关的配置项:
{
"DumpString": true, // 是否导出字符串
"StringEncryptionKey": null, // 全局字符串加密密钥
"CustomDecryptor": "", // 自定义解密器路径
"StringOutputFormat": "json" // 输出格式(json, txt, csv)
}
通过合理配置这些选项,可以优化字符串提取过程,提高提取成功率。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



