论坛首页 逆向工程技术区 阅读主题

[原创] Vmprotect1.6x分析之虚拟机流程

318 浏览 21 回复
#1 楼主 2026-06-01 21:08:48
Qq: 2746074413 微信:vmp520888个人空间 e75K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6K6M7r3q4U0k6g2)9J5k6h3u0A6L8r3W2T1K9h3I4A6i4K6u0W2j5$3!0E0i4K6u0r3x3K6f1@1y4U0V1#2y4U0j5$3y4o6p5@1y4U0j5H3x3b7`.`. 相信大家对于Vmprotect虚拟机的逆向一定非常头痛吧,尤其是最新版本,我去官网看了一下已经到了3.96了,如果我们直接去分析他,那无疑是螳臂当车,杯水车薪,根本是不可能的事情了,经过多年的发展,已经发生了翻天覆地的变化了,在准备材料的过程中,我也浏览了早期大神们发的很多文章,而我介绍的这个版本大概是在2010年前的,具体时间没有去查,属于是初代版本的,而我之所以发这篇文章,其实我也是菜鸟,发出来和大家一起交流共同成长,可能会出现错误,老鸟勿喷。Ok,废话不多说。步入正题。 我要讲的内容大概有是Vmp1.2从到1.6的改动,为什么选择1.6呢,那是因为1.64版本开始加入了反调试,所以选择这个版本比较具有代表性,还有一个原因就是,他们中间的版本网上不好找,而且相邻的版本之间改动的并不多,没必要每个版本都去分析。相比于1.2版本1.6版本,虚拟寄存器已经放在了堆栈里面了,1.2版本是放在vmp区段,这是一个比较有意思的变动。有意思的是我找的1.64版本是个demo版本,很多功能被阉割了,连代码混淆都没有,这恰巧给我分析带来了参照,所以,我将结合1.63和1.64版本进行分析讲解,我第一次拿到1.63版本给程序加密后,用OD调试的时候发现,看起来感觉这还是vmp吗?怎么跟我分析的1.2版本不大一样,一眼看上去像天书。没关系,接下来我会慢慢的给大家分析出来。这篇帖子如果对于初学者来说还是有一定难度的,不过没关系我出过一部关于vmprotect逆向入门的课程,讲的非常详细主要就是围绕vmp1.2版本的深度讲解,https://www.kanxue.com/book-section_list-200.htm 大家可以去看看,如果手头不宽裕的也可以自己去研究,其实并不难,想开飞机的可以花点小钱。 我们找到vmp1.64目录下HelloASM.vmp1.exe,这个程序经过vm过的,设置选项选择最快速度,然后把检测调试器勾去掉,vm的代码我们在程序入口点选择5个nop,如下所示 这5个nop会被忽略,根据我以前分析1.2的经验,他还是会生成把当前寄存器入虚拟堆栈和出虚拟堆栈的伪代码并执行,之所以采用最简单的加密也是为了排除不必要的额外分析,然后生成的这个程序,把他拖到OD我们跟踪看下,之前的5个nop,被替换成了jmp 如下代码接着单步我们来看下,如何将当前寄存器值压入虚拟堆栈的跟踪发现,上面这条指令一共执行了12次,对应的伪代码如下 因为我vm的代码是nop,编译的时候其实是会被忽略的,如果是其他代码,执行到这边,就是真正开始执行被vm的代码了,既然这边没有东西需要执行,那就进入收尾阶段就是,取出返回地址完了之后把堆栈上的所有虚拟寄存器,全部赋值到堆栈,我们可以继续看下代码是怎么样的 接着我们看下jmp HelloASM.004056C8的代码 上面这段代码比较长,我使用的这个demo,执行到ja HelloASM.00405105,就跳转了,我猜测应该是执行某些特殊的handler才需要执行后面那些代码吧,他们最终都是会跳回00405105继续读取执行伪代码,在这里我稍微卡了一下,没必要把这里也弄的那么清楚,这里只是一个小小的细节而已,OK,我们继续,执行到这边我们发现esp的值一直都没变,从开始执行handler之后esp这个寄存器就没有用到了,倒是epb反复的被用到,想想还蛮复杂的,有很多细节我们不必太在意。我们刚刚执行到这边,结果其实就是这两句 ebp在这里可以比作esp,这时候edx的值是0,其实上面两句是不是相当于push edx,接着我们再往下执行,又来到了004056C8 这里,在这边这一部分代码可以忽略,我们
单步到 0040510D ,去看看下一条handler, 由于是使用demo版本的vmp编译的所以,数据都没有加密啥的,所以我们可以在伪代码看到401005这个地址,如果是push xxxxxxxx,我们甚至可以看到xxxxxxx,当然正式版不可能看到的,不过这方便了我们分析,我们再看下一条handler 上面是一个加法的handler,用于重定位,算出返回地址的时候同时已经把结果存放到堆栈里面了。接着我们看下一条handler 上面这条handler是把标志寄存器,存放到对应的虚拟标志寄存器,我们接着看下一条handler, 上面是把虚拟寄存器的值全部弹出到堆栈,总共执行10次,下面是对应的伪代码 这就是前面把堆栈上的值入虚拟寄存器相反的操作了,最后执行一个返回handler 执行完retn后就回到了401005,以上就是1.64最简单的虚拟机的执行过程了。我们发现和1.2比把虚拟寄存器放在堆栈上,确实让handler变得更加复杂化,为什么刚开始把虚拟寄存器放在vmp区段,应该是刚开始开发没那么多精力吧,什么东西都是摸石头过河,没办一下子,做到完美的原因吧。要是这么简单,确实vmp也不难,于是作者肯定要在每个指令上下功夫,垃圾指令加膨胀。1.63版本的我刚拿到分析的时候确实有点懵,感觉就是一堆看不懂的指令外加各种跳转,确实这么一搞很有效果,反正我第一眼看了,在想,完了这还怎么分析,都看不懂,不过猪鼻子插葱,再怎么也不可能变成大象,你们说对不对,比如说,伪代码地址,和计算handler有关的代码比如 eax*4+地址,等等都是能够找到的,在这个版本是这样的,后面版本作者想要做的更加隐蔽,也是有可能的 前面我们分析了1.64demo版的vm代码,接下来我们看看,使用同样的设置,在1.63编译后的在OD调试时候的样子,将vmp1.63目录下的HelloASM.vmpa.exe拖入OD, 上面这几个代码使用一些垃圾无意义的指令让代码变复杂,干扰我们分析,可能还有一些别的操作,我们在看下一个代码块 以上就是未执行handler前的所有代码了,可以看到,通过解密各个数据然后加入了很多垃圾指令,让整个代码变得很没有可读性。接着往下执行到第一个handler, 上面这几个代码块就是执行第一个handler整个过程,这前面分析的1.64相比就是加了很多花指令,但是流程还不变的,所以我们可以推测出来,编译器在编译的时候先生成没有混淆的代码,也就是1.64分析的那样,然后进行变异膨胀加花指令等等。 接下来我们分析一下1.64的反调试,在帮助说明那边说了,v1.64 新增 调试器检测 和 VMWare 虚拟运行环境检测。果然这个版本强度直接上了一个档次,这边我就单独分析一下他的反调试,其他的分析思路都是一样的,我这边编译的时候设置跟前面一样,只不过检测调试器勾选择上,然后下拉框选择user-mode,把编译好的HelloASM.vmp2拖到OD里面,上面的代码前两句没有用jmp xxxx

...(已截断)

---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-288594.htm
#17 2026-06-01 21:08:48
感谢分享
#18 2026-06-01 21:08:48
感谢分享
#19 2026-06-01 21:08:48
感谢分享
#20 2026-06-01 21:08:48
感谢分享
#21 2026-06-01 21:08:48
学习下
#22 2026-06-01 21:08:48
学习学习
‹ 上一页 1 2 下一页 ›

请登录后参与讨论

立即登录 注册账号