首页
社区
课程
招聘
[分享]VMP学习笔记之万用门(七)
发表于: 2019-9-14 18:04 26872

[分享]VMP学习笔记之万用门(七)

2019-9-14 18:04
26872

主题:万用门介绍

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 被黑手鱼编辑 ,原因:
上传的附件:
收藏
免费 11
支持
分享
最新回复 (9)
雪    币: 29182
活跃值: (63621)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
2
前排沙发!感谢楼主分享!
2019-9-14 19:14
0
雪    币: 775
活跃值: (1129)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
3
大佬6去哪里了
2019-9-14 23:14
0
雪    币: 1435
活跃值: (4508)
能力值: ( LV9,RANK:220 )
在线值:
发帖
回帖
粉丝
4
xuanzee 大佬6去哪里了
没整理就没发了后面有空再发
最后于 2019-9-14 23:31 被黑手鱼编辑 ,原因:
2019-9-14 23:28
0
雪    币: 9057
活跃值: (5301)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jgs
5
搞懂后,爆破的方法之一
2019-9-15 18:28
0
雪    币: 175
活跃值: (2601)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
精品,1-6在哪里·?
2019-9-16 19:25
0
雪    币: 1435
活跃值: (4508)
能力值: ( LV9,RANK:220 )
在线值:
发帖
回帖
粉丝
7
xingbing 精品,1-6在哪里·?
最后于 2019-10-13 00:25 被黑手鱼编辑 ,原因:
2019-10-13 00:18
0
雪    币: 12502
活跃值: (3068)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
精彩,看完这部分内容,感觉还原还是可行的。

比如虚拟了cmp、test、sub、and,那么我们可以运算根据前后的内容,以及屏蔽的mask,结合最终的eflasg和result运算结果,化简一些公式,简单确定出这是个and还是cmp(要是觉得化简麻烦可以自己用计算器计算),最终得出 vm_calculate a,b这种形式;

如果后面还有jcc指令被虚拟了,我们需要查一下手册的eflags结合一些mask的动态数据815等等,确定他取了哪些eflags位,是zf还是cf,至于jcc的两个目的地址,需要找到前面push imm中的imm和后面shr后的两种结果,利用v_addf加上来,组合成 imm+a和imm+b的形式,这样还原出的指令就是两条指令
jcc imm+a
jncc imm+b

现在比较麻烦的就是,前面的各种混淆和乱序,会影响我们看到完整的指令,也就是说我们看不到handle,针对这个,我是利用x32dbg的python脚本,我的脚本原理是:在vm入口处(也可以是片段处)停下,unicorn模拟部分代码,然后脚本去混淆,这样会得到我们想要的一些handle的位置,输出到一个txt文本,然后我们根据这个txt分析哪些地方需要下断,我们就同样脚本下断,然后把那些内存实际的值记录下来,这样既可以得到实际运行的数据又可以得到干净的handle。
以后不论是做破解还是patch,都会方便很多。
2020-2-5 09:56
1
雪    币: 2590
活跃值: (4455)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
10
2023-12-4 10:48
0
游客
登录 | 注册 方可回帖
返回
//