跟随ximo的脚步——简单分析VMP
ximo兄在《庆祝A-new苏醒系列之一--简单的VM保护程序的爆破分析》一文中介绍了如何Patch e_flag来对vmp进行爆破,文章写得通俗易懂,适合入门。相信有不少同学都跟我一样好奇,ximo是如何调试到那个地方的。通过一晚上的调试,我想和各位分享一下我的心得,如有错漏,忘不吝赐教。另外,建议大家参考一下aa1ss2大牛所著的《VMProtect逆向分析》。认真读一遍,收获会不小的。
1、记录Handlers
既然要分析VM,应该记录一下有哪些操作,所以记录Handler是十分必要的。vmp有个Dispatch,通过解密EIP(esi)来确定应该执行啥指令,然后根据DispatchTable跳转过去执行。通常,Dispatch的最后是一个push 接上一个retn 0xXX,而ecx或者edx中保存的是handler的地址。所以,我们可以在这里将程序断下来,记录handler,以便于分析VM。
之前我试过用脚本记录,但会严重影响程序的效率,所以这次我写了一个dll,在Dispatch结束的时候,跳转到dll的代码中,将handler记录下来。dll的代码很简单,就是写文件而已,大家都会写。
在ximo的那个程序中,Dispatch是这样的:
0040C47E FF7424 2C push dword ptr
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
0040D12E 66:0FABF2 bts dx, si
0040D132 8B55 04 mov edx, dword ptr
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 , eax
我们此时执行到0040C592的时候,esi等于00410611,会出现明文,也就是2010,经过了Add32的运算,的值如果是-1,即输入的值为2010,不是-1,输入错误。
接下来如何Patch,我就不用说了。
4,结尾
我只分析了一部分,有兴趣的同学可以继续搞,或者提供一种更好的解决方案。
好吧,回头看了一下,觉得我写得好烂。各位拍砖轻一点,谢谢。
exe见ximo的帖子,我上传Handlers的记录好了,记录是从scanf返回开始的。 本帖最后由 ximo 于 2010-8-9 22:50 编辑
分析每条handler,实在是个蛋疼的体力活。
不过,如果不以完全还原代码为前提的话,还是可以取巧的,
比如,只是破解,可以hook住eflag计算,vm_jmp等
分析数据,可以hook住vm_push和vm_pop(对应小伟牛文章里的GetR32和SetR32,不同的人可能对handler的命名有差异,但意思就是那个意思),vm_retn等。
支持小伟牛多写vm的分析文章。学习。 大牛的头像!
義勇君 发表于 2010-8-9 22:27 http://www.52pojie.cn/images/common/back.gif
感谢沙发,这个是Slipknot的主唱…… 回复 3# ximo
所以啊,很多人说知道了一组正确的注册码之后VM弱下来了……对比着分析挺容易取巧的。
不过我还是抱着学习的态度来看,尽量理解多一些。 多谢分享,今天跟朋友去喝酒了,明天起来好好看。 大牛的头像:funk:eweqw! 其实我觉得最好的理解VM的办法,就是自己写个VM。
VM的最经典的文章可以参考softworm的那些,真的很经典。
曾经自己摸索着写过一个简易的虚拟机,这对我来理解VMP有非常大的帮助,不过写的太挫,就不拿出来丢人现眼了。 Softworm的天书,确实经典。常置于桌面,至今为止没能理解个大概,实为汗颜……
VM的话,我有想过挺细的,但是没写过。
vm 1.2x也是一个很好的学习工具,至少我是那么认为的。 本帖最后由 mycc 于 2010-8-9 23:22 编辑
楼主跟到哪里,差不多了,
你那个 FFFFFFFF 的说法是对的,然后呢,它接着又会到了下一步
temp = n_n_a (-1)
if (temp == 0 )
ok
else
no
估计不懂得人继续不懂得 (只是说说我的看法),至于还原 VM 过的算法的话,全在分析 有限几个 H 就可以了
其他的都是辅佐 H ,基本没有必要浪费时间 谢谢分享,慢慢看了。