- 第一章 - OD 的各个窗口介绍
- 第二章 - 数值系统
- 第三章 - 寄存器
- 第四章 - 汇编指令
- 第五章 - 数学指令
- 第六章 - 比较和条件跳转
- 第七章 - call ret
- 第八章 - 循环 字符串指令和寻址方式
- 第九章 - 基本概念
- 第十章 - 断点
- 第十一章:硬件断点与条件断点
- 第十二章 - 消息断点
- 第十三章 - 硬编码序列号寻踪-Part1
- 第十四章 - 硬编码序列号寻踪-Part2
- 第十五章 - 硬编码序列号寻踪-Part3
- 第十六章 - 序列号生成算法分析-Part1
- 第十七章 - 序列号生成算法分析-Part2
- 第十八章 - 序列号生成算法分析-Part3
- 第十九章 - OllyDbg 反调试之 IsDebuggerPresent
- 第二十章 - OllyDbg 反调试之检测 OD 进程名
- 第二十一章 - OllyDbg 反调试之检测 OD 进程名,窗口类名,窗口标题名
- 第二十二章 - OllyDbg 反调试之 UnhandledExceptionFilter,ZwQueryInformationProcess
- 第二十三章 - OllyDbg 反调试之 ProcessHeap,NTGlobalFlag,OutputDebugStringA
- 第二十四章 - OllyDbg 反调试之综合 CrackMe
- 第二十五章 - 异常处理
- 第二十六章 - Visual Basic 程序的破解-Part1
- 第二十七章 - Visual Basic 程序的破解-Part2
- 第二十八章 - Visual Basic 程序的破解-Part3
- 第二十九章 - P-CODE-Part1
- 第三十章 - P-CODE-Part2
- 第三十一章 - 脱壳简介
- 第三十二章 - OEP 寻踪
- 第三十三章 - 神马是 IAT 如何修复
- 第三十四章 - 手脱 UPX,修复 IAT
- 第三十五章 - 手脱 ASPack V2.12
- 第三十六章 - IAT 重定向
- 第三十七章 - 论 IAT 重定向之修复
- 第三十八章 - 手脱 Yoda's Protector v1.3(Yoda's Crypter)
- 第三十九章 - 神马是 stolen bytes
- 第四十章 - OllyDbg 脚本的编写
- 第四十一章 - 神马是 AntiDump
- 第四十二章 - ACProtect V1.09 脱壳(寻找 OEP 绕过硬件断点的检测 修复 Stolen code)
- 第四十三章 - ACProtect V1.09 脱壳(编写脚本修复 IAT)
- 第四十四章 - ACProtect V1.09 脱壳(修复 AntiDump)
- 第四十五章补充章节-ReCrypt v0.80 脱壳(续)
- 第四十六章 - Patrick 的 CrackMe-Part1
- 第四十七章 - Patrick 的 CrackMe-Part2
- 第四十八章 - PeSpin V1.3.04 脱壳-Part1
- 第四十九章 - PeSpin V1.3.04 脱壳-Part2
- 第五十章 - 再谈 ReCrypt v.0.80 脱壳(调戏 OutputDebugString)
- 第五十一章 - ASProtect v2.3.04.26 脱壳-Part1
- 第五十二章 - ASProtect v2.3.04.26 脱壳-Part2
- 第五十三章 - TPPpack 脱壳
- 第五十四章 - EXECryptor v2.2.50.a 脱壳-Part1
- 第五十五章 - ExeCryptor v2.2.50.a-Part2
- 第五十六章 - EXECryptor v2.2.50.b 脱壳
- 第五十七章 - ExeCryptor v2.2.50.c/d/e/f/g 脱壳
- 第五十八章 - ExeCryptor v2.2.50
第三十八章 - 手脱 Yoda's Protector v1.3(Yoda's Crypter)
上一章节给大家介绍了 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论