距上次发帖已经过去一个多月了,VMProtect最新版本都已经到3.10.x了,果然更新的速度蛮快的,之前分析了VmProtect.3.9.4的简单流程,之所以叫简单,说明分析起来并不难,VmProtect的每次更新都会往壳里面加料,加的什么新的猛料我们不得而知,但是VMProtect3.5.1版本源码的泄露,作者一定会对代码进行更加大范围的修改,正如3.8.1的界面多了很多看不懂的选项。有了源码的加持,这对于开发分析插件来说,难度少了很多,于是我打算把这款插件分享给大家,由于是OD插件所以,只支持32位,32位程序,懂的都懂,面对庞大的数据,很容易出现内存不足的问题,在这里我也是卡了很久,分析小的流程还好,一碰到大流程,就莫名的奔溃,于是我,学乖了,内存可以重复利用的就定义为全局,不能重复利用的就及时释放,还有就是delete这个函数,经常会导致闪退,所以就能重复利用的内存就重复利用,少用delete,终于明白开发一个处理庞大数据的程序要考虑的东西好多,之前在测试代码的时候,用VMProtect加密堆栈操作类的指令的时候,也会出现加壳后秒退的问题。所以说任何东西不是一开始就完美的,得经过各种测试,修补,才能达到我们现在用起来一点瑕疵都没有。下面我介绍一下这个插件怎么用。
这里我在附件准备了两个测试样本,和Ollydbg调试器,为什么给调试器呢,因为将插件放在其他修改版中测试会出现莫名的错误,而且我还用了好多硬编码,所以还是不想做兼容,太烦!然后这两个样本,第一个是只加了代码变异虚拟化,第二个没有对代码处理,而是加了一层反调试外壳。
首先,我们把第一个讲解的样本CreakMe.vmp.exe拖入OD里面,还有一个未加壳的程序CreakMe.exe,里面的代码这里我就不贴了,拖进来之后是一个jmp直跳,我们单步一下,走到
这里就是插件的分析起点,直接右键AntiVmp-》Auto Analyse。这个选项是自动分析,他会分析整个流程块,我们也可以在某个地方下断点,那么他就会分析到断点的地方停止,分析过程中底下会有分析进度显示,如果分析的代码块指令过多,时间会比较长,当然分析的指令数量也是有一定限度的,这里我已经设置满足大多数情况了,这里分析并不是和以往的插件一样,静态分析,这里是先Trace记录数据,记录完成再进行分析,没分析完成之前不要操作OD,有可能会卡主,或者闪退,这里可以多打开一个OD,结合前面分析的代码,自己去调试,分析完成之后后如果没有出现这个 
大家可以点击Auto Analyse下面的ReadCommands。出现之后我们直接双击他,就出现了,刚刚分析得出的一级指令,

