返回介绍

第四十四章 - ACProtect V1.09 脱壳(修复 AntiDump)

发布于 2025-01-31 21:07:01 字数 10044 浏览 0 评论 0 收藏 0

我们上一章节介绍了如何定位 stolen bytes,以及 IAT 的修复。我们利用上一章编写的脚本可以很方便的修复 IAT 并且定位到 OEP,接下来我们的任务就是 dump。

我们依然用 OD 加载 UnPackMe_ACProtect1.09,并对 KiUserExceptionDispatcher 入口以及下方的 ZwContinue 调用处分别设置断点,并且清除之前设置的硬件断点。

接着我们执行 OEP.txt 这个脚本定位到 OEP 处。

好了,现在我们到达了 OEP 处。

接下来进行 dump。

这里我们不勾选 Rebuild Import 的选项,将转储出来的文件重命名为 dumped.exe。接下来我们重启 OD,执行修复 IAT 的脚本。

接下来打开 Import Reconstructor,定位到该程序所在进程。

接着就需要填上 OEP(RVA),IAT 起始地址(RVA),IAT 的大小。

OEP = 271B5

IAT 的起始地址(RVA) = 60818

IAT 的大小 = 460F28 - 460818 = 710

点击 Get Imports。

我们会发现有一项是无效的,其他项都是有效的,是不是我们哪里处理的有问题?

我们来跟一下,看看哪里出了问题,重启 OD,我们选中上面显示无效的 IAT 项,设置内存写入断点。

运行起来,断在了尝试对 460DE8 该内存单元进行写入的指令处。

我们会发现 ESP - 0C 指向的栈空间中并没有保存 API 函数的入口地址,而是保存了 46E5CB 这个值。

我们可以看到通过 IAT.txt 脚本,460DE8 这个 IAT 项被保存的是 46E5CB 这个值,那么不通过脚本呢?我们按 F7 执行该指令。

我们可以看到不通过脚本 460DE8 这个内存单元中保存的值是 46BD5B。

我们转到 46BD5B 地址处看看是什么。

这里我们可以看到首先是将一个常量压入堆栈,接着与另一个常量进行异或就可以得到某个 API 函数的入口地址,我们一起来计算一下。

942C0892 xor 946aed59

如果你不想通过计算器来算的话,那么也可以通过 OD 执行这几条指令来得到结果。

这里我们可以看到异或得到的结果是 46E5CB,跟执行 IAT.txt 脚本得到的结果是一致的。也就是问题并不是出在脚本上。应该是其他的某个环节出了问题。我们重启 OD,随便找一个 API 函数跟一下。

我们执行 OEP.txt 脚本到达了 OEP 处,接着依然对刚刚的 460DE8 这个无效的项设置内存访问断点,看看会断在哪里。

断在了这里,我们跟进去看看。

我们跟到 RET 指令处,继续跟进。

这里我们可以看到第一条指令是 PUSHAD,那么根据堆栈平衡原理,可以很自然的想到后面应该有个 POPAD 指令,我们按 F7 键往下跟若干行会到达这里。

这里我们可以看到调用了 MessageBoxA 这个 API 函数。

另一种更加快捷的方法就是通过 OD 的自动跟踪功能来定位,我们设置自动跟踪的终止条件为 EIP 大于 500000,也就是说从当前区段转入到系统 DLL 中去执行 API 函数的时候就会断下来,我们一起来看一看。

这里我们选中 EIP is outside the range。范围设置为 0~500000。下面我们一起来看看效果。

我们可以看到断在了 MessageBoxA 的入口处,为了验证 API 函数的正确性,我们来看看该函数的调用处是哪里,看看堆栈中的返回地址。

这里我们可以看到返回地址是 40E51B,我们直接转到这个地址。

这里返回到的是调用处的下一行,好了,这里我们就得到了正确的 API 函数,我们重启 OD,执行 IAT.txt 脚本,就 OEP,IAT 起始地址,IAT 大小等数据都填入到 IMP REC 中。

