使用OllyDbg从零开始Cracking 第三十六章-IAT重定向
第三十六章-IAT重定向本章我们继续增加壳的难度,将看两款壳,分别是bitarts 5.0,telock 0.98,telock 0.98会涉及到本章我们要讨论的IAT 重定向的知识点。我们先拿简单的bitarts 5.0开刀,用OD加载它。第一行不是用PUSHAD保存寄存器环境,我们按F7键往下跟。这里我们跟到PUSHAD指令处,按F7执行该指令,接着在寄存器窗口中定位到ESP寄存器的值,在其上面单击鼠标右键选择-Follow in Dump。给前4个字节设置硬件访问断点。按F9键运行起来(遇到异常忽略掉),断了下来。往下单步跟几行就能到达OEP处。大家也可以使用OD自带的功能选项定位OEP,前面OEP章节中介绍的方法大家可以一一尝试。OEP命中在第一个区段。第一个区段为代码段,OD不会弹出入口点不在代码段的提示框。这里我们可以看到调用的第一个API函数是GetVersion,我们可以在一开始给GetVersion设置一个断点,运行起来,接着会断下来,看看返回地址是不是位于第一个区段,如果是就定位到返回地址处,上面就是OEP了。定位OEP很容易,这里不再赘述了,下面我们来看下IAT。460ADC是IAT中的一项,其中保存的是GetVersion的地址,我们在数据窗口中定位到IAT。这个IAT有点大,嘿嘿。这个IAT项存放的是GetVersion的地址,属于Kernel32.dll,我们也可以在区段列表窗口中看看7Cxxxxxx的地址属于哪个DLL。绿色标注的项大部分都是属于Kernel32.dll的,中间夹杂着几项NTDLL.dll的,这几项是用Kernel32.dll中的相应函数替换了,各个DLL的IAT项被零隔开了。下面我们来看看77xxxxx这类是属于哪个DLL的,我们除了在区段列表中看,也可以在770F48C0这一项上面单击鼠标右键选择-Find references。这里可以看到参考引用列表。这里可以看到基本上都是在第一个区段中调用的OleAut32.dll中的VariantClear这个API函数。区段列表窗口中我们也可以看到770xxxxx这类地址是属于OleAut32.dll的代码段的。这里我们就不一一看其他DLL的IAT项了,直接定位到IAT的尾部。这里用湛蓝色,粉红色,灰色分别标注了不同DLL的IAT项,分割的零用绿色标注出来,在最后一个IAT项上面单击鼠标右键选择-Find references。我们可以看到最后一个IAT项是属于oledlg.dll中OleUiBushA这个API函数,我们在区段列表窗口中来验证一下。下面的几项都不是IAT项了。我们在6C50000B上面单击鼠标右键选择-Findreferences。可以看到参考引用列表是空的,所以说IAT的最后一项的起始地址为460F28。我们再来看看哪里是IAT的起始位置。这里可以看到460810里面的值是80000008,明显不会属于任何一个Dll,我们可以在查看一下其参考引用列表来验证一下,在其上面单击鼠标右键选择-Findreferences。可以看到参考引用列表也是空的,说明IAT的第一项的起始地址为406818。现在我们知道了IAT的起始地址和结束位置,我们来计算一下IAT的大小:IAT大小 = 460F28 - 460818 = 710。IMP REC需要的三条数据:OEP = 271B0(RVA)IAT起始地址 = 60818(RVA)IAT 大小 = 710下来我们用OllyDump插件来dump。这里不够选Rebuild Import,仅仅dump。打开IMP REC,定位到bitarts所在的进程,当前该进程处于OEP处。将OEP,RVA,Size的值都设置上。单击Get Imports。可以看到该壳在IAT中添加垃圾数据,修复的IAT项都是有效的,单击Fix Dump,选择刚刚dump出来的文件修复之。修复过的程序被命名为unpacked_.exe,运行一下看看效果。完美运行,没有AntiDump,比之前介绍的壳稍微复杂一点点。下面我们来看看telock 0.98这款壳,该壳涉及到了我们将要介绍的IAT 重定向的知识点。这里我们依然用ESP定律来定位OEP,单步跟几步就能看到PUSHAD指令。按F7键执行PUSHAD指令,接着在寄存器窗口中定位到ESP寄存器的值,在其上面单击鼠标右键选择-Follow in Dump。给前4个字节设置硬件访问断点,运行起来。单击鼠标右键选择-Analysis-Remove analysis from module删除掉OD的分析结果。我们可以看到断在了这里。这说明ESP定律不起作用,有可能该壳会检测硬件断点,我们继续运行的话会提示错误,所以我们暂时先把硬件断点删除掉。重启OD。ESP定律行不通,我们来尝试一下最后一次异常法,首先清空日志窗口。忽略异常的选项都不勾选,运行起来,可以看到壳的解密例程产生的最后一处异常是4666F1处。运行起来,遇到异常直接Shift+ F9忽略掉,直到断在4666F1处为止。给第一个区段设置内存访问断点。接着Shift + F9运行起来,遇到异常就Shift + F9,不一会儿就会断在位于第一个区段中的OEP处。因此OEP是4271B0,这里的原程序和上一个例子的原程序是一样的,加的壳不一样而已。我们知道上一例子原程序调用的第一个API函数是GetVersion,但是这个例子我们并没有看到GetVersion的提示信息,被重定向过了。我们来看看调用了哪些API函数,在反汇编窗口中单击鼠标右键选择-Search for-All intermodular calls。我们可以看到这些CALL都被重定向到了其他区段。这些间接CALL并不是去调用系统DLL的中API函数,而是转向了9Fxxxx这类地址的一个区段,这里在我的机器上是9Fxxxx,大家的机器上不一定是这个地址。如果大家往下看的话,会发现还是有一些直接调用API函数的,但是大部分还是CALL 9Fxxxx这类指令。这里这些直接调用API函数的项我用湛蓝色标注出来了。这里我们定位到435FA5这处,这里是CALL 435CDE,OD提示是一个间接跳转到API函数的入口处,我们在这条指令上单击鼠标右键选择-Follow。我们可以看到是一些间接跳转去调用API函数,很明显这里是IAT中的一些项,我们在数据窗口中定位到460ED4这一项。这里我们可以看到IAT中的最后一部分是正确的,跟上一个例子一样,IAT的结束地址为460F28,下面全是零了。往上看,这里用湛蓝色标注出来的这一部分,这一组里面的其他项形式跟76B1A8F7这一项形式不一样,我们在76B1A8F7这一项上面单击鼠标右键选择-Find references。我们可以看到调用的是WINMM.dll中的PlaySoundA这个API函数,我们再来看看其他项的参考引用。这里我们可以看到参考引用的一些项,但是都是一些指针,并不是调用某个系统DLL中的API函数,我这里是Axxxxx的形式(换一台机器这类数值可能不一样),这类数值是什么呢?这些就是IAT中重定向的一些项,当程序运行起来时,壳的解密例程会覆盖掉IAT中的某些项,将这些项重定向到解密例程中,我们拿4038A6这处为例:这里并不是直接调用API函数,壳将这一项覆盖为了自己所在区段中的一个地址。为了更好的理解这一点,我们来看看GetVersion这个API函数,在OEP的下面。其实,这里原本我们并不知道是调用的GetVersion,但是该原程序跟上一个例子是相同的,所以可以断定这里是调用GetVersion,这里是一个间接CALL,我们按F7键跟进,看看里面是什么。我们到了9F06F7处。这里我的机器上是9F06F7,大家的机器上这个地址可能会不一样,该地址不属于原程序的区段。这里我们可以看到区段列表窗口,湛蓝色标注出来的是原程序区段,9F06F7命中在下面这个没有标注名称起始地址为9F0000的区段。如果我们重启OD断在入口点处时,会发现这个时候该区段并不存在。因此,这个内存块是在壳解密例程运行过程中创建的,我们来看看它是什么时候被创建的。我们给VirtualAlloc这个API函数设置一个断点,这个函数是用来申请内存空间的。忽略异常的选项都勾选上,按shift + F9运行起来,程序直接结束了,很明显该壳会检测我们设置的API断点,我们将断点设置VirtualAlloc的RET处。运行起来。断了下来,EAX的值为3C0000,继续运行。这里我们可以在区段列表窗口中看看刚刚创建的这个内存块。我们可以看到该内存块被标记为了Priv(私有的),也就是说该内存块是壳自己创建的。这里我们删除之前设置的断点,按前面介绍的步骤利用最后一次异常法再次定位到OEP处。我们再次定位到OEP处,来看看区段列表窗口。可能看到起始地址为9F0000这块内存空间也被标记为了Priv,IAT项中的值会被重定向到这里,我们按F7键单步到9F06F7处。定位到了9F06F7处。往下跟几步,可以看到这里的PUSH指令将GetVersion的地址压入到堆栈中,接着RET将会返回到GetVersion的入口处,这样就可以达到间接调用API函数的目的。也就是说,壳会将GetVersion的IAT项替换成自己创建的内存单元中的地址,起到了一个重定向的作用。因此我们在定位IAT的起始和结束位置的时候,不仅仅要判断是否为系统DLL中的地址,还是需要判断其是否为重定向过的地址。下面我们继续来定位IAT的起始和结束位置。湛蓝色标注出来的这部分形式为Axxxxxx的地址是被重定向过的,被重定向到了壳的代码中,我们继续往上定位IAT的起始位置。这部分湛蓝色标注出来的,有几项是属于系统DLL,其他项形式为9Fxxxx,指向了壳创建的内存单元中。我们来看看460AC0这一项参考引用,的确是重定向到壳刚刚创建的内存块中,我们继续往上看。这里用橙色标注出来的项,其中形式为A1xxxx的地址属于壳创建的另一个内存块。我们看看460894这一项的参考引用。我们继续往下,我们看到这里:这几项用橙色标注出来的是属于系统DLL的。再往下就是零了,左边一项是80000000,明显不属于任何一个内存单元。所以IAT的起始地址为460818,长度为710,OEP为4271B0。OEP = 271B0(RVA)IAT起始地址 = 60818(RVA)IAT长度 = 710我们打开IMP REC,定位到telock0.98所在的进程。将OEP,IAT起始地址,长度的值都填上。单击Get Imports。我们可以看到IMP REC检测到了重定向过的项,但是提示无效,我们单击右边的Show Invalids(显示无效的项)。关于这些重定向的IAT项如何修复我们在下一章节继续讨论。本系列文章汉化版转载看雪论坛
感谢原作者:RicardoNarvaja(西班牙人) 原作者个人主页:http://www.ricardonarvaja.info/
感谢热心翻译的朋友:1~3章译者:BGCoder4~58章译者:安于此生
全集配套程序下载地址:链接: http://pan.baidu.com/s/1eQzTWfo 密码: vytv
怎么西班牙人的网址提示风险啊。 感谢发布原创作品! 继续学习中 感谢楼主分享 代码也不会,女朋友也没有 。 正需要,我去试试! 收藏,便于后续使用 Thank you!!!Thank you!
页:
[1]