返回介绍

第三十八章 - 手脱 Yoda's Protector v1.3(Yoda's Crypter)

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

上一章节给大家介绍了 IAT 重定向以及修复方法。本章我们稍微增加一点难度。

我们一起来脱 Yoda Crypter v1.3,首先大家配置好 OD 的反反调试插件,加载它。

断在了入口点处。

我们可以看到这里有个 PUSHAD 指令,嘿嘿,我们可以使用 ESP 定律来定位 OEP,我们单步到 PUSHAD 指令处,按 F7 键单步执行 PUSHAD 指令。

然后在 ESP 寄存器的值上面单击鼠标右键选择-Follow in Dump,这样就能在数据窗口中定位到刚刚保存的寄存器环境了,我们选中前 4 个字节,单击鼠标右键选择-Breakpoint-Hardware,on access-Dword,对其设置硬件访问断点。

运行起来。

断在了这里,我们可以看到这里将给 SEH 链添加一个新的节点,接着通过 JMP 指令跳转到下面引发一个异常,我们跟到 JMP 指令处。

这里将跳往下面,将产生异常。我们来看看异常处理程序在哪里。

选择主菜单项中的 View-SEH chain。

我们可以看到刚刚安装的异常处理程序入口地址为 46590B,不出意外的话到达该异常处理程序,随后就会到达 OEP,我们给第一个区段设置内存访问断点,触发异常后,随即我们就会到达 OEP 处。

直接运行起来。

断在了 OEP 处,这里 OEP 为 4271B0,大家应该很熟悉了吧,我们加壳的目标程序都是同一个 CrackMe,嘿嘿。

如果要深究的话,大家会发现异常处理函数中 Context 结构的 EIP 寄存器的值由 465982 修改为了 4271B0,即 OEP,关于 CONTEXT 结构体的详细介绍我们后面章节再说。

好,现在我们到了 OEP 处,可以 dump 了。

这里我们不勾选 Rebuild Import 选项。

这里我们将其重命名为 yodadump.exe,我们会发现程序无法正常运行。我们需要修复 IAT。

下面我们来分析一下 IAT,随便找一个 API 函数的调用处,这里我们还是跟之前一样拿 CALL GetVersion 开刀,嘿嘿。

我们定位到 4271D6 处 CALL DWORD PTR DS:[460ADC]指令,460ADC 是 IAT 中的一项,我们在数据窗口中定位到这个地址。

这部分 IAT 项看起来像是正常的,我们打开区段列表窗口,看看这部分 IAT 项属于哪个系统 DLL,这里我们可以看到这部分 IAT 项命中在 Kernel32.dll 的代码段,即这部分 IAT 项是正确的。

再随便选一项单击鼠标右键选择-Find references(查看一下参考引用),这里我选择 460B34 这一项。

继续往下:

这里我们可以看到粉红色标注出来的区域,我们在区段列表窗口中看看这部分属于哪个区段。

我们可以看到不属于系统 DLL,该区段应该是由壳创建的,我们重启 OD,来验证一下。

我们可以看到此时起始地址为 150000 的区段,长度为 3000 字节,但是壳执行以后,该区段变成了 29000 字节,即可壳将该区段增大了,并且增大的部分供自己使用。

该区段是用于重定向 IAT 的部分元素的,我们具体来分析一下。

随便找一个举例,这里我们将拿 460BAC 这一项来说,我们来看看其参考引用,选中该项,单击鼠标右键选择-Find references。

这里我们可以看到有两处参考引用,我们直接在第一条记录上面双击,定位到了这里。

定位到这个 CALL 处,我们在其上面单击鼠标右键选择-Follow,看看被重定向到了哪里。

我们可以看到重定向到这里,并没有过多的弯弯绕就直接 JMP 去调用 SysStringLen 这个 API 函数了,这样我们就知道其真正要调用的 API 函数了。

这个重定向比较简单,我们打开 IMP REC,看看能不能用 IMP REC 自带的 Trace 功能进行修复,不过修复不成功,我们再来手动分析。

打开 IMP REC。

定位到 unpackme_yoda’s crypter1.3 所在进程,当前其断在了 OEP 处,填写上 OEP,IAT 起始地址的 RVA,IAT 长度。

OEP = 4271B0 - 映像基址 400000 = 271B0 (RVA)。

我们现在来定位 IAT 的起始位置,往上拉。

这一部分是重定向到起始地址为 150000 的区段的,我们继续往上。

这里我们可以看到 460810 这一项为 80000008,明显不是 IAT 项,继续往上的一部分是以 6XXXX 的形式,我们看看 460804 这一项的参考引用情况,会发现没有引用该项的地方。

因此,IAT 的起始地址为 460818,IAT 起始地址的 RVA = 460818 - 400000(映像基址) = 60818。

