ximo兄在《庆祝A-new苏醒系列之一--简单的VM保护程序的爆破分析》一文中介绍了如何Patch e_flag来对vmp进行爆破,文章写得通俗易懂,适合入门。相信有不少同学都跟我一样好奇,ximo是如何调试到那个地方的。通过一晚上的调试,我想和各位分享一下我的心得,如有错漏,忘不吝赐教。
另外,建议大家参考一下aa1ss2大牛所著的《VMProtect逆向分析》。认真读一遍,收获会不小的。
1、记录Handlers
既然要分析VM,应该记录一下有哪些操作,所以记录Handler是十分必要的。vmp有个Dispatch,通过解密EIP(esi)来确定应该执行啥指令,然后根据DispatchTable跳转过去执行。通常,Dispatch的最后是一个push [esp + xxx]接上一个retn 0xXX,而ecx或者edx中保存的是handler的地址。所以,我们可以在这里将程序断下来,记录handler,以便于分析VM。
之前我试过用脚本记录,但会严重影响程序的效率,所以这次我写了一个dll,在Dispatch结束的时候,跳转到dll的代码中,将handler记录下来。dll的代码很简单,就是写文件而已,大家都会写。
在ximo的那个程序中,Dispatch是这样的:
0040C47E FF7424 2C push dword ptr [esp+0x2C]
0040C482 C2 3000 retn 0x30
通过观察,当执行到0040C47E的时候,ecx中的值即是Handler,所以Patch 0040C47E处的代码,让其跳转到一块空间,然在那里把ecx的值传递给dll,dll负责记录。这样跑一遍,Handler基本就可以记录完了。
2,分析Handlers
知道了有哪些操作,下一步就是要知道他们是干嘛的。其实这个和反汇编是一个道理,通常是调试器帮你把代码反汇编好,然后等着你去理解。现在也差不多,是该理解一下了。
分析Handlers是体力活。看了一下记录,有4519行,也就是说这个过程执行了4519条Handlers。接下来就是人肉了,在OD中转到对应的Handler的地址,观察其功能,然后利用记事本的替换功能,把Handler对应的指令注释上去。
注释完大概会得到这样的结果:
0040CCF8 GetI32
0040D672 GetR32
0040CCF8 GetI32
0040DA5A GetESP
0040CE9C GetI8
0040D74B Add32
0040C1EE SetR32
0040D271 WmSs32
0040C1EE SetR32
0040D74B Add32
0040C1EE SetR32
0040D125 nor32
0040C1EE SetR32
0040D672 GetR32
0040DA5A GetESP
0040D37F RmSs32
0040D125 nor32
0040C1EE SetR32
0040CCF8 GetI32
当然,这里只是一小部分而已。还有很多,等下一起上传了,欢迎批评指正。
这里说一点废话,识别Handler,我目前还是使用肉眼,之前调试过很多次,对VMP有了一定的了解,还算比较容易。如果大家想偷懒,建议大家去Upk找Nooby在某个回复里面发的一个记事本,里面有一个记事本和完整的VM记录,看样子是OD插件生成的。大家可以使用那个记录来看看Handler是啥样的。具体哪个帖子我忘记了……大牛们都有自动化插件了,我等菜鸟还在人肉,差距啊。
3,分析程序
从Handlers到程序的差距还是挺大的。由于之前调试过vmp,知道vmp在进行比较的时候会使用NOR32指令,所以需要在NOR32下段并进行观察。
当前的NOR32是这样的:
0040D125 10CC adc ah, cl
0040D127 66:0D DC76 or ax, 0x76DC
0040D12B 8B45 00 mov eax, dword ptr [ebp]
0040D12E 66:0FABF2 bts dx, si
0040D132 8B55 04 mov edx, dword ptr [ebp+0x4]
0040D135 66:0FBAE4 08 bt sp, 0x8
可以看到分别把两个操作数从vm堆栈装入eax和edx,所以我选择在0040D135下断点,方便观察eax和edx的值。
接下来在控制台中输入43690,选择输入这个的原因是,43690的十六进制形式是AAAA,比较容易观察,以免错过。
在scanf返回后,NOR32中断了17次后,eax的值为AAAA,此时转到Handler记录,F3搜索0040D125,第十七次附近的代码是这样的:
0040D672 GetR32
0040D125 nor32
0040C1EE SetR32
0040D74B Add32
0040C1EE SetR32
0040DA5A GetESP
0040D37F RmSs32
F7两条指令,来到0040D74B,也就是Add32指令,指令的核心部分是这样的:
0040C592 0145 04 add dword ptr [ebp+0x4], eax
我们此时执行到0040C592的时候,esi等于00410611,[ebp+0x4]会出现明文,也就是2010,经过了Add32的运算,[ebp+0x4]的值如果是-1,即输入的值为2010,不是-1,输入错误。
接下来如何Patch,我就不用说了。
4,结尾
我只分析了一部分,有兴趣的同学可以继续搞,或者提供一种更好的解决方案。
好吧,回头看了一下,觉得我写得好烂。各位拍砖轻一点,谢谢。
exe见ximo的帖子,我上传Handlers的记录好了,记录是从scanf返回开始的。 |