这里总共有10列,分别是handler的地址,再讲第二个含义之前我先解释一下,三个轮转的寄存器,分别是ebp,esi,DispatcherReg。这里的ebp是根据2.x版本得出的,在他之前ebp寄存器始终都是用于存放临时变量的相当于esp,esi用于存放伪代码指针,DispatcherReg是3.x版本开始有的,这里刚好edi可以用,那么esp始终指向虚拟寄存器块,在这个版本这三个寄存器过段时间就会轮转,所以我们分析的时候,首先要确定他们的职责,介绍完了,我们看第二列就是handler执行前ebp的值,第三列是执行后的值,第四列是handler名称,第五六七列就是前面说的这三个寄存器现在对应的寄存器,第八列是这条handler执行前,前面执行了多少次,这对于定位代码非常有用,记得以前分析2.x版本的时候一条handler可以对应多个伪代码,是一对多,现在是多对多,执行同一个功能的handler可以有好多个,第九列就是对应伪代码的地址了,第十个是解密出来的虚拟寄存器编号或者常数的值。前面说了这个寄存器轮转就发生在VM_JmpEntry这个handler里面,从名字我们就可以看到他其实是以前的VmEntry,也只有VmEntry才对寄存器进行重新分配,还有一个VM_JmpEntry2,这个handler是镶嵌在VM_JmpEntry里面的,但是他的起始地址是在,举个例子
这个条指令开始的,所有VM_JmpEntry和VM_JmpEntry2共用了一部分代码,VM_JmpEntry2作用就是重新获取代码的地址,VM_JmpEntry比VM_JmpEntry2多了个寄存器轮转,这个程序我们是要让他输出Success而不是Failed,这里是给出了两个值0xABC和0xCDE,用cmp指令判断是否相等,相等则输出Success,显然给出的值不相等,所以我们就要找到模拟cmp指令的地方然后将标志寄存器zflag,改成1。
从分析出来的数据中,找到上面这个几个handler,就是模拟cmp指令了, 执行到VM_Nor32这条handler里面的and指令下一条就是修改zflag的时机了,将zflag,改成1。就能显示Success了。
我们再讲第二个样本test拖到OD里面,这个是反调试外壳,当然这个外壳也是被vm了,而且体量非常大,这个反调试外壳,并不是所有代码都vm,我们按照前面一样右键分析,分析完成之后我们转到代码界面,这时候很显然是正常代码但是加了很多垃圾代码,这边我们可以正常去分析,当然用不了多久,他又进入vm了,这里如果我们不想看这段没被vm的正常代码,可以使用执行到返回,再单步,进入到下一个分析起点,之后可以再右键分析,但是不建议这么做,为什么呢,这也是我们百思不得其解的地方,会偶尔莫明奇妙的闪退,如果是分析的代码量巨大就不要连续使用分析功能了,记住或者下断下一个分析起点,把OD重开,在运行分析,否则会因为内存不足大概率闪退,如果我们想将结果保存,可以在分析的日志界面,右键-》复制到粘贴板->整个表,这样子我们可以在记事本上慢慢的分析。
在讲爆破他的反调试之前,我先讲下他的调试流程,因为源码已经泄露了,所以整个流程大家都一览无余了,检测的手段很多,但是依次进行,比如说先检测A位置,如果A位置发现了调试器,那么直接弹出警告,然后执行ExitProcess,如果没有检测到,继续往下执行检测B位置,直接所有都结束才去执行宿主程序,这里可以在检测A的时候使用爆破,他的逻辑是发现调试器,弹出警告,修改变量,判断变量,如果符合条件则执行宿主程序,不符合则执行ExitProcess退出。这里我给出一个地址
可以先运行到这个地址,然后执行Manu Analyse,这个功能是用于处理Auto Analyse效果不好的的情况,其中第三行的ToCallApi这个是用于寻找最近的一次API调用的,回到Manu Analyse,执行分析后会弹出一个输入地址的对话框,这里我们输入007AD796,
点击确定过后他会自动开始分析,分析到某个call的时候就会弹出警告,然而这个对话框属于这个call内部的,这时候Trace一直停在这个call上,这里我们需要手动点击这个警告对话框,对话框消失后,Trace才继续,这里我设置了一个对话框用于挂起分析线程,当Trace停下后,再点击确定,这时候,分析线程开始工作,完成后就输出分析日志到窗口了。完成后,程序显示退出了,当然这个是因为刚才停下的地方的那个call就是ExitProcess,到这里我们就把这部分流程给抓取了,
分析的日志我们可以保存到记事本,用notepad++分析,整个流程就执行了两次VM_CallApi,第一次只是弹出警告,第二次就是ExitProcess了,我们就只要分析弹出警告后面的日志块就行了,这里的cmp是用变量和1进行比较,我们可以查看最后一列Value,看下常数1的地方,
这里我们和前面的方法一样修改007011D7的VM_Nor32内部and指令执行完的zflag就可以实现爆破了。
0043BC8E 68 77EED285 push 0x85D2EE77
0043BC93 E8 E187FDFF call CreakMe_.00414479
0043BC8E 68 77EED285 push 0x85D2EE77
0043BC93 E8 E187FDFF call CreakMe_.00414479
0047C136 8D35 36C14700 lea esi,dword ptr ds:[0x47C136]
0047C136 8D35 36C14700 lea esi,dword ptr ds:[0x47C136]
0046A4A4 VM_Nand32 edi ebp esi 0 004386AC
00445FA1 VM_PopVR32 edi ebp esi 2 004386A8
00423783 VM_Add32 edi ebp esi 0 004386A3
0046A39B VM_PopVR32 edi ebp esi 2 0043869F
0045B753 VM_PushEsp edi ebp esi 0 0043869A
0047AD44 VM_ReadSs32 edi ebp esi 0 00438696
00469B5D VM_Nor32 edi ebp esi 0 00438692
0046A4A4 VM_Nand32 edi ebp esi 0 004386AC
00445FA1 VM_PopVR32 edi ebp esi 2 004386A8
00423783 VM_Add32 edi ebp esi 0 004386A3
0046A39B VM_PopVR32 edi ebp esi 2 0043869F
传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2025-11-14 16:22
被阿强编辑
,原因: