首页/新闻资讯/正文详情

Il2CppDumper实战:Unity il2cpp逆向与符号恢复指南

发布时间:2026/9/26 17:01:56 来源:云帆数科 栏目:资讯中心
Il2CppDumper实战:Unity il2cpp逆向与符号恢复指南
简介Il2CppDumper-win-v6.7.46 是一款面向 Unity 逆向工程与安全研究人员的实用工具包主要用于还原 il2cpp 编译后的 DLL 文件不含源码并提取 MonoBehaviour 与 MonoScript 信息适合具备一定逆向基础、需要分析 Unity 游戏逻辑或做协议研究的开发者使用。压缩包共 11 个文件包含 8 个 Python 脚本、2 个可执行程序及 1 个 JSON 配置文件整体约 10.7MB其中 exe 为 Windows 平台主程序py 脚本用于生成 IDA 与 Ghidra 分析脚本、结构体头文件及 WASM 相关支持json 则保存运行配置。工具支持 ELF、ELF64、Mach-O、PE、NSO 和 WASM 等多种格式兼容 Unity 5.3 至 2020 版本并可从内存 dump 的 libil2cpp.so 绕过保护、处理简单 PE 保护。目前已有 1035 人学习下载能帮助读者快速获得可导入 IDA/Ghidra 的脚本与结构体头文件提升 il2cpp 文件的分析效率与准确性。1. Il2CppDumper-win-v6.7.46把 Unity 的 il2cpp 黑匣子撬开一条缝做 Unity 手游逆向或者安全评估的人迟早会撞上 il2cpp 这堵墙。Unity 从某个版本开始把 C# 编译成 IL 之后不再走 Mono 虚拟机而是通过 il2cpp 把 IL 转成 C 再编译成原生机器码于是你拿到一个libil2cpp.so里面全是sub_xxxxxx这种没有名字的函数字符串、方法名、类结构全被压进一个叫global-metadata.dat的文件里。Il2CppDumper 干的事情就是把这个 metadata 文件解析出来再把 so 里的函数地址和 metadata 里的方法一一对上最后吐出dump.cs、script.py、il2cpp.h这些能读的东西。标题里的 win 指的是 Windows 平台版本v6.7.46 是具体的发布版本号。这篇笔记面向的是需要分析 Unity il2cpp 产物、做协议还原或漏洞挖掘的从业者从工具怎么跑通讲到参数怎么调、坑在哪新手能照着复现熟手能对一下自己的边界。2. 先搞清楚 Il2CppDumper 到底在解析什么2.1 il2cpp 的两块拼图metadata 与二进制要理解 Il2CppDumper 的输出得先知道 il2cpp 运行时把信息拆成了两部分。第一部分是global-metadata.dat这是一个结构化文件头部有 magic通常是0xFAB11BAF、版本号、字符串表、类型定义表、方法定义表、字段表等等。它记录了「有哪些类、哪些方法、方法签名长什么样、字符串字面量是什么」这些逻辑信息。第二部分是libil2cpp.soAndroid或GameAssembly.dllWindows里面是真正编译出来的机器码每个方法对应一段原生指令但符号被剥离函数名基本不可读。Il2CppDumper 的核心工作就是读 metadata 拿到方法清单和元数据再去二进制里定位每个方法的代码地址。它靠的是 il2cpp 运行时在初始化时构建的那张方法指针表或者通过扫描特定指令模式来推断函数边界。所以你会看到它需要同时提供 metadata 文件和二进制文件缺一不可。只给 metadata它能列出类和方法名但没有地址只给二进制那就是一堆无名函数。提示metadata 的版本必须和二进制匹配。不同 Unity 版本生成的 metadata 结构有差异版本对不上时工具会直接报错或者解析出乱码。2.2 为什么需要 dump 出 dump.cs 和 script.pydump.cs是给人看的它把解析出来的类、方法、字段按 C# 语法重新组织方法体里标注了对应的原生地址类似// RVA: 0x123456 Offset: 0x123456 VA: 0x123456。有了这个文件你就能知道某个方法在 so 里的偏移配合 IDA 或 Ghidra 直接跳过去看反汇编。script.py是给 IDA 用的它是一段 IDAPython 脚本运行之后会把符号名、注释、函数名批量应用到 IDA 的数据库里原本sub_xxxxxx的地方会变成ClassName__MethodName这样的可读符号。这一步是效率分水岭没有脚本的话你得手动一个个对地址有了脚本几秒钟就能把整个 so 的符号恢复出来。il2cpp.h则是给需要重新编译或者做结构体对齐的人用的头文件。2.3 Windows 版和命令行版的差别标题里带 win说明用的是 Windows 平台的发布包。Il2CppDumper 的 Windows 版通常是带 GUI 的双击 exe 之后选文件、点 dump 就行。但实际干活时我更推荐用命令行版本因为可以写脚本批量处理也方便在 CI 或者远程环境里跑。Windows 版在路径处理上和 Linux 版有一点差异比如反斜杠和正斜杠的混用、中文路径的编码问题这些在后面避坑章节会细说。3. 在 Windows 上把 Il2CppDumper 跑通的最小步骤3.1 准备三个东西工具、metadata、二进制先把发布包解压到一个纯英文路径下比如D:\tools\Il2CppDumper。路径里不要有中文和空格这是血泪经验很多 .NET 写的工具在中文路径下会莫名其妙报Could not find file或者直接闪退。解压后你会看到主程序、依赖的 dll 以及可能的config.json。然后从目标应用里取出两个文件。Android 应用的话apk 解压后在assets/bin/Data/Managed/Metadata/global-metadata.dat找到 metadata在lib/arm64-v8a/libil2cpp.so或者armeabi-v7a找到二进制。Windows 应用的话metadata 通常在*_Data/il2cpp_data/Metadata/global-metadata.dat二进制是GameAssembly.dll。注意架构要对应你拿 arm64 的 so 配 arm64 的 metadata别混。3.2 命令行方式跑一次完整 dumpGUI 点点点适合第一次试但真正干活用命令行。假设工具在D:\tools\Il2CppDumper文件放在D:\work\target命令大概是这样cd /d D:\tools\Il2CppDumper Il2CppDumper.exe D:\work\target\libil2cpp.so D:\work\target\global-metadata.dat D:\work\output第一个参数是二进制文件路径第二个是 metadata 路径第三个是输出目录。输出目录不存在的话工具一般会自动创建。跑完之后去D:\work\output看正常会有dump.cs、script.py、il2cpp.h、stringliteral.json这几个文件。如果只生成了部分文件或者报错往下看排查章节。3.3 把 script.py 灌进 IDA 恢复符号打开 IDA加载libil2cpp.so等自动分析跑完。然后File - Script file选刚才生成的script.py。脚本跑的过程中 IDA 的输出窗口会刷一堆Renamed之类的日志跑完之后按ShiftF3打开函数列表你会看到原本的sub_xxxxxx变成了ClassName__MethodName这种形式。这时候再去看反汇编可读性完全不一样。如果脚本报错说找不到某个地址或者版本不匹配通常是 IDA 版本和脚本用的 API 不兼容或者 so 的基址设置有问题。IDA 加载 so 时基址默认是 0脚本里用的 RVA 也是相对基址的一般能对上。要是你手动改过基址就得把脚本里的偏移逻辑对应调整。# script.py 里核心逻辑的简化示意实际脚本更复杂 # 遍历 dump 出来的方法列表把名字和地址应用到 IDA for method in methods: addr method.rva image_base # image_base 通常是 0 ida_name.set_name(addr, method.name, ida_name.SN_NOCHECK) ida_funcs.add_func(addr) # 确保地址被识别为函数上面这段是脚本逻辑的示意不是原脚本。关键点是image_base这个基址如果你的 so 在 IDA 里加载基址不是 0就要把实际基址加进去否则符号会全部错位。参数SN_NOCHECK是告诉 IDA 不要做重名检查直接覆盖避免因为符号冲突中断。4. 参数、版本与输出文件的取舍4.1 版本号 v6.7.46 意味着什么Il2CppDumper 的版本迭代主要跟 Unity 版本和 metadata 结构变化走。v6.7.46 这个版本号说明它支持到比较新的 Unity 版本对 metadata 的解析做了兼容处理。实际使用时工具会自动检测 metadata 版本如果版本太新或者太旧可能会提示不支持。这时候要么换工具版本要么手动指定--metadata-version之类的参数不同版本参数名可能不同以--help输出为准。我一般会先跑一次看它自动识别的版本对不对不对再手动干预。Unity 2019 到 2022 之间的 metadata 结构相对稳定2023 之后有些字段调整老版本工具可能解析出字段错位。所以工具版本和 Unity 版本的对应关系要心里有数。4.2 输出文件怎么选不是每次都需要全部输出。dump.cs最常用看类结构和方法地址都靠它。script.py在需要 IDA 分析时必用。il2cpp.h在你要写 hook 或者做结构体对齐时才需要。stringliteral.json是字符串字面量的映射做协议分析时很有用能快速定位某个字符串在代码里的引用。如果目标很大dump.cs可能几百 MB打开会卡。这时候可以用工具的参数只 dump 特定命名空间或者特定类减少输出体积。具体参数看--help常见的有按 namespace 过滤、按类名过滤的选项。4.3 架构与 metadata 的匹配检查跑之前先确认二进制架构和 metadata 是不是一套。Android 上 arm64 和 armeabi-v7a 的 so 是分开的metadata 通常是共用的但有些应用会针对不同架构打包不同的 metadata。判断方法很简单跑一次如果方法地址全是 0 或者明显不对就是架构或版本不匹配。另一个检查点是看dump.cs里方法数量正常几万个方法是有的如果只有几百个大概率解析出问题了。检查项正常表现异常表现metadata magic0xFAB11BAF其他值或读取失败方法数量数万级别几百或零地址字段有合理 RVA全 0 或负数字符串表能读出可读字符串乱码或空5. 避坑与排查那些让我返工三次的问题5.1 中文路径导致工具闪退或报文件找不到现象双击 exe 或者命令行跑直接闪退或者弹窗说Could not find file xxx但文件明明就在那。原因工具是 .NET 写的部分版本对非 ASCII 路径处理有问题尤其是路径里带中文时内部拼接路径可能编码错乱。解决把工具、metadata、二进制、输出目录全部放到纯英文无空格路径下比如D:\work\。这个坑我踩过不止一次现在养成习惯逆向相关的东西一律不放中文目录。5.2 metadata 版本不匹配导致解析出乱码现象工具能跑完但dump.cs里类名、方法名全是乱码或者空字符串表也读不出东西。原因metadata 的版本和工具支持的版本对不上结构体字段偏移错位解析出来的全是垃圾数据。解决先看工具启动时打印的 metadata 版本号和你的 Unity 版本对照。如果工具不支持换更新的工具版本或者找对应版本的旧工具。另一个办法是用--metadata-version手动指定但前提是你知道正确的版本号。5.3 IDA 脚本跑完符号没恢复现象script.py跑完了日志也刷了但函数列表里还是sub_xxxxxx。原因通常是 IDA 加载 so 时的基址和脚本假设的基址不一致或者脚本因为某个异常提前中断了。解决先确认 IDA 里 so 的加载基址在Edit - Segments里看如果是 0 就正常。如果脚本中断看输出窗口最后的报错常见的是某个地址已经被定义成数据而不是代码add_func失败。这时候可以手动把那块地址 undefine 再重新跑脚本或者改脚本跳过冲突地址。5.4 大文件导致内存溢出现象目标应用很大跑 dump 时工具卡死或者报OutOfMemoryException。原因工具默认把整个 metadata 和二进制读进内存解析文件大了内存扛不住。解决用 64 位版本的 exe如果有的话或者用过滤参数只 dump 需要的部分。另外输出目录所在磁盘要有足够空间dump.cs几百 MB 是常事。5.5 杀毒软件误报拦截现象工具刚解压就被杀毒删了或者跑的时候被拦截。原因逆向工具经常被安全软件标记为风险程序。解决把工具目录加到杀毒软件白名单或者临时关闭实时防护。这个不多说做这行的都懂。6. 进阶用 dump 结果做交叉验证与自动化跑通一次 dump 只是起点真正省时间的是把结果用起来。我一般会做两件事交叉验证和自动化批处理。交叉验证是指拿dump.cs里的方法地址去和 IDA 里的反汇编对照确认符号恢复是对的。具体做法是随便挑几个方法看dump.cs里标注的 RVA在 IDA 里跳过去看函数开头是不是符合 C# 方法的典型 prologue比如STP X29, X30, [SP, #-0x10]!这种 arm64 的栈帧建立指令。如果对不上说明基址或者版本有问题得回头查。这一步花几分钟能避免后面基于错误符号做一堆无用功。自动化批处理是指写个脚本把多个 so 或者多个版本的 dump 串起来跑。比如你要对比两个版本的差异可以分别 dump 出dump.cs然后用 diff 工具对比方法地址和类结构的变化。或者写个 Python 脚本解析stringliteral.json把所有字符串按长度和出现频率排序快速定位可疑的协议字段或者密钥。import json # 读取 stringliteral.json按字符串长度过滤出可疑的长字符串 with open(stringliteral.json, r, encodingutf-8) as f: data json.load(f) # data 结构通常是 {地址: 字符串} 或列表形式按实际输出调整 candidates [] for addr, s in data.items(): if isinstance(s, str) and len(s) 20: candidates.append((addr, s)) # 按长度降序长字符串往往是密钥、URL、协议模板 candidates.sort(keylambda x: len(x[1]), reverseTrue) for addr, s in candidates[:50]: print(addr, repr(s))上面这段脚本的逻辑是从字符串字面量里筛出长度超过 20 的按长度排序取前 50 个。参数20是个经验值太短会混入大量普通标识符太长可能漏掉一些关键串。实际用时可以调整这个阈值也可以加上关键词过滤比如包含http、key、token的优先看。这一步能帮你从几万个字符串里快速缩小范围比一个个翻dump.cs高效得多。另一个进阶用法是把script.py的输出和 Frida 结合。符号恢复之后你知道某个方法的地址和名字就可以写 Frida hook 脚本去动态跟踪调用。静态 dump 加动态 hook两条腿走路分析效率比单用一种高一个量级。我现在的习惯是先 dump 恢复符号用 IDA 静态看关键逻辑再用 Frida 验证运行时行为最后回到dump.cs确认字段偏移。这套流程跑顺了一个中等规模的 il2cpp 目标从拿到文件到定位核心逻辑一两天能出结果。最后说个我自己的教训别迷信工具的自动识别结果。版本号、架构、基址这些每次都要手动确认一遍。我有一次偷懒没检查拿 arm64 的 metadata 配了 armeabi-v7a 的 sodump 出来的地址全是错的基于错误地址 hook 了一整天最后发现是架构不匹配。从那以后我养成了一个习惯跑完 dump 先看方法数量和几个关键类的地址是否合理确认无误再往下做。希望帮到你。本文还有配套的精品资源点击获取

