Unity il2cpp字符串加密算法识别:常见加密方式与分析方法

Unity il2cpp字符串加密算法识别:常见加密方式与分析方法

【免费下载链接】Il2CppDumper Unity il2cpp reverse engineer 【免费下载链接】Il2CppDumper 项目地址: https://gitcode.com/gh_mirrors/il/Il2CppDumper

你是否在逆向分析Unity游戏时,遇到过字符串被加密隐藏的情况?当你尝试通过IL2CPP(中间语言转C++)反编译后的代码进行分析时,关键字符串却以乱码或数值形式呈现,导致逻辑理解困难。本文将系统梳理IL2CPP环境下常见的字符串加密算法,提供可落地的识别方法与分析思路,帮助你高效还原隐藏的关键信息。

读完本文你将获得:

  • 4种IL2CPP常见字符串加密算法的特征识别指南
  • 基于Il2CppDumper的自动化解密工具开发教程
  • 手动分析与动态调试相结合的实战技巧
  • 加密算法强度评估与绕过策略

IL2CPP字符串加密的底层原理

在Unity项目发布为IL2CPP格式时,原始C#代码会被编译为C++中间代码,其中字符串处理机制发生显著变化。理解这些变化是识别加密的基础。

元数据存储结构

IL2CPP的字符串信息主要存储在global-metadata.dat文件中,通过Il2CppGlobalMetadataHeader结构体管理:

public class Il2CppGlobalMetadataHeader
{
    public uint sanity;               // 校验值 0xFAB11BAF
    public int version;               // 元数据版本号
    public uint stringLiteralOffset;  // 字符串字面量偏移
    public int stringLiteralSize;     // 字符串字面量大小
    public uint stringLiteralDataOffset; // 字符串数据偏移
    // ... 其他元数据字段
}

正常情况下,字符串通过Il2CppStringLiteral结构体存储:

public class Il2CppStringLiteral
{
    public uint length;  // 字符串长度
    public int dataIndex; // 数据索引,指向实际字符串内容
}

加密字符串会破坏这种标准结构,导致dataIndex指向无效数据或加密内容。

加密触发场景

通过分析Il2CppDumper源码,发现以下情况会触发字符串加密处理:

  1. 元数据加密检测:在Program.cs中存在加密检查逻辑

    Console.WriteLine($"ERROR: Metadata file not found or encrypted.");
    
  2. 可执行文件加密:如Mach-O格式文件加密会被明确标记

    Console.WriteLine("ERROR: This Mach-O executable is encrypted and cannot be processed.");
    
  3. 自定义加密实现:游戏开发者通过以下方式实现自定义加密:

    • 修改字符串存储方式
    • 重写il2cpp_string_new等字符串创建函数
    • stringLiteralDataOffset指向的内存区域进行加密

常见加密算法识别与分析

1. XOR异或加密

算法特征:使用固定密钥或动态密钥对字符串每个字节进行异或运算。

识别方法

  • 在反编译代码中寻找类似byte ^ key的操作模式
  • 字符串长度通常保持不变
  • 密钥常为1-4字节的小数值(如0xAA, 0x55等)

分析实例

假设发现加密函数如下:

// 加密函数伪代码
char* XorEncrypt(const char* input, int len, byte key) {
    char* output = malloc(len);
    for(int i=0; i<len; i++) {
        output[i] = input[i] ^ key;
    }
    return output;
}

