首页
论坛
课程
招聘
[原创] 记录一下从编译的角度还原VMP的思路
2023-1-11 17:52 12409

[原创] 记录一下从编译的角度还原VMP的思路

2023-1-11 17:52
12409

1 摘要

1.1 关于代码优化与还原

关于还原,我认为难点是工作量大,需要自动化提升效率

 

还原和混淆是一对反义词,相同点是保证代码功能相近,不同是一个是使代码更易读,后者则相反

 

而代码优化非常类似,也要保证代码功能相近,不同是减少代码的体积运行速度

 

所以我感觉还原和代码优化有很多共通点

 

然后尝试了一下从编译的角度去做自动化还原,这里分享一下思路,算是画一个不太完美的句号吧

1.2 还原流程

我的还原流程简单来说就三步:

  1. 识别汇编对应的语义(翻译虚拟机字节码)
  2. 虚拟指令转换成C
  3. 二次编译,利用编译器优化

第三步可以针对性的实现一些优化,因为vmp是一个基于栈的虚拟机,编译器的优化效果有限

 

第一步是我做的比较多的一部分,在后面的实现过程会说具体思路

2 实现过程

2.1 Handler语义识别

这一步说的是怎么判断Handler对应的虚拟机指令

2.1.1 浅谈VMP的CFG

Handler识别首先绕不开一个问题,怎么找到Handler在哪

 

关于VMP 3.X的架构这里简单说一下

 

在VMP2中会有一个分发器,所有Handler的地址都存在一个数组中,很容易就能把所有Handler找出来;但到了3,分发方式变成从字节码中解码出下一条指令的地址

2.1.2 模拟执行输出虚拟指令

目前分析到两种跳转方式:

1
2
mov reg
jmp reg

1
2
push reg
ret

我的思路是模拟执行,遇到jmp reg或者push ; ret时就代表一条Handler已经结束,reg中的是下一条Handler的地址

 

所以可以构建一个Handler 虚拟地址虚拟指令的映射

 

模拟执行还有一个好处,对于不同的虚拟指令,在Handler中下断,让Handler自己解密字节码中的内容,然后提取出来

2.1.3 Handler识别

关于Handler的语义是什么就省略了

 

根据jmp regpush ; ret把Handler提取出来后,现在就需要识别其对应的虚拟机指令

 

两种思路:

  • 正则表达式匹配(速度块)
  • DAG或者数据流图匹配

2.1.3.1 正则匹配

这是我目前正在用的方案,对汇编代码使用正则表达式匹配

 

矛盾点是正则规则越严格,漏判越严重,规则越宽松,误判越严重

 

缓解方案是对汇编代码先进行一次优化,参考编译原理中的死代码消除,对寄存器的使用进行分析

 

以一个加法的Handler为例:

 

比如优化前的Handler:

 

handler_add_asm

 

其中4、5、10、11行连续对rdi寄存器进行了写入,显然前三条写入是无效的

 

优化后的Handler:

 

handler_add_asm_deobf

 

正则匹配:

 

handler_add_regex

2.1.3.2 DAG匹配

这部分只是做一个尝试

 

同样是加法的例子,这是其DAG图(不太严格,因为x86复杂指令集有点麻烦)

 

蓝色下划线是从栈获取的操作数

 

绿色下划线是将结果和RFLAGS放回栈

 

handler_add_dag

2.1.4 识别结果

模拟执行顺序执行的片段:

 

vasm

2.2 控制流还原

2.2.1 虚拟机指令DU分析

先分析每条虚拟机指令对栈的读写,然后构建DU链

 

接着利用DU链进行一次简单的优化,包括常量传播,折叠一些变量在VM栈和VM寄存器上的移动,还有简单的MBA表达式优化(简化接下来的判断分支等步骤)

2.2.2 判断是否为分支

进行到这里就可以判断是jmp还是jcc

 

jmp的例子(左边是每条指令起始时VM字节码指针和VM栈指针):

 

vasm_jmp

 

jcc的例子:

 

vasm_jcc

 

区别就是RET之前的一条语句PUSH的是否为一个立即数(依赖前面的常量传播优化)

2.2.3 获取分支去向

接下来就可以通过DU链,获取分支的两条去向分别是什么

 

依据是VMP的分支跳转伪代码为:

1
2
3
4
mask = -1 + flag
a1 = mask & FAddr
a2 = ~mask & TAddr
jmp = a1 + a2

这里是识别的例子:

 

vasm_du_jcc

2.2.4 获取分支条件(未完善)

这里我大致分成了两步:

  • 识别判断的rflags标志位
  • 识别~(~x+y)

一个比较标准的test x-y,然后判断CF的例子

 

绿色框是上一步的跳转地址计算

 

黄色框是rflags标志位的判断

 

红色框是计算x-y的rflags

 

vasm_du_jcf

 

一个and x, x,判断是否为0的例子

 

绿框是上一步的跳转地址计算

 

黄框是判断其ZF位

 

红框是读取内存,然后获取其and x, x的rflags,没识别到

 

vasm_du_jzf_nn