相关推荐

PyTorch+Flask宠物图像识别:从训练到部署全链路实战
PyTorch+Flask宠物图像识别:从训练到部署全链路实战

简介:这份资源是基于PyTorch与Flask构建的宠物图像识别完整项目包,面向具备一定深度学习基础、希望打通从模型训练到Web服务部署全流程的开发者与学习者。包内共2000个文件,以1993张jpg宠物图片作为训练与测试样本,辅以4个Python脚… · 2026/9/26 17:01:47

Go+AI Agent实战:一张商品图生成整套电商详情页
Go+AI Agent实战:一张商品图生成整套电商详情页

1. 为什么我盯上了"一张商品图生成整套详情页"这件事做电商的朋友应该都有体会,详情页是个磨人的活儿。一张主图拍完,运营要写卖点文案、设计要排版、美工要抠图换背景、最后还要拼成一套符合平台规范的详情页长图。一个 SKU 走完这套流程&… · 2026/9/26 17:01:47

SpringBoot健身轻食平台实战:从权限设计到Docker部署全攻略
SpringBoot健身轻食平台实战:从权限设计到Docker部署全攻略

前阵子一个学弟找我帮他搞定毕业设计,课题名称就是“基于SpringBoot的健身服务与轻食间平台系统”。他一开始以为这种课设项目无非就是写个登录、加几个CRUD页面,能跑起来就能交差。但真的从拿到源码到写lw(论文),再到… · 2026/9/26 17:01:47

