虚拟机逃逸漏洞(CVE-2017-4901)的研究以及复现

前言:

      这个项目是我在2017年和黎镓辉同学申请的南京邮电大学STITP(大学生创新训练计划)项目,指导老师是沙乐天老师。

      在将近一年的紧凑时间内,我和黎镓辉同学在老师以及学长的帮助下,从立项开始一点点地开始学习如何复现这个当时还十分火热的CVE。

      由于当时还没有系统学习网安专业知识,研究时间也是在课余时间里挤出来的,因此会有一些仓促,但好在有了老师的指导,我们最终成功进行了复现并提出了一些改进方法。

      由于大多数资料以及报告都保存在另一位同学那边,由于特殊原因已经难以找到当时的报告以及部分研究调试数据,为此我根据最终答辩时的PPT制作了这个核心思路总结概述。

      总结的过程有一些简陋,如果有所缺漏请指出,谢谢。

 

正文:

1、 后门(BACKDOOR)接口

  使得在用户态就可以通过这个接口发送命令和host通信

 函数中含有一个”inl”指令会导致用户态程序产生权限错误

 该错误会被host的hypervisor捕捉从而实现通信,类似于一个错误中断

 

2、 RPCI(Remote Procedure Call Interface)

  基于Backdoor机制实现,通过这个机制,guest可以向host发送请求完成某些操作

例如拖放(Drag n Drop)和复制黏贴(Copy Paste)

RPCI依据info-get guestinfo.ip获取guest的ip地址,这是通过套接字实现的

 

3、 漏洞

  类似于过去在Version4中所出现的漏洞,在Version3中也同样存在

当guest发送DnD/CP数据包时,host会重组guest发送的DnD/CP消息

关键问题在于,函数只检查了包头的buffer长度,对后续的数据包检查无效,

因此可以在后续的包中指定更大的binarySize来满足检查,触发溢出

 

4、 漏洞利用执行方法

  我们需要在堆上覆盖一个函数指针,或者破坏C++的虚表指针

(1)首先将DnD/CP协议设置为version 3,RPCI在检查到DnD/CP协议版本修改时会创建一个对应版本的C++对象,对于version3,两个C++对象会被创建,一个用于DnD,一个用于CP

(2)分配一个内存块,让它分配在C++对象前,利用堆溢出改写C++对象的vtable指针(虚表),让其指向可控内存,执行SHELL

 

5、 绕过ASLR

  在实现上述过程首先要绕过保护机制ASLR(地址空间布局随机化)

关键在于找到能够破坏的,带有长度或数据指针的对象,并且可以被guest读取

于是找到了“info-set”和”info-get”

我们可以通过溢出来覆盖结尾的null字节,让字符串连接上相邻的内存块。如果我们能够在发生溢出的内存块和DnD或CP对象之间分配一个字符串,那么我们就能泄露对象的vtable地址,从而我们就可以知道vmware-vmx的地址。

 

问题在于,这种覆盖可能导致关键函数被覆盖从而崩溃

 

具体实现策略:

1.首先分配一些填满“A”的字符串,

2.然后通过溢出写入一些“B”,

3.接下来读取所有分配的字符串,其中含有“B”的就是被溢出的字符串。

4.这样我们就找到了一个字符串可以被用来读取泄露的数据,然后以bucket的内存块大小0xA8的粒度继续溢出,每次溢出后都检查泄露的数据。

5.由于DnD和CP对象的vtable距离vmware-vmx基地址的偏移是固定的,每次溢出后只需要检查最低一些数据位,就能够判断溢出是否到达了目标对象。

 

虚拟机逃逸漏洞(CVE-2017-4901)的研究以及复现

                                                                                         执行流程图

 

6、 两种情形,两种方法

(1)DND

  不能只覆盖vtable指针,需要伪造一个vtable来躲避访问

(2)CP

  覆盖虚指针,让它指向我们可控的其他数据,这些数据可以用作对象虚表,只要我们找到一个指向可控数据的指针就可以解决

虚拟机逃逸漏洞(CVE-2017-4901)的研究以及复现

 

虚拟机逃逸漏洞(CVE-2017-4901)的研究以及复现

 

7、 如何解决LFH堆问题

  LFH堆一旦开启便无法关闭,但是使用一些全局标志可以导致无法启用LFH(gflag调试)

 

8、 例图

虚拟机逃逸漏洞(CVE-2017-4901)的研究以及复现

 

由于我们之前执行获得的结果截图没有保存,因此这里使用的是原作者的例图。

我们使用的是WINXP虚拟系统实现的逃逸。

 

上一篇:Armv8-A虚拟化手册(1)


下一篇:人生第一次使用ECS服务器