当前位置: 首页 > news >正文

实战解密il2cpp的global-metadata.dat文件:用IDA和VS Code逆向分析技巧

实战解密il2cpp的global-metadata.dat文件:用IDA和VS Code逆向分析技巧

在移动应用安全研究和游戏逆向工程领域,il2cpp作为Unity引擎的核心组件,其生成的global-metadata.dat文件承载着关键的类型信息和运行时元数据。本文将深入探讨如何通过IDA Pro和VS Code这两款工具的组合运用,实现对加密global-metadata.dat文件的逆向分析与解密。

1. 逆向分析环境准备

1.1 工具链配置

进行il2cpp逆向分析需要准备以下专业工具组合:

  • IDA Pro 7.5+:建议使用专业版以获得完整的反编译功能
  • VS Code:配备C/C++扩展和Hex Editor插件
  • Python 3.8+:用于编写解密脚本
  • 010 Editor:二进制文件分析利器
  • JADX:APK反编译工具

注意:所有工具应保持最新版本,避免因版本差异导致分析结果不一致。

1.2 样本获取与预处理

以《Last Island of Survival》6.3版本为例,获取XAPK文件后需进行以下处理:

# 解压XAPK获取APK文件 unzip Last_Island_of_Survival_6.3_Apkpure.xapk # 使用apktool解压APK apktool d base.apk -o decompiled

解压后重点关注assets/bin/Data/Managed/Metadata/路径下的global-metadata.dat文件以及lib/armeabi-v7a/libil2cpp.so等原生库文件。

2. 元数据文件结构解析

2.1 global-metadata.dat基础结构

通过010 Editor打开文件,可以观察到典型的il2cpp元数据结构特征:

偏移量长度描述
0x004魔数标识(通常为0xFAB11BAF)
0x044版本号
0x088字符串字面量区大小
0x108字符串数据区偏移

2.2 加密特征识别

加密后的global-metadata.dat通常呈现以下特征:

  • 文件头魔数被破坏
  • 熵值分析显示高随机性
  • 特定位置出现重复的XOR模式

使用Python进行初步熵值检测:

import math def calculate_entropy(file_path): with open(file_path, 'rb') as f: data = f.read() if not data: return 0 entropy = 0 for x in range(256): p_x = float(data.count(x))/len(data) if p_x > 0: entropy += -p_x * math.log(p_x, 2) return entropy print(f"Entropy: {calculate_entropy('global-metadata.dat'):.4f}")

提示:正常未加密的元数据文件熵值通常在4.5-5.5之间,加密后通常超过7.0。

3. IDA静态分析实战

3.1 关键函数定位

将libil2cpp.so加载到IDA后,按以下步骤定位解密逻辑:

  1. 使用Shift+F12打开字符串视图
  2. 搜索"global-metadata.dat"引用
  3. 追踪到aGlobalMetadata字符串的交叉引用
  4. 通过X键查看引用该字符串的函数

典型调用链示例:

sub_57E558 (MetadataCache::Initialize) -> sub_57EE7C (LoadMetadataFile) -> os::File::Open -> DecryptMetadata

3.2 伪代码分析

在IDA中按F5生成伪代码后,重点关注以下特征结构:

while ( v15 = 0; v16 = 0; v15++ ) { *(_BYTE *)(v13 + v15) ^= dword_2A26E10[(v15 / 0x32) % 50]; }

这显示了一个典型的循环XOR加密模式,其中:

  • dword_2A26E10是50字节的密钥数组
  • 加密按字节进行
  • 密钥索引通过(offset/0x32)%50计算

4. VS Code动态验证

4.1 源码对照分析

在VS Code中打开il2cpp源码,全局搜索"global-metadata.dat",定位到vm/MetadataLoader.cpp文件中的关键函数:

