平常我们爆破一个软件,有一种有常见的方法就是通过修改jcc跳转来达到爆破的目的。而vmp实现jcc,跳还是不跳,其实计算是eflags。
以jz为例,大家都知道jz跳不跳其实是看zf标志位的状态:
zf == 1 ---> 跳转
zf == 0 ---> 不跳转
那么我们看看vmp是怎么做的,先上个elflags reg图和给几个要用的数字以及一个handle:
数字:0x815
0x246
0x206
0x216
0x40
(如果有玩过vmp的,应该对这几个数字有熟悉)
handle大致样子,记为vm_p(a,b):
下面我会一一解释。
先看看0x815的二进制:100000010101
好像看不出来什么所以然,那么这样呢?
这样就很直观了,其实等价于OF AF PF CF的mask。
同理大家可以看看其他的几个数字。
比如0x40,这里就直接用维基的图了:
明白了这几个数字的含义那么我们看看可以怎么得到zf为1的情况,之前已经说到了会用到eflag的值。是不是可以这样:
~zf = and(0x40,not(eflags)) = 0 (1)
zf = and(0x40,eflags) = 1 (2)
注意到这里的0和1都是所对应到eflags zf的数值
那么eflags又是怎么得到的,这里vmp通过加法和0x815实现
eflags = and( eflags1, 0x815) + and( eflags2, not(0x815)) (3)
而vmp中的not,and运算都可以用vm_p来实现,比如我们将式(1)转换后,如下:
~zf = vm_p(not(0x40),eflags) = 0
至于eflags1,eflags2我们可以并不关心他怎么运算的,因为我们只需要修改最终的eflags即可达到爆破的目的。
不过接触过vmp的人应该明白eflags1,eflags2的数值是通过vm_p(sn,sn)+?这样的式子得到的。
相信vmp为什么会选择0x40这个数字来计算zf大家也明白了(还有一点,大家注意一下af)。
0x02 实战
明白了原理之后,我们找个东西进行一番实践。
这里我选择的是EverEdit,因为官方刚好有两个vmp版本
使用的是官方下的32位的绿色版
你可以输入了随意输入sn后(不过注意,everedit的sn太短不行,233)通过暂停法然后再单步找到vmp调用handle的地方(也就是dispather),也可以通过那块保存sn的堆空间找到(因为是malloc的),当然方法很多。
使用trace into记录到文件中。
接下来我们只需要找到vm_p这条handle,然后在记录的文件之中搜索(记得倒着,从下向上)就ok。
而怎么找handle,如果你对vmp有了解的话,应该知道其实就4套handler。
这里我用一种我的方法,先分析是如何jmp到handle的。
然后我们在看看0x5BD000这个数组:
如果有人再仔细一些会发现,这个地址刚好是vmp0的区段的开始。
对了,可以提一提,这个数组大小是0x100 * 4。但其实vmp加密的时候第一次扫了186次,第二次随机扫剩下的,再把地址填进去。
至于为什么是186次:
1).186个匹配规则
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2019-2-1 18:24
被admin编辑
,原因: