vmp的万用门

VMP里的“万用门”主要利用 NOR(或非) 或 NAND(与非) 逻辑运算。因为在理论上,仅靠这两种门中的任何一种,就能组合实现NOT、AND、OR、XOR汇编里面最基本的4种逻辑运算。VMP早期版本以NOR门为主,3.x版本后又引入了NAND门来增加分析难度。

1
2
3
4
Not(a) = ~a = ~a & ~a = Nand(a,a)
Or(a,b) = a | b = ~(~a & ~b) = Nand(Nand(a,b),Nand(a,b))
And(a,b) = a & b = ~~a & ~~b = Nand(Nand(a,a),Nand(b,b))
Xor(a,b) = (~a & b) | (a & ~b) = (0 | (a & ~b)) | (0 | (b & ~a)) = (a & (~a | ~b)) | (b & (~a | ~b)) = (~a | ~b) & (a | b) = ~(a & b) | ~(~a & ~b) = Nand(And(a,b),Nand(a,b)) =Nand(Nand(Nand(a,a),Nand(b,b)),Nand(a,b))

在VMP 3.x版本中,大量使用了Nand运算来表示其他的各种逻辑,真实地隐藏了原本的各种逻辑运算,有效地加大了逆向分析的难度。

实现跳转指令JCC

VMP虚拟机内通常只有一个唯一的跳转指令(JMP)。条件跳转(如JE、JNZ)并非直接实现,而是先用万用门根据EFLAGS标志位计算出“是否跳转”的结果,然后根据这个结果选择目标地址,再执行那个唯一的跳转指令。

以je指令模拟为例:ZF=1

这时ebp是虚拟栈寄存器,[ebp]和[ebp+4]存储的都是eflags的值,这条handler是VMP虚拟机中实现NOR(或非)运算的虚拟指令
Not(eflags) = Nor(eflags(0x00000246),eflags(0x00000246)) = result0(0xFFFFDB9)
得到~ eflags

Nor(~ eflags(0xFFFFDB9),imm0(0xFFFFFFBF)) = And(eflags(0x00000246),0x00000040) = result1(0x00000040)
保留zf标志位;

这条handler是VMP虚拟机中实现右移运算(SHR,即 Shift Right)的虚拟指令,
shr(result1(0x00000040),imm1(0x6)) = result2(0x00000001)
zf标志位右移到第0位;

这条handler是VMP虚拟机中实现加法运算(ADD)的虚拟指令,
add(result2(0x00000001),imm2(0xFFFFFFFF)) = reslut3(0x0000000)
转换成0或-1形式方便后续按位与;

这条handler是是VMP虚拟机中实现NAND(与非)运算的虚拟指令,
Not(reslut3) = Nand(reslut3(0x0000000),reslut3(0x0000000)) = result4(0xFFFFFFFF)

Nand(result4(0xFFFFFFFF),imm3(0x00439204)) = result5(0xFFBC6DFB)
此时出现了一个跳转地址imm3(0x00439204),result5的值可能有两个结果 0xFFFFFFFF 或 ~0x00439204,这取决于ZF是 0 或 1;

Nand(result5(0xFFBC6DFB),result5(0xFFBC6DFB)) = result6(0x00439204)
取反还原出结果 0 或 0x00439204;

Nand(reslut3(0x0000000),imm4(0x00441E38)) = result7(0xFFFFFFFF)
此时出现了另一个跳转地址imm4(0x00441E38),result7的值可能有两个结果 ~0x00441E38 或 0xFFFFFFFF,这取决于ZF是 0 或 1;

Nand(result7(0xFFFFFFFF),result7(0xFFFFFFFF)) = result8(0x00000000)
取反还原出结果 0 或 0x00441E38;

Add(result6(0x00439204),result8(0x00000000)) = result9(0x00439204)
这里两个数其中必定有一个是0,取决于ZF是 0 或 1,这里就将最终的跳转地址求出来了。

Add(reloc(0x00000000),result9(0x00439204)) = result10(0x00439204)
重定位相加,得到最终结果。


后续将跳转地址赋值给esi,esi就是vEIP,这一套流程下来就模拟出来je指令。