使用OllyDbg从零开始Cracking 第三十八章-手脱Yoda's Crypter v1.3
第三十八章-手脱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是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 = 271B0IAT起始地址的RVA = 60818IAT的长度 = 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。比较简单,大家应该不会觉得很难。本系列文章汉化版转载看雪论坛
感谢原作者:RicardoNarvaja(西班牙人) 原作者个人主页:http://www.ricardonarvaja.info/
感谢热心翻译的朋友:1~3章译者:BGCoder4~58章译者:安于此生
全集配套程序下载地址:
链接: http://pan.baidu.com/s/1eQzTWfo 密码: vytv
希望出个视频教程,这样好点理解 奉上小小红包希望笑纳 不错,感谢楼主分享! 666,学到了 希望继续更新! 好好学习下看看! 谢谢站长大佬分享教程
页:
[1]
2