我们定位到这个无效的项,双击之,将其修改为 MessageBoxA。

好了,现在所有的项都有效了。接下来修复 dump 文件,选中 dumped.exe,单击 Fix dump。

修复后的 dump 文件被重命名为了 dumped_.exe,别忘了 stolen bytes 我们还没有填充回去,我们用 OD 打开 dumped_.exe。

停在了假的 OEP 处,我们准备好 stolen bytes。

我们将 stolen bytes 以汇编指令的形式填充上。

我们通过计算可知 stolen bytes 总共占 5 个字节长度,4271b5 往上 5 个字节就是 4271b0,也就是说正确的 OEP 应该是 4271b0。

我们从 4271b0 地址处开始写入 stolen bytes。

接下来我们通过单击鼠标右键选择-Copy to executable-All modifications 将刚所做的修改保存到文件。接着我们来将其 OEP 更正。

用 OD 加载刚刚保存的文件,我们可以通过在数据窗口中单击鼠标右键选择-Go to-Expression,输入 400000 定位到 PE 头。

单击鼠标右键选择 Special-PE header 将显示模式切换为 PE 头视图,接下来定位到 AddressOfEntryPoint,将其修改为 271b0 并保存。

好了,现在我们就修复完毕了,但是我们运行修复后的程序会发现无法正常运行,程序崩溃了。好,那么我们不勾选忽略异常的选项,加载刚刚修复过的程序,运行起来,看看会提示哪些异常。

我们可以看到日志窗口中显示了一个非法访问异常。我们通过单击工具栏中的 K 按钮查看调用堆栈。

这里我们可以看到最后一次调用来至于 429806,我们通过单击鼠标右键选择-Show call 定位到该调用处。

单击鼠标右键选择-Follow 看看这个 CALL 里面是什么。

嘿嘿,这里我们我们可以看到一个跳转表,正是由于这些跳转表的目标地址诸如 177658 这类地址才导致程序无法正常运行报错的。

该地址所属的区段是由壳创建的,但是我们并没有 dump 出来。下面我们就来解决这个问题。

我们再开一个 OD,加载原始的程序,执行 OEP.txt 脚本到达 OEP 处。

我们到了这里,我们定位到上面的跳转表。

我们在数据窗口中定位跳转表中唯一一个目标地址,这里我们定位 1775C4。

我们往上定位到第一个跳转,我这里是 46C0F5。

这些跳转指令都占 6 个字节长度,我们随便挑一个目标地址,这里我们选择目标地址为 178250,转到这个地址处,我们会发现其执行会 6 个字节长度的指令,然后返回。

这里我的想法是用这 6 个字节替换掉那跳转表中的 6 个字节。

我们选中这三行指令,单击鼠标右键选择-Binary-Binary copy。

然后定位到相应的跳转指令处,单击鼠标右键选择-Binary-Binary paste。

这里我们可以看到覆盖后的效果。

下面我们来将整个跳转表都替换掉。

我们可以看到跳转表开始于 1772B4。

该跳转表的最后一项为 1782B4,其中的值为 1799BA。(PS:该跳转表的地址在你们的机器上可能不一样)

这里将所有的代码都以二进制的形式拷贝出来,接着以二进制的形式粘贴到跳转表所在区域。

这里我们会发现没有覆盖完全。

可能该壳做了一些干扰吧,没有关系,到目前为止,我们的思路是正确的。好,那么我们直接定位 dump 文件所在的 OD,就这部分二进制数据粘贴上去。效果同上。

(PS:作者处理有点冗余,这里我稍微修改了下,让大家更好理解)

接着保存所做的修改到文件,运行修复过的文件看看效果。

我们可以看到程序可以正常运行了,至此关于 ACProtect V1.09 的 OEP 定位,stolen bytes,IAT,AntiDump 的修复我们就介绍完毕了。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文