作者:Kissy
目标程序为一个下载者生成器,PEID查壳如图所示
设置OD忽略所有异常,用PhantOm.dll插件隐藏OD,设置如下
载入我们的目标程序。停在入口
由于这篇文章的重点是VM代码的修复,脱壳过程不再赘述,详情可参见FLY和windycandy两位大哥的脱文,或者参考我之前做的一个语音手工脱壳教程《DELPHI程序的TMD壳手工脱壳语音教程》
(http://www.unpack.cn/viewthread.php?tid=23488&extra=page%3D1)
这里我们采用论坛的一位朋友修改的FXYANG大哥的一个脚本取代手工的工作。运行脚本后停在伪OEP
这个时候IAT也随之处理完毕
我们这里记录下脚本结束后停留的地址00406A38以及此时寄存器中EAX的值
也就是004B8BB4。这里我找来一个无壳的DELPHI程序来观察入口部分的特征
DELPHI程序的入口特征很明显,但是也比较多变,总体来说有一定的规律可循:第一个关键CALL之前的代码基本类似,第一个关键CALL之后的代码我们可以看作是对寄存器的赋值操作以及一些CALL指令。虽然有些DELPHI程序的OEP处代码很长,其中夹杂着一些其它的操作,我们多留心寄存器和堆栈,可以慢慢跟出来。所幸TMEMIDA不会VM很多句,我所见最长的也不超过15句(先泄密下:这篇文章中的目标程序是14句 HOHO~~ ^_^).
那么我们这里也就可以写上部分修复后的OEP代码了:
一般情况下就是这几句了,但是我们观察到OD的堆栈窗口中压入了一个值
我们发现对应的是EBX中的值0012FF9C,所以这里我们还要补上PUSH EBX这句代码。经验告诉我们,我们应该把这句话放在ADD ESP,-10的前面,那么这里我们能够修补出来的代码如下:
我们单步走到RETN,走出这个CALL来到了THEMIDA壳的VM代码部分
论坛里的一位前辈给出了从VM中找代码的一个思路,我总觉得不够通用,而且稍不留神,容易出错。我自己想出了个办法来简化和明确我们的操作
这里我就分2步来进行:
1. 找出所有被偷取的关键CALL
2. 在找到关键CALL的基础上通过寄存器和堆栈的变化来“猜”出前面提到的赋值操作,也就是MOV指令
之所以这么做,是为了尽可能避免在VM中迷失方向,因为CALL后面的地址是代码段,而非壳段,当我们从VM中来到代码段的时候,我们就知道我们抓住了主心骨 ^_^
现在OD停在007901F2我们单步走几步,经过2个JMP后在代码段F2下断,SHIFT+F9来到
继续单步经过几个JMP后对代码段下断,SHIFT+F9运行,我们会发现来到了
这也就是我们的第二个CALL了,这里就不要花力气思考在这2个CALL之间有些什么指令,我们现在的目标是先找到全部的CALL。单步到004672AE,继续F8,再次来到VM中。重复先前的单步+CODE段下断然后SHIFT+F9的操作,几次操作后再次来到程序的代码中,这里停留的地址也就是第三个CALL了
单步走出这个CALL,又到了VM中。我们现在有心理准备了,^_^ 不怕。继续用我们的老办法来对付他,很快就来到了004B8FE6处
我们发现,这里应该就是OEP附近了。分析下代码,我们再拿之前那个无壳的DELPHI程序的入口来做对比
那么OEP应该就是004B8FB4了,当然也有特例的情况,但大部分情况下就是这样了。我们后面也可以来验证一下。
那么到这里,我们的第一个找所有关键CALL的步骤也就完成了。我们写出部分的修复代码,未找到的部分用××××来表示,如下:
后面紧跟着就是正常的未被处理的代码了。
接下来的操作就比较简单了,因为我们找到了主心骨。^_^ 但是也是这篇文章的重点部分咯~各位看官别睡着咯~~
重新载入目标程序,跑完脚本后,停留在伪OEP处,单步走到CALL的出口RETN,再单步一次停留在VM的入口,我们用截图软件截下寄存器此刻的各项数值(有时候也需要截取堆栈,但是一般情况下不需要,此例中也不需要)如图:
然后在00467298处F4断下来,此刻再将寄存器中的各项值用截图软件截取下来
我们发现只有EAX和EBX中的值发生了变化。我们CTRL+B搜索EC DB 4B 00找到004BC85C处
那么可以写出:
CTRL+G来到EBX的004BDBEC中,发现正好与EAX中的数值对应上,
当然我们这里可以搜索C8 17 C9 02来查找地址
于是我们又可以写出:
哈哈 我们发现这么做的好处了吧。不必受VM的困扰,抓住关键部分,从VM的入口再到VM的出口,从整体上来看他究竟干了些什么,这样就不会迷失在VM的海洋中了~
这样我们处理完一处了,我们转到EIP。走出这个CALL,停留在VM的入口,对寄存器截图
CTRL+G来到00466e90,F4断下来,再次截图做对比
发现只有EAX和EDX的值发生了改变(ESP的改变不是我们关心的)CTRL+B搜索3C 90 4B 00 发现没有找到,那么我们就直接写成:
以及:
继续单步走出这个CALL ,在VM的入口截图
CTRL+G来到正常代码的起始处004B8FE6,F4断下,再次截图
只有EAX和ECX做了变动,根据先前的方法很容易找到这里的2句指令:
到这里我们修复代码的工作基本上就完成了,我们组装整理下,得到如下14条修复后的指令:
从我们先前找到的OEP-004B8FB4起用IDAFicator插件把这些命令导入或者逐条手工敲入,发现代码不多不少刚刚好,心里窃喜下先,证明我们的修复是没问题的,OEP找得也是正确的。^_^
在004B8FB4新建EIP,LOADPE修正镜像,完整转存,再用IMPORTREC修复IAT抓取保存,运行正常,至此我们的工作也就圆满结束了。
当然还有脱壳后的优化操作,但不在本文之列。忽忽~~
已经有(0)位网友发表了评论,你也评一评吧!
原创文章如转载,请注明:转载自Eddy Blog
原文地址:http://www.rrgod.com/program/235.html 欢迎订阅Eddy Blog。