void MetadataLoader::LoadMetadataFile(const char* fileName) { // ... if (!os::File::Open(fileName, ...)) { LOG("ERROR: Could not open %s", fileName); return; } // ... DecryptMetadata(encryptedData, dataSize); }

通过对比IDA伪代码和源码,可以确认:

  • sub_57EE7C对应MetadataLoader::LoadMetadataFile
  • 加密发生在文件读取之后

4.2 密钥提取技巧

在IDA中定位到密钥数组后,可通过以下Python脚本导出密钥:

import idautils def extract_key(start_addr, key_size=50): key = [] for i in range(key_size): key.append(idc.get_wide_byte(start_addr + i)) return bytes(key) key = extract_key(0x2A26E10) print(f"XOR Key: {key.hex(' ', 1)}")

5. 解密算法实现

5.1 Python解密脚本

基于逆向分析结果,实现完整的解密工具:

import struct from pathlib import Path def decrypt_metadata(input_path, output_path=None): if output_path is None: output_path = Path(input_path).with_name( Path(input_path).stem + "_decrypted.dat") key = [ 0xFE, 0x98, 0xAB, 0xDE, 0x99, 0x76, 0x36, 0x33, 0xBC, 0xFE, 0xAB, 0x65, 0xAD, 0x61, 0x97, 0xBE, 0x89, 0xAB, 0x0A, 0x93, 0x98, 0x8A, 0x2D, 0x93, 0x23, 0xDF, 0xB3, 0x35, 0x0D, 0x32, 0x4D, 0xE2, 0xE8, 0xDB, 0x0E, 0xAE, 0x8E, 0x3D, 0x0A, 0xE9, 0xA8, 0xE8, 0xEB, 0x38, 0xEF, 0xBD, 0xE8, 0x9B, 0x39, 0xE9 ] with open(input_path, 'rb') as f_in, open(output_path, 'wb') as f_out: n = 0 while True: chunk = f_in.read(4096) if not chunk: break decrypted = bytearray() for i, byte in enumerate(chunk): key_index = (n + i + (n + i) // 0x32) % 50 decrypted.append(byte ^ key[key_index]) f_out.write(decrypted) n += len(chunk) return output_path

5.2 解密验证方法

成功解密后应满足以下条件:

  1. 文件头魔数恢复为0xFAB11BAF
  2. 字符串表可读性显著提高
  3. 使用il2cppdumper工具可以正常解析类型信息

验证脚本示例:

def verify_decryption(file_path): with open(file_path, 'rb') as f: magic = struct.unpack('<I', f.read(4))[0] return magic == 0xFAB11BAF

6. 高级技巧与问题排查

6.1 密钥定位的替代方案

当密钥地址难以直接定位时,可尝试以下方法:

  1. 特征码搜索:在IDA中搜索/50 00 00 00/模式,寻找50字节数组
  2. 交叉引用追踪:从XOR指令回溯密钥来源
  3. 动态调试:在解密函数处设置断点,观察寄存器值

6.2 常见加密变种处理

不同游戏可能采用加密变种,需要调整解密逻辑:

  1. 密钥大小变化:修改脚本中的key数组大小
  2. 索引计算调整:例如(n//0x40)%64等变种
  3. 多层加密:可能需要多次应用不同密钥

典型变种处理示例:

# 处理索引计算变种 key_index = (n // 0x40 + n % 0x40) % len(key) # 处理多层加密 for byte in chunk: byte ^= key1[key_index] byte ^= key2[key_index] decrypted.append(byte)

在实际项目中遇到过密钥被分段存储的情况,需要组合多个内存区域的数据才能得到完整密钥。这种情况下,动态调试往往比静态分析更有效率。

http://www.jsqmd.com/news/525054/

相关文章:

  • Vue3 + Element Plus 日期选择器:开始 / 结束时间,结束时间不超过今天
  • MacBook用户必看:Cursor免费版无限续杯的3种技术方案
  • 亲测有效!论文AI率直降40%的秘密:4个指令+3个技巧+1个神器
  • 知网/维普/万方三大平台AI检测全攻略:一文搞懂怎么通过 - 我要发一区
  • MiniCPM-V-2_6科研协作:会议白板照片识别+行动项自动提取
  • 高效获取网络小说与个性化阅读的全流程指南
  • 达摩院PALM春联模型应用场景:文旅景区AI楹联互动体验设计
  • 2026四川AI企业培训避坑指南:选对路径,少走弯路
  • 数组中有两个数据,将其变成字符串
  • 毕业论文降AI率:免费额度/效果/售后全维度对比 - 我要发一区
  • 网捷顺科技客服咨询AI流量赋能,重塑智能体验新标杆 - 王老吉弄
  • Clawdbot部署实操:Qwen3-32B与LangChain/LlamaIndex生态无缝集成指南
  • Breaking the Prior Dependency: A Novel Approach to Camouflaged Object Detection with Adaptive Featur
  • 嘎嘎降AI vs 比话降AI vs 率零:2026毕业季工具横评 - 我要发一区
  • 手把手教你为STM32F103C8T6(蓝色小药丸)编译Cleanflight固件,解决Flash溢出问题
  • kubernetes学习
  • OCPI开源充电接口:解决电动汽车充电网络互操作性的技术架构实战
  • 拿云文化客服咨询AI流量赋能,重塑智能体验新标杆 - 王老吉弄
  • 密码安全那些坑:为什么你的正则表达式可能漏掉键盘连续字符?
  • DocMost 容器化部署进阶:从单机到高可用集群
  • 【杠杆】杠杆,保证金,爆仓相关计算--23
  • 苏州同宠信息科技客服咨询AI流量赋能,重塑智能体验新标杆 - 王老吉弄
  • 应届毕业生必看:降AI率工具怎么选?3款不踩坑推荐 - 我要发一区
  • 【DFT实战解析】OCC架构设计:从原理到复杂层级集成的时钟控制策略
  • 正点原子2026开发板教程——从0开始配置Linux内核(4)内核模块详解:从 Hello World 到设备驱动
  • 2026年石油石化电力电缆生产厂家推荐 中低压低压中压变频聚乙烯聚氯乙烯绝缘线缆详解 - 品牌2026
  • 2026半导体键合机温控设备优质推荐榜:恒温温控设备/激光干涉仪温控设备/键合机温控设备/光刻机温控设备/半导体检测设备温控设备/选择指南 - 优质品牌商家
  • 毕业论文降AI率省钱攻略:免费额度+工具组合最优方案 - 我要发一区
  • Orekit实战指南(四)——卫星轨道六根数与地面站经纬度的高效转换
  • Realistic Vision V5.1在量子计算领域的应用:前沿科研人员形象定制