下面我们再来看看哪里是 IAT 的结束位置。

这里 460f24 是 IAT 的最后一项的地址,因为后面 460F2C 这一项定位不到参考引用处。所以 460f28 是 IAT 的结束位置。现在我们来计算一下 IAT 的大小。

IAT 的大小 = 结束地址 - 起始地址 = 460F28 - 460818 = 710。

因此

OEP 的 RVA = 271B0

IAT 起始地址的 RVA = 60818

IAT 的长度 = 710

将这个三个值填到 IMP REC 中去。

单击 Get Imports 按钮。

这里我们可以看到有 296 项被 IMP REC 标识为了无效,我们来试试 IMP REC 内置的 Tracer 能不能修复这些项。如果单击右边的 Auto Trace(自动跟踪) 按钮的话,IMP REC 将被挂起(像卡死了一样)。我们再来试试其他的 Tracer,首先单击右边的 Show Invalid,接着在显示出来的无效项上面单击鼠标右键选择-Trace Level1(Disasm)。

可以看到这里提示所有无效项均被修复,嘿嘿,我们再次单击 Show Invalid,可以看到所有的项都被标记为有效。

我们单击 Fix Dump 对刚刚 dump 出来的文件 yodadump.exe 进行修复。

修复后的文件被重命名为了 yodadump_.exe,我们运行试试。

嘿嘿,正常运行。

下面我们来看看如何定位该壳的关键跳。

首先让程序停在 OEP 处,接着随便定位一个重定向过的 IAT 项。

我们给 460ECC 这一项设置硬件写入断点,接着如果我们重启 OD 的话,硬件断点依然存在。

当 460ECC 地址处被写入的时候 OD 就会断下来,我们直接运行起来。

断在了这里,这里向 460ECC 中写入的是一个正常的值,此时,EAX 包含了一个 API 函数的地址。

EDX 的值 460ECC,即指向了之前我们设置了硬件断点的那个重定向的 IAT 项,这里其被写入的是正确的值,随后会被修改为重定向过的值,我们继续往下跟,看看会发生什么。

我们跟到这里,这里 460ECC 中将被写入重定向过的值,ESI 此时保存的就是重定向过的值。

也就是说正常的 IAT 项只会被写入一次,而需要被重定向的项将被写入两次。

下面我们来看看正常的 IAT 的项的处理流程,就拿 OEP 下面调用的 GetVersion 这个 API 函数来说吧,即 460ADC 处将被壳填充上正常 IAT 值,我们对其设置硬件写入断点,运行起来。

断在了这里,此时 EAX 保存正确 API 函数地址,将写入到 460ADC 中。

继续往下跟一点点。

这里我们可以看到 46577F 这一处 JMP 指令,其将跳过红色箭头标注的设置为重定向值的指令,所以这里是关键跳,之前还有几处条件跳转,这里我们来尝试 NOP 掉写入重定向值的指令,看看效果如何。

首先给 465799 这条指令设置硬件执行断点,这里我们并不向想其被写入重定向的值,所以给其上一行设置硬件执行断点。

断了下来,我们将写入重定向值的指令 NOP 掉。

下面我们来看看该壳会不会检测自身代码被 NOP 掉了,我们运行到 OEP 处。

删除硬件断点,运行起来。

程序无法正常运行,可能是壳有自校验,检测到自身被修改了报错,所以我们不能 NOP,我们继续来到关键跳处。

我们随便跟一个将被重定向的项,跟到关键跳附近,可以看到 46577D 处的条件跳转将直接跳到下面,这样 46577F 处的关键跳将得不到执行,接着将被写入重定向的值,我们尝试将 46577D 这处条件跳转 NOP 掉,让其直接执行 46577F 处的 JMP 指令,我们来看看效果。

依然是报错。

那么我们来看看 IAT 吧,我们可以看到 IAT 项都被修复了,都是正确的。这里我们有两种选择: 一,再开一个 OD,加载该 CrackMe 的另一个实例,直接跟到 OEP 处,不修改任何东西,然后将当前我们这个实例的正确的 IAT 复制出来,覆盖掉新开的这个实例的 IAT,注意是二进制复制,这个方法比较简单。二,直接用 IMP REC 定位到 CrackMe 的进程,此时 IAT 全部被写入正确的值了,但是还未到达 OEP 处,我们直接填上 OEP,RVA,SIZE 等数据,没有到达 OEP 处没有关系,我们单击 Get Imports。

我们可以看到所有的 IAT 项都是正确的,直接单击 Fix Dump 修复之前 dump 出来的文件即可。

运行修复过的 yodadump_.exe,看看效果。

我们可以看到正常运行。本章到此为止。

给大家留个练习 unpackme_FSG_1.31_dulek。比较简单,大家应该不会觉得很难。

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

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

发布评论

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