2.2.5 控制流还原杂谈

在前面Handler语义识别的时候,难免会有错漏,出现识别不了的语句

 

在模拟执行还原控制流时,妥协做法是停止该分支的分析

 

这里截取了一段控制流

 

每个圈圈是一个虚拟指令基本块

 

这里绿色箭头的是前面flag=1分支、红色箭头是前面flag=0的分支

 

红色圈圈的是遇到未知虚拟指令或模拟执行错误,停止分析的块

 

vasm_bb

2.3 还原成C(做的不太好)

这一步随便水水了,只做了一部分,主要工作量太大了

 

将虚拟指令输出成对应的C语言代码,然后上编译器编译

 

给个加法的例子吧:

 

vasm_c_compile

3 结尾(欢迎指教)

3.1 收获

比较喜欢写代码吧,vmp代码还原的自动化又是个需要写很多代码的工程,就比较感兴趣,断断续续大学花了不少时间在这上面

 

最大的收获是经验吧,写的时候花了很多时间在debug上,实际写的时间根本没多少

 

我也明白,先设计好再写代码可以减少很多写代码和debug的时间,但缺乏还原经验,设计的时候无从入手,也考虑不周全,只能边写边想

 

算是积累了一些经验吧

 

然后实践了一下编译原理的入门知识,一个非常有意思的领域,希望以后有机会继续深入学习下去吧

3.2 关于分析深度和还原难度

在还原的过程中,我发现对虚拟机架构的分析越多,获得更多关于壳的信息,就能写出更容易实现、更有针对性、更有效果的优化

 

有点类似窥孔优化的思路,牺牲通用性,以便实现和提高效果

4 相关链接

VMP架构与虚拟机指令:

 

VMProtect 2 - Detailed Analysis of the Virtual Machine Architecture // Back Engineering

 

虚拟机分支分析:

 

[分享]VMP学习笔记之万用门(七)-加壳脱壳-看雪论坛-安全社区|安全招聘|bbs.pediy.com (kanxue.com)

 

vmp3.5模拟x86分支指令je、jne、jge和jl的分析-软件逆向-看雪论坛-安全社区|安全招聘|bbs.pediy.com (kanxue.com)

 

编译原理(哪本书不记得了):

  • 基本块的有向无环图表示
  • DU链

加密与解密


[2023春季班]《安卓高级研修班(网课)》月薪两万班招生中~

最后于 2023-1-11 20:19 被wx_御史神风编辑 ,原因:
收藏
点赞16
打赏
分享
最新回复 (13)
雪    币: 1662
活跃值: 活跃值 (3207)
能力值: ( LV4,RANK:55 )
在线值:
发帖
回帖
粉丝
smallzhong_ 活跃值 2023-1-11 18:23
2
1
资瓷
雪    币: 669
活跃值: 活跃值 (2826)
能力值: ( LV6,RANK:98 )
在线值:
发帖
回帖
粉丝
还我六千雪币 活跃值 2023-1-11 18:38
3
1
学,我继续学
雪    币: 4049
活跃值: 活跃值 (19914)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
shinratensei 活跃值 1 2023-1-11 19:33
4
1
优秀
雪    币: 57
活跃值: 活跃值 (734)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zbzb 活跃值 2023-1-11 20:58
5
0
赞一个!
雪    币: 301
活跃值: 活跃值 (376)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
初学者有毅力 活跃值 2023-1-11 21:46
6
0
得到handle再用规则就可以还原了,但是效率是一个很大的问题!  
雪    币: 821
活跃值: 活跃值 (1334)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Grav1ty 活跃值 2023-1-11 22:30
7
0
mark
雪    币: 4
活跃值: 活跃值 (425)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
菜鸟也想飞 活跃值 2023-1-12 11:03
8
0
感谢分享!
雪    币: 2034
活跃值: 活跃值 (1632)
能力值: (RANK:260 )
在线值:
发帖
回帖
粉丝
xiaohang 活跃值 3 2023-1-12 12:14
9
0
先行关注,期待后边的完善
雪    币: 1564
活跃值: 活跃值 (111)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wangez8 活跃值 2023-1-12 16:12
10
0
感谢分享!
雪    币: 2142
活跃值: 活跃值 (2063)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
fengyunabc 活跃值 1 2023-1-13 11:58
11
0
感谢分享!
雪    币: 642
活跃值: 活跃值 (37)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kxreax2 活跃值 2023-1-13 14:49
12
0
感谢分享
雪    币: 5604
活跃值: 活跃值 (2743)
能力值: ( LV4,RANK:55 )
在线值:
发帖
回帖
粉丝
Jev0n 活跃值 2023-1-15 18:41
13
0
资次
雪    币: 202
活跃值: 活跃值 (252)
能力值: ( LV4,RANK:41 )
在线值:
发帖
回帖
粉丝
14
0
获取handler后可以先转成IR,然后优化后再得到简化的IR指令进行匹配再次转换为新的IR指令
组合一起再次进行IR优化,转换后用现用的工具转成c
游客
登录 | 注册 方可回帖
返回