vs2019 - 使用IDA定位已经被捕获的异常

本文介绍了如何使用VisualStudio2019和IDAPro配合,找出并修复程序中被try-catch捕获的异常,包括加载调试版本的EXE,设置断点,以及改进编码实践以利用IDE的输出窗口进行异常追踪。

vs2019 - 使用IDA定位已经被捕获的异常

概述

正在测试程序的功能, 用VS2019开着调试版跑起来. 发现程序关闭后, 在VS2019的输出窗口发现了C++异常的信息, 还不是一条.
在这里插入图片描述
虽然不影响程序的运行, 但是心里膈应.
这种异常发生了, 但是没被VS2019断下来, 说明这4个C++异常是在工程中被try-catch住的.
我现在这个程序, 主动使用try-catch的地方不多. 如果在每个try-catch住的地方下断点倒是可以.
但是为了普遍性, 还是要找出一种不依赖断点无脑排错的调试方法.

笔记

将debug版编译好, 用IDA带着跑起来.
用IDA载入EXE时, 因为是载入的Debug版程序, 连同PDB一起载入.
选择本地调试器
在这里插入图片描述
跑起来.
进行一样的操作, 发现IDA断住异常了:)
在这里插入图片描述
按确定后, 让程序自然暂停住.
打开栈调用链窗口
在这里插入图片描述
在这里插入图片描述
因为出了异常, 栈调用链不是很准.
但是能看到最上层的函数是COrderOperation::static_thread_dispatch().
那现在就可以有的放矢了, 关掉IDA.
只在COrderOperation::static_thread_dispatch()上下断点.
然后重新用VS2019跑程序, 到了发现报错的疑似顶层函数, 步入, 然后步过, 看看执行过那步, 会在VS2019输出窗口显示被捕获的异常信息.
如此这般, 就会很快缩小排查范围. 最后定位并修复问题.

我这里发下的问题是, 删除文件的函数做了try-catch, 如果删除了不存在的文件, 就会抛异常, 并被函数内的catch捕获住. 修正如下:

bool CFileOperation::Delete(CString sPathName)
{
	try {
		// 如果文件存在, 才删除, 防止出异常.
		// 虽然这里被catch住了, 总的来说不好
		if (!this->IsFileExist(sPathName))
		{
			return true;
		}

		DoDelete(sPathName);

	} catch (CFExeption* e) {
		m_sError = e->GetErrorText();
		m_dwError = e->GetErrorCode();
		delete e;

		if (m_dwError == 0) {
			return true;
		}

		return false;
	}

	return true;
}

备注

虽然被try-catch住的异常, 不会引起程序的功能出问题. 但是也说明可能哪里出了问题, 如果能在逻辑上将异常搞定, 让他不出异常, 感觉更好一点.

修正完后, 又跑了一次, 程序退出后, 在VS2019的输出窗口没有任何发生c++异常的提示信息了:P

补充

又想了一下, 既然是自己try-catch, 那么自然知道是哪里catch的, 为何不在catch中, 用框架提供的功能, 整点动静出来, 这样, 也不用第三方调试器辅助调试了.
在这里插入图片描述
在VS2019Debug版程序退出后, 如果在输出窗口看到自己catch住的打印信息的输出, 双击就可以定位到catch住异常的地方了.
这属于自己编码不规范引起的问题.

当然, 发现异常后, 如果有可能修复, 还是要修复.

备注

这种用IDA来辅助定位问题的方法, 对于自己的工程可能有点脱裤子放屁的感觉.
但是对于自己接手维护的不规范工程(e.g. 不是自己写的工程(刚接手, 还没深入理解), 开源工程(代码行数大, 看不过来, 刚接触的工程, 逻辑理解的有点懵懂), 遗留的烂工程(可能就是自己以前写的工程)), 还是管点用.

END