分析工具实现(C#)

public static string DecryptXor(byte[] encryptedData, byte key)
{
    byte[] decrypted = new byte[encryptedData.Length];
    for (int i = 0; i < encryptedData.Length; i++)
    {
        decrypted[i] = (byte)(encryptedData[i] ^ key);
    }
    return Encoding.UTF8.GetString(decrypted);
}

密钥查找技巧

  • 尝试常见密钥:0x00(不加密), 0xFF, 0xAA, 0x55, 0x2A
  • 分析字符串引用处的解密函数参数
  • 动态调试跟踪il2cpp_string_new调用

2. 位移加密(Shift Encryption)

算法特征:通过位运算(左移/右移)对字符编码进行偏移。

识别方法

  • 代码中存在<<>>位运算操作
  • 常与&|运算结合使用
  • 在Elf格式处理中发现相关操作:
    var bloom_shift = ReadUInt32(); // 位移值读取
    

典型加密代码

char* ShiftEncrypt(const char* input, int len, int shift) {
    char* output = malloc(len);
    for(int i=0; i<len; i++) {
        // 循环左移shift位
        output[i] = (input[i] << shift) | (input[i] >> (8 - shift));
    }
    return output;
}

分析实现

public static string DecryptShift(byte[] encryptedData, int shift)
{
    byte[] decrypted = new byte[encryptedData.Length];
    for (int i = 0; i < encryptedData.Length; i++)
    {
        // 反向位移操作
        decrypted[i] = (byte)((encryptedData[i] >> shift) | (encryptedData[i] << (8 - shift)));
    }
    return Encoding.UTF8.GetString(decrypted);
}

3. 查表替换加密

算法特征:使用预设的替换表对字符进行映射转换,Il2CppDumper中未直接实现但常见于第三方加密。

识别方法

  • 寻找大型字节数组(通常256字节)作为替换表
  • 函数中存在table[input[i]]形式的数组访问
  • 加密后字符串仍保持原长度

分析流程

  1. 定位替换表(通常是大小为256的byte数组)
  2. 创建反向查找表:reverseTable[encryptedByte] = originalByte
  3. 使用反向表解密整个字符串

分析代码示例

public static string DecryptLookupTable(byte[] encryptedData, byte[] encryptTable)
{
    // 创建反向查找表
    byte[] decryptTable = new byte[256];
    for (int i = 0; i < 256; i++)
    {
        decryptTable[encryptTable[i]] = (byte)i;
    }
    
    // 解密数据
    byte[] decrypted = new byte[encryptedData.Length];
    for (int i = 0; i < encryptedData.Length; i++)
    {
        decrypted[i] = decryptTable[encryptedData[i]];
    }
    
    return Encoding.UTF8.GetString(decrypted);
}

4. 组合加密算法

算法特征:结合多种加密手段,如"XOR+位移+查表"的多层加密,是最难以分析的类型。

识别方法

  • 函数调用链较长,包含多个加密步骤
  • 存在嵌套的位运算和数组访问
  • 解密函数参数较多,可能包含多个密钥或表

分析策略:采用分阶段分析法,逐层剥离加密层:

mermaid

自动化解密工具开发

基于Il2CppDumper开发自定义解密工具,可大幅提高逆向效率。

工具架构设计

mermaid

核心实现代码

  1. 加密检测扩展:在Metadata.cs中添加加密检测方法
public EncryptionType DetectStringEncryption()
{
    // 遍历字符串字面量检测异常模式
    foreach (var strLiteral in stringLiterals)
    {
        try
        {
            Position = (uint)(header.stringLiteralDataOffset + strLiteral.dataIndex);
            var data = ReadBytes((int)strLiteral.length);
            
            // 检测XOR特征
            if (EncryptionDetector.IsXorEncrypted(data))
                return EncryptionType.XOR;
                
            // 检测位移特征
            if (EncryptionDetector.IsShiftEncrypted(data))
                return EncryptionType.Shift;
                
            // 检测查表特征
            if (EncryptionDetector.IsLookupEncrypted(data))
                return EncryptionType.LookupTable;
        }
        catch
        {
            // 无法正常读取,可能是加密
            return EncryptionType.Unknown;
        }
    }
    return EncryptionType.None;
}
  1. 解密功能集成:修改StringDecryptor.cs添加解密实现
public string DecryptString(Il2CppStringLiteral strLiteral, EncryptionType type, object key)
{
    Position = (uint)(metadata.header.stringLiteralDataOffset + strLiteral.dataIndex);
    var encryptedData = ReadBytes((int)strLiteral.length);
    
    switch (type)
    {
        case EncryptionType.XOR:
            return DecryptXor(encryptedData, (byte)key);
        case EncryptionType.Shift:
            return DecryptShift(encryptedData, (int)key);
        case EncryptionType.LookupTable:
            return DecryptLookup(encryptedData, (byte[])key);
        default:
            return "无法解密: 未知加密类型";
    }
}
  1. 命令行接口扩展:在Program.cs中添加解密参数
case "decrypt":
    var metadata = new Metadata(metadataStream);
    var encryptionType = metadata.DetectStringEncryption();
    Console.WriteLine($"检测到加密类型: {encryptionType}");
    
    if (encryptionType != EncryptionType.None)
    {
        var key = GetEncryptionKey(metadata, encryptionType);
        var decryptor = new StringDecryptor(metadata);
        
        foreach (var str in metadata.stringLiterals)
        {
            var decrypted = decryptor.DecryptString(str, encryptionType, key);
            Console.WriteLine($"解密字符串: {decrypted}");
        }
    }
    break;

实战案例分析

案例1:Unity游戏XOR加密字符串分析

环境:某Android Unity游戏,IL2CPP后端,字符串无法正常显示

分析步骤

  1. 加密识别

    Il2CppDumper --detect-encryption GameAssembly.dll global-metadata.dat
    

    输出:检测到XOR加密,密钥可能为0x2A

  2. 密钥验证

    Il2CppDumper --decrypt-xor 0x2A GameAssembly.dll global-metadata.dat
    

    部分字符串成功解密,确认密钥正确

  3. 批量分析

    Il2CppDumper --dump-decrypted 0x2A GameAssembly.dll global-metadata.dat output_dir
    

结果:成功分析2000+字符串,包括关键API地址、配置路径和调试信息

案例2:多层加密字符串分析

环境:某Switch平台Unity游戏,采用"XOR+查表"双层加密

分析难点

  • 外层XOR密钥动态生成
  • 内层查表替换表在内存中动态构建
  • 加密函数经过混淆处理

解决方案

  1. 使用Frida动态Hookil2cpp_string_new函数
  2. 记录加密前后数据对比
  3. 反推密钥和替换表
  4. 开发专用解密插件

关键代码

// Frida脚本获取加密前后数据
Interceptor.attach(Module.findExportByName("GameAssembly.dll", "il2cpp_string_new"), {
    onEnter: function(args) {
        this.input = args[0];
        this.inputStr = Memory.readUtf8String(this.input);
    },
    onLeave: function(retval) {
        var outputStr = Memory.readUtf8String(retval);
        console.log(`加密前: ${this.inputStr}, 加密后: ${outputStr}`);
        // 保存数据用于密钥分析
    }
});

加密防护与绕过策略

加密强度评估

不同加密算法的安全性与可分析性对比:

加密类型分析难度性能影响特征明显度推荐防护等级
XOR★☆☆☆☆
位移加密★☆☆☆☆
查表加密★★☆☆☆
组合加密★★★★☆
AES-256极高★★★★★

高级绕过技术

  1. 动态调试法:在字符串使用前下断点获取解密后内容
  2. 内存dump法:在字符串解密后dump内存提取
  3. 函数重定向:Hook解密函数直接获取明文
  4. 元数据修复:修复被加密的元数据结构

元数据修复示例

public void RepairEncryptedMetadata()
{
    // 修复字符串数据偏移
    header.stringLiteralDataOffset = DecryptedStringDataOffset;
    
    // 重建字符串字面量表
    for (int i = 0; i < stringLiterals.Length; i++)
    {
        // 更新dataIndex指向解密后的数据
        stringLiterals[i].dataIndex = decryptedDataIndices[i];
    }
}

总结与展望

IL2CPP字符串加密是Unity游戏保护的重要手段,但同时也为逆向分析带来挑战。本文系统介绍了四种常见加密算法的识别与分析方法,从手动分析到自动化工具开发,提供了完整的解决方案。

随着Unity版本的更新,字符串加密技术也在不断演进,未来可能会看到:

  • 更复杂的动态加密算法
  • 基于硬件安全模块的加密
  • AI驱动的自适应加密方案

作为逆向分析工程师,需要持续学习新的加密技术与分析方法,同时开发更智能的自动化工具。建议结合静态分析与动态调试,灵活运用各种技术手段,以应对不断变化的加密挑战。

最后,本文提供的技术仅用于学习研究目的,请遵守相关法律法规,不得用于非法用途。


扩展资源

  • Il2CppDumper源码:https://gitcode.com/gh_mirrors/il/Il2CppDumper
  • IL2CPP内部原理文档:Unity官方IL2CPP技术白皮书
  • 字符串加密分析工具:本文配套的Il2CppDecryptor插件

【免费下载链接】Il2CppDumper Unity il2cpp reverse engineer 【免费下载链接】Il2CppDumper 项目地址: https://gitcode.com/gh_mirrors/il/Il2CppDumper

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值