第三代编程来了!Cursor与Agent浪潮下,TaoToken的配置机遇还是危机?
第三代编程来了!Cursor与Agent浪潮下,TaoToken的配置机遇还是危机?

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 18:09:23

普通人要不要碰 OpenClaw?先配好 TaoToken 网关再谈安全边界
普通人要不要碰 OpenClaw?先配好 TaoToken 网关再谈安全边界

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 18:09:23

Harness Engineering 从入门到精通:用 AGENTS.md 与 Lint 搭建 SDD/TDD 工程骨架
Harness Engineering 从入门到精通:用 AGENTS.md 与 Lint 搭建 SDD/TDD 工程骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 18:09:15

虚拟首席AI官:企业AI落地的系统化指南与实操框架
虚拟首席AI官:企业AI落地的系统化指南与实操框架

1. 从“虚拟首席 AI 官”这个角色说起:企业到底缺的是什么第一次看到“虚拟首席 AI 官”这个说法,我脑子里冒出来的第一个念头是:这不就是给企业配一个“AI 军师”吗?但仔细琢磨之后发现,事情没那么简单。Codos 推出的… · 2026/9/26 18:09:09

Spring AI Tools实战:从@Tool注解到function-call源码解析
Spring AI Tools实战:从@Tool注解到function-call源码解析

做Agent开发的朋友,一定遇到过这种场景:用户问“帮我查一下订单到哪了”,模型一本正经地回你“我暂时无法查询实时物流信息”。这不是模型笨,是因为它本质上是个文本生成器,你给它再多的提示词,它也只能输出… · 2026/9/26 18:08:56

PHP可变函数安全风险深度剖析:从动态调用原理到代码执行防护
PHP可变函数安全风险深度剖析:从动态调用原理到代码执行防护

一个看起来再普通不过的 PHP 语法糖,在某个凌晨会变成一台服务器的“任意代码执行后门”。这不是电影情节,也不是反序列化那种自带流量的漏洞,而是一种长期潜伏在业务代码里的安全隐患——可变函数。它不会像未授权接口那样被扫描器直接报出来… · 2026/9/26 18:08:56

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21

OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40

向下兼容与向上兼容:接口设计中的兼容性策略与工程实践
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践

一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码