<think>好的,用户现在的问题是想要了解如何解密并重组被分段加密的`global-metadata.dat`文件,并且提到了使用GG修改器和il2cppdumper工具。根据之前的对话,用户已经尝试过使用GG修改器进行内存dump,但得到的文件比原文件小,无法正常使用il2cppdumper。现在用户需要更具体的指导来解决分段加密的情况。 首先,我需要回顾之前的回答。在之前的解决方案中,提到了动态Hook、逆向解密算法以及内存dump与修复的方法。用户现在特别关注的是分段加密的情况,所以需要扩展这些方法,尤其是如何重组被分段的加密数据。 接下来,需要分析用户当前的引用内容。引用[1]提到对libil2cpp.so进行深度加密会影响il2cppdumper的依赖,这可能导致用户遇到的元数据文件被加密的问题。引用[3]提到使用il2cppdumper时需要输入两个offset,这可能与分段加密后的重组有关。引用[4]提到了资源文件的偏移设置,可能涉及如何定位分段后的数据块。 用户的问题主要集中在分段加密的重组上,所以需要详细说明如何识别分段、如何定位各个段在内存中的位置、如何dump这些段,以及如何将它们合并成完整的文件。同时,用户提到使用GG修改器和il2cppdumper,因此需要结合这些工具的具体操作步骤。 首先,分段加密可能意味着`global-metadata.dat`被分成多个部分,每个部分单独加密存储。在运行时,这些分段会被解密并加载到内存中的不同位置。因此,用户需要找到这些内存区域,分别dump,然后合并。 步骤可能包括: 1. 使用GG修改器搜索特征值或魔数来定位每个分段的起始和结束地址。 2. 确定分段的数量和顺序,可能需要分析内存中的数据结构或使用动态调试工具。 3. 分别dump每个分段的数据,并验证其有效性。 4. 合并分段,修复文件头,确保il2cppdumper能够识别。 在动态调试方面,Frida脚本可能有助于自动化这一过程,比如hook内存加载函数,记录每个分段的加载地址和大小。对于重组,可能需要手动分析内存布局,或根据文件结构特征进行拼接。 另外,用户可能遇到的分段加密可能具有不同的加密算法,或者每个段使用相同的密钥但不同的IV,这可能需要逆向解密函数来获取解密逻辑。如果无法直接解密,可能需要依赖运行时内存中的明文数据进行重组。 最后,需要验证重组后的文件是否正确,确保il2cppdumper能够处理,并生成正确的dump.cs文件。如果重组后的文件仍有问题,可能需要进一步修复文件头或调整元数据段的偏移。 总结来说,回答需要分步骤详细说明定位分段、dump内存、合并数据以及修复文件的步骤,同时结合GG修改器和Frida等工具的具体使用方法,并考虑可能的异常情况和解决方法。</think>### 针对分段加密的 `global-metadata.dat` 解密与重组方法 若 `global-metadata.dat` 被分段加密,需通过动态内存分析与数据重组技术恢复完整元数据文件。以下是详细操作流程: --- ### **一、分段加密的识别与定位** #### 1. **特征值定位分段** - **原理**:分段加密的 `global-metadata.dat` 在内存中可能以块状结构存在,每段可能包含固定特征(如魔数 `0xFAB11BAF` 或元数据标识符 `Assembly-CSharp`)。 - **步骤**: 1. **使用 GG 修改器搜索特征值**: - 启动游戏并加载到主界面。 - 在 GG 修改器中按字节序(如 `AF 1B B1 FA`)搜索魔数 `0xFAB11BAF`,记录所有匹配的内存地址。 - 若魔数被加密掩盖,改用元数据特有字符串(如 `System.String`)模糊搜索。 2. **验证分段边界**: 对每个匹配地址,查看其附近内存区域的十六进制数据,判断是否为有效元数据段(如包含类名、方法名等可读字符串)。 #### 2. **动态 Hook 捕获分段加载** - **工具**:Frida 或 LLDB。 - **步骤**: 1. **Hook 内存加载函数**: 拦截 `mmap` 或 `memcpy` 函数,捕获解密后的分段数据块。 ```javascript // Frida 脚本示例:拦截 mmap 调用 Interceptor.attach(Module.findExportByName(null, "mmap"), { onEnter: function(args) { this.size = args[1].toInt32(); }, onLeave: function(retval) { if (this.size > 0x1000) { // 过滤大内存块 var data = Memory.readByteArray(ptr(retval), this.size); if (data.includes("Assembly-CSharp")) { console.log("[*] Metadata segment at:", retval, "size:", this.size); // 保存分段数据 var file = new File("/sdcard/metadata_segment.bin", "wb"); file.write(data); file.close(); } } } }); ``` 2. **记录分段地址与大小**: 通过日志收集所有可能的分段位置,用于后续重组。 --- ### **二、分段数据的 Dump 与重组** #### 1. **使用 GG 修改器导出分段** - **步骤**: 1. 对每个定位到的分段地址,使用 GG 修改器的 **内存导出** 功能,保存为独立文件(如 `segment1.bin`, `segment2.bin`)。 2. **验证数据完整性**: 用十六进制工具(如 HxD)检查导出文件是否包含元数据特征(如 `0xFAB11BAF` 或可读字符串)。 #### 2. **手动重组分段** - **原理**:分段可能按顺序加载或通过索引表关联。 - **步骤**: 1. **合并分段文件**: 按内存地址升序拼接分段文件(如 `cat segment1.bin segment2.bin > merged.dat`)。 2. **修复文件头**: 若合并后文件头部无效,参考正常 `global-metadata.dat` 的头部结构(如 `;FFMETADATA1`)手动修复[^4]。 ```bash # 示例:使用 dd 命令替换头部 dd if=normal_header.bin of=merged.dat bs=1 count=16 conv=notrunc ``` #### 3. **自动化重组脚本** - **工具**:Python + 010 Editor 模板。 - **步骤**: 1. 编写脚本识别分段边界(基于魔数或固定偏移)。 2. 按逻辑顺序拼接分段并修正校验和。 ```python def merge_segments(segments, output_file): with open(output_file, 'wb') as f_out: for seg in sorted(segments, key=lambda x: x['address']): with open(seg['path'], 'rb') as f_in: f_out.write(f_in.read()) ``` --- ### **三、使用 Il2CppDumper 处理重组文件** #### 1. **适配非常规文件** - **问题**:重组后的文件可能因填充或偏移错误导致 Il2CppDumper 报错。 - **解决方案**: - **指定自定义偏移**: 运行 Il2CppDumper 时手动输入元数据起始偏移(参考引用[3]中提到的 `174E858` 和 `1739C10`)。 ```bash Il2CppDumper -m merged.dat -s 0x174E858 -o 0x1739C10 ``` - **修改 Il2CppDumper 源码**: 调整 `Metadata` 类的解析逻辑,跳过无效填充数据[^1]。 #### 2. **验证输出结果** - **关键检查点**: 1. 生成的 `dump.cs` 是否包含完整类名和方法名。 2. 使用 IDA 或 Ghidra 加载 `libil2cpp.so` 时,能否通过脚本自动关联符号。 --- ### **四、对抗分段加密的高级技巧** #### 1. **内存连续性分析** - **原理**:分段在内存中可能连续存放,通过计算相邻分段地址差推断总长度。 - **工具**:GDB 或 Frida 脚本遍历内存映射。 ```javascript // Frida 脚本:遍历内存模块 Process.enumerateRanges('r--').forEach(function(range) { if (range.size > 0x10000) { // 过滤大内存块 var data = Memory.readByteArray(range.base, 4); if (data[0] === 0xAF && data[1] === 0x1B && data[2] === 0xB1 && data[3] === 0xFA) { console.log("[Metadata Segment]", range.base, "-", range.base.add(range.size)); } } }); ``` #### 2. **动态解密函数模拟** - **适用场景**:分段使用不同密钥加密。 - **工具**:Unicorn 引擎。 - **步骤**: 1. 逆向 `libil2cpp.so` 中的解密函数。 2. 模拟执行函数,逐段解密后合并。 --- ### **五、实战工具链总结** | 工具/方法 | 用途 | 示例场景 | |--------------------|-------------------------------|------------------------------| | GG 修改器 | 内存搜索与分段导出 | 定位加密分段并快速 Dump | | Frida | 动态 Hook 与自动化脚本 | 拦截内存加载函数捕获分段 | | 010 Editor | 十六进制编辑与模板修复 | 手动修复文件头或填充数据 | | 自定义 Python 脚本 | 分段合并与校验 | 按逻辑顺序重组多段数据 | | 修改版 Il2CppDumper| 适配非常规元数据文件 | 跳过填充或自定义偏移解析 | --- ### **相关问题** 1. **如何判断分段加密是否使用不同的密钥?** 2. **重组后的文件仍无法解析时如何调试?** 3. **如何利用 IDA 直接关联分段加密的元数据?** 4. **是否有公开工具支持自动化分段重组?** [^1]: 深度加密会破坏 Il2CppDumper 对字符串地址的依赖,需动态提取解密后数据。 [^2]: 文件头修复需严格遵循 `;FFMETADATA` 格式定义,否则解析工具会报错。 [^3]: Frida 的注入能力使其成为动态分析的理想工具,但需注意反调试对抗。 [^4]: Unity 资源偏移机制可能导致元数据分段存储,需结合内存布局分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值