VMProtect 3.31的OEP之旅

回复 星标
更多

VMProtect 3.31的OEP之旅

最近试着分析找了一下VMP3.31保护下的oep,以前从没分析过,第一次分析还是挺有意思的,打算和大家说说我找oep的旅途,错误纰漏处还请指正包涵。

准备工作

我找oep前还是先做好准备工作,把ep第一行nop掉(避免首字节int3检测),ep第二行改成jmp 0x45e53e,使程序只跑在ep这一段代码。

510923

这样做有2个好处:

1. 尽量减少原程序的干扰,例如API的调用。

2. 跑起来后,直接下断停住,观察寄存器和和堆栈有什么“特点”,同时还可以与初始环境对比。

确定OEP的出现

一开始我的想法还是很“正经”,想试试内存断点快速找到OEP一试,要么被抓到(反调试),要么程序没停住。

根据第二种情况,我又试图下断VirtualProtect,看看有没有改写text区段的属性。结果断是断下了很多次,但是并没有看见对text区段的操作,这时我猜测可能模拟wow64直接走syscall了,但这个应付起来有点麻烦,暂且不管,先试试别的方法。现在,出现在我脑袋里的是第二个方法:对比环境,左图为初始环境,右图为oep环境。

510923

先扫一遍寄存器,都跟OEP无关。再看ebpesp,发现没有改变,这是个好事。再看堆栈,esp-4处出现了OEP。我的第一反应是,是push oep,然后retn过来的吗?

为了证实这个猜测,我把VMP的反调试选项关闭(解除硬件断点检测的干扰),重新加壳,直接对esp-4处下硬件访问断点。

一路run,run到了oep。同时多次重新加壳,重复这个操作,都没问题。至此,oep已经能锁定。

找暂停点1

找暂停点,不仅仅是为了下硬件断点,更重要的是尽可能接近OEP,避开壳的各种检测。由于之前VirtualProtect成功停下过,先试试这个。

下断,run9次后跑飞。那就在run8次后停下,下硬件断点,run,看看会不会检测到。

很幸运,此时已经躲过硬件断点检测了,成功到达oep同时,我又想到一个念头。既然躲过了硬件断点检测,那内存断点检测是否也不在了。

对此,我在text下内存执行断点,run、run、run。结果一直被停在text区段各个retn上面(应该是vmp为了对付内存断点的手段),run到后面还被反调试查出来了。这个方法宣告死亡。

找暂停点2

之前第一个方法用VirtualProtect。感觉能找到API,运气成分很大。换别的壳可能就找不到这种API了。遂想试试第二种方法,稳妥点找到一个API。要尽可能接近OEP(避开各种检测),那就用工具看看VMP最后调用了哪些API。

510923

虽然vmp3.1开始有wow64模拟,但是现在看来,wow64模拟也没有模拟全部API

找API时尽量按以下要求找:

1. 从后往前找,越后面调用的API越好;

2. 尽量不选被检测的API;

3. 下断API后,run到跑飞的次数要尽可能是固定的(需要多次测试);

4. 需要run的次数越少越好(但检测必须已run过去)。

对比,我一直从下往上找,找到了一个适用的。

510923

但是这个API有点“不完美”,或者说太底层了。每次重新加载程序,都会在这里停10次左右。

对此,我停住后往下单步走,跟到了壳调用的API

510923

经过多次测试,这个API就很不错,适合做暂停点。不管是默认加壳,还是全保护加壳,都只需要断2次(VirtualProtect会因此需要改变中断次数),便可以下硬件断点。至此,默认OEP保护方面就没什么好闲谈的了。

VM OEP保护

由于se没有vmoep,顶多是偷掉第一个字节,所以vmoep的保护也是我第一次研究。内心难免充满了许多疑问:

“vmp把oepvm了,仅仅只是防止别人看出OEP或者直接搜特征码吗?”

“都说vm和壳是两回事,是不是意味着跑到vm后的oep直接dump就可以了,vm的oep和壳没关系?”

“如果vm后的oep和壳有“联系”,会是怎么联系的?”

带着这些疑问,我用之前的找oep方法来尝试vmoep后的程序。结果,在下硬件断点后一直run,并没有runoep,而是直接跑起来了,而且也没有停在我对OEP附近设置的断点上。这时,我心里基本就有答案了。vm后的oep和壳“联系”在一起了。

此时,vm模拟着45e53e处的jmp,在不停的跑(尽管他不知道自己永远也跑不到尽头,哈哈)。

无意间,我随手暂停住程序,就发现了希望。EIP是在vmp0区段,而不是vmp1区段。有了这个“跨区段”的差别,我就可以试着用内存断点停在vm后的oep那么我接下来的操作还是用“对比法”,并且有了以下流程:

1. VM OEP保护

下断CreateToolhelp32Snapshotrun2次,对vmp0下内存执行断点,并且run。停在vmp0区段。

2. 默认OEP保护:

下断CreateToolhelp32Snapshotrun2次,对vmp0下内存执行断点,并且run。也停在vmp0区段。

两种情况下都停在了vmp0区段,这个地点应该不是oep。还需要更接近oep才行,为此我又对2个程序下之前的硬件断点,run一波,然后停在硬件断点处,再对vmp0下内存执行断点,继续run下去。

这时出现分叉了,默认保护下跑飞(没有再跑到vmp0),VM OEP保护下,又一次跑到了vmp0

再看看出现在我眼前的代码,我以为此时应该是push xxxxx,call xxxxx这种进入虚拟机的代码。但却是这种代码。

510923

看见这种代码,我内心是有点虚的。这意味着要么我找错了,要么此时的OEP有什么东西和壳“联系”起来了(最大可能就是opcode)。

为了判断找对地方没,我选择将OEP的保护由“虚拟”改成“变异”重新加壳,重新按上述操作。再看看此时的代码样子。

510923

OK,错不了了,这里就是VMP后的OEP

再来看看去除混淆后的这条hander。这条hander每次加壳都会变,但是换汤不换药。

mov eax,dwordptrds:[edi] // edi为vm_esp,此时存放着opcode地址addedi,0x4 mov esi,eax mov ebx,esi lea ebp,dwordptrds:[0x78C2E9] sub esi,0x4 mov edx,dwordptrds:[esi]xoredx,ebx bswap edx dec edx bswap edxaddedx,0x2B2E1207xorebx,edxaddebp,edx push ebpret

这条hander大致就是起到“连接”的作用。此时直接dump程序,写一个hookesp或者ebp赋给edi,再对[edi]写入opcode地址,vm oep方面就解决了。

想测试能不能成功运行,需要先把VMP的“导入保护信息”和“资源保护”选项关闭再重新加壳。此时在CreateToolhelp32Snapshot也只需要中断1次。

到此为止,"OEP之旅"就结束了。

510923

- End -

510923

看雪ID:Lixinist

https://bbs.pediy.com/user-758886.htm

本文由看雪论坛Lixinist原创

转载请注明来自看雪社区

热门图书推荐

510923

立即购买!

热门文章阅读

1、借助gdb调试glibc代码学习House of Orange

2、逆向ObRegisterCallbacks 分析回调表结构

3、【汇编语言】值得学习的“编程世界的常青树”

公众号ID:ikanxue

官方微博:看雪安全

商务合作:wsc@kanxue.com

点击下方“阅读原文”,查看更多干货

此帖已被锁定,无法回复
新窗口打开 关闭