主题:万用门介绍
1、NOR实现逻辑运算
2、cmp实现(sub)
3、jxx实现
1、破解vmp程序的关键点
2、谈谈vmp的爆破
3、一个VMP1.20程序的伪指令总结
正文:
1、万用门实现逻辑指令
理论知识:
vmp里面只有1个逻辑运算指令 not_not_and 设这条指令为P
P(a,b) = ~a & ~b
这条指令的神奇之处就是能模拟 not and or xor 4条常规的逻辑运算指令
怕忘记了,直接给出公式,后面的数字指需要几次P运算
not(a) = P(a,a) 1
and(a,b) = P(P(a,a),P(b,b)) 3
or(a,b) = P(P(a,b),P(a,b)) 2
xor(a,b) = P(P(P(a,a),P(b,b)),P(a,b)) 5
2、模拟CMP减法指令
理论知识:
参考S大的图
总结:
通过上述我们可以将操作步骤分为两个部分:
1、模拟sub减法指令
~(~a+b)
2、模拟Eflag标志位
int Eflag1 = (~a+b)
int Eflag2 = ~(~a+b)
int Eflag=(Eflag1 and 0x815) +(Eflag2 and ~0x815)
通过试验证明公式:
随便改个demo去加密看看VMP是如何实现的
假设:eax = 77523C33 ebx= 7FFD3000
模拟出正确结果:eax-ebx=F7550C33
模拟出正确标志:Elag287
2、1 模拟减法指令
公式:~(~a+b)
假设:eax = 0x77523C33 ebx= 0x7FFD3000
模拟出正确:eax - ebx = 0xF7550C33
0~2 行模拟出~a a = 0x88ADC3CC
3 行(~A+B) (~A+B) = 0x08AB03CC Eflag1 = 0x207
4 行保存Eflag1
5~6 行取出 (~A+B)的结果
7 行 ~(~a+b) ~(~a+b) =0xF7550C33 Eflag2 = 0x286
8 行保存Eflag2
剩下的cmp跟sub唯一区别:sub保留结果、cmp不保留结果
总结:
我们得到两个关键的数据分别是:
int Eflag1 = (~a+b) 207
int Eflag2 = ~(~a+b) 286
2、2 模拟Eflag标志位
公式:
int Eflag1 = (~a+b)
int Eflag2 = ~(~a+b)
int Eflag=(Eflag1 and 0x815) +(Eflag2 and ~0x815)
第一个ElfagAndConstant模拟出 Eflag1 and 0x815 = 0x5
第二个ElfagAndConstant模拟出 Eflag2 and ~0x815 = 0x282
然后就VM_ADDF = 0x282+0x5= 0x287
最后VM_POP_CONTEXT 保存0x287标志位
细看第一个ElfagAndConstant函数(就是模拟and指令)第二个同理
VM_PUSH_CONTEXT 取 Eflag1 = 0X207
VM_PUSH_CONTEXT 取 Eflag1 = 0X207
VM_NOR ~Eflag1 = 0XFFFFFFFFFFFFFDF8
VM_PUSH_IMM ~815 = 0X7EA
VM_NOR ~Eflag1 and ~0X7EA = 207 and 815
转了一圈发现是模拟and(a,b) = P(P(a,a),P(b,b)) 3
那么第一个(Eflag1 and 0x815) = 0x207 and 0x815 = 0x7
2、3 题外话
感谢群里小零大佬提供0x811与0x815等价
811其实就是
OF,AF,CF
而
PF,ZF,SF不管是add还是sub,or,and计算出来都是一样的
通过nor计算出PF,ZF,SF和
add出来的标志位合并一下就好了
3、模拟JXX指令
理论知识:
EFLAGS中的状态标志
EFLAGS的状态标志代表什么意思呢?它们代表的是算数指令(arithmetic instruction)的结果状态,算数指令就是大家熟悉的的加减乘除,ADD,SUB,MUL和DIV,当然还有很多其他指令暗含有这些基本的算数指令,比如cmp指令就暗含有sub操作,因此cmp也会影响状态标志。
typedef struct _EFLAGS
{
unsigned CF : 1; // 进位或错位
unsigned Reservel1 : 1; // 对Dr0保存的地址启用 全局断点
unsigned PF : 1; // 计算结果低位包含偶数个数1时 此标志位1
unsigned Reservel2 : 1; // 对Dr0保存的地址启用 全局断点
unsigned AF : 1; // 辅助进位标志 当位3处 有进位或结尾时 该标志为1
unsigned Reservel3 : 1; // 保留
unsigned ZF : 1; // 计算结果为0时 此标志位1
unsigned SF : 1; // 符号标志 计算结果为负时 该标志位1
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2019-9-14 18:17
被黑手鱼编辑
,原因: