虚拟机逃逸初探----2018rwctf_station-escape

admin 2022年6月28日09:47:29评论67 views字数 3606阅读12分1秒阅读模式

点击 / 关注我们

这里的rwctf_station-escape的主要基于长亭师傅(https://zhuanlan.zhihu.com/p/52140921)在知乎的文章进行,在此基础上进行了比较详细的exp分析和调试

静态分析

这里从头开始,一般出现在ctf的虚拟机逃逸会有俩个vmx,一个是原来正常的,另一个是patch过的 使用010editor比较俩个文件的异同

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

有俩处不同,拖进ida,找到对应的地址看看改了啥

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

查看被patch过的地址

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

在0x1893c9(379)指针置null的操作被nop掉了 另一个在0x1893e6(383)处的函数调用中,replay_type&1变成了v7&0x21 +7对应的成员out_msg_buf 如果该句被nop掉,out_msg_buf指针没有被置NULL,其次在第二处patch中,原先被限制的reply type(&0x1)变成了&0x21,也就是说在finish_recv_func(sub_177700)中可以存在free部分再次释放out_msg_buf

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

这个patch会导致UAF:如果我们在接收完成之后设置了0x21这个位,那么output buffer就会被释放掉,但由于它没有被清零,所以理论上我们可以无限次的将它free掉。可以通过 多次执行 case 5释放 输出缓冲区,最后制造一个 double free的漏洞。然后利用 info-get和 info-set命令,实现堆块的分配。利用RPC的发送命令和接受返回来实现堆块布局 这里的思路借鉴长亭师傅 利用思路 Leak: 1. 开两个channel:A和B,A的output buffer为buf_A,然后A释放buf_A 2. 这时让B准备给guest发output,B会分配一个buffer,我们利用info-set和info-get来控制我们分配的buffer大小,使得B的output buffer: buf_B=buf_A。3. A再次释放buf_A,这也导致了buf_B被释放。这个时候我们就可以leak出buf_B的fd了,但是这个指针没有什么用,我们想要的是text base。4. 因此我们再执行命令vmx.capability.dnd_version,这会让host分配一块内存来存放一个obj,通过控制buffer大小我们可以刚好让buf_B被用来存放一个obj。而这个obj里面有vtable,我们可以leak出来计算text base。注意我们一直没有接受B的输出,只是让它做好准备(分配output buffer)。直到这个时候我们才接受它的输出,完成leak Exploit 有了leak的方法,exploit的也是类似的了。简单来说就是UAF,把tcache的fd改到bss段,然后改函数指针为system,最后弹calculator 给出作为一个通信的结构体 这里参考了Alex师傅的符号说明 https://a1ex.online/2021/05/28/2018-RealWorld-Station-Escape/

虚拟机逃逸初探----2018rwctf_station-escape
图片.png


exp分析

主要看的部分主要是leak()和 expilot()部分,channel_recv_finish2()函数就是把rbx改为0x21最后会执行到free操作

Run_cmd()

发送命令进行执行

Leak()

初始化操作,这里使用 info-set命令发送了0x100的信息,在后续只要使用info-get命令就可以执行malloc(0x100)的操作,这里0x100是因为dnd_version为4时会分配一个0x100的Obj。

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

第一步:开启通道0,此时通道0分配了buf为0x100

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

第二步:开启通道1,发送指令分了俩部分,在俩个发送指令之间释放了通道0的内存,此时再发送完指令后,通道1的内存块为buf

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

第三步,再次通过通道0释放buf(因为指针一直没有置0,就可以一直释放),执行"vmx.capability.dnd_version",在发送“vmx.capability.dnd_version” 命令的时候,对应的处理函数中如果发现当前版本和设置的版本不一致,就会调用函数创建新的 object,把原来的版本的object销毁。再开始时发送指令tools.capability.dnd_version 4,会使得这个分配的大小为0x100。此时的object就会到buf的位置。object里包含vtable的地址,再次通过通道1进行数据的返回(之前一直没有),进而得到数据的基地址

虚拟机逃逸初探----2018rwctf_station-escape
图片.png


Expilt()

类似于leak,此时的buf安排的大小是0x150 开启四个通道,通道0先malloc出0x150的空间

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

此时通道0指向buf,第一次0释放,分配1通道,此时1指向buf,buf存在 第二次0释放,buf不存在,此时1通道进行写操作,当内存块不存在时,此时1通道写的位置其实是下一块的地址,pay1是一个在bss段上,且一定存在call的一个地址 Exp中的是FE95C8,可以对应下列的位置

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

其中rax调试会发现一直为0 分配通道2,buf存在 分配通道3,此时分配的地址应该是buf的下一个的地址,也就是会在bss段上分配出一个buf出来,之后再写入system等参数,相当于此时在bss段写入一个可控的的system函数,因为该地址一定会被call,之后再进行通信,就能触发我们写入的函数。

虚拟机逃逸初探----2018rwctf_station-escape
图片.png


Gdb调试

先正常启动guest 然后在host机中启动 sudo gdb /usr/lib/vmware/bin/vmware-vmx -q 使用ps -aux | grep vmware-vmx得到进程pid

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

在启动的gdb 中attach上去 (ps:这里有概率失败,我的处理办法是重启再开一次)

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

获取此时vmware-vmx的基址 输入codebase

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

此时将断点设在patch的位置

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

通过ssh远程连接guest执行exp

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

此是到达了patch中nop的位置

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

第一次达到

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

查看堆信息

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

因为发了0x100字节的信息,再加上堆块的一些size等8字节信息,此时大小未0x110 该地址就是bufA的位置

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

最后会将基址写到bufA的位置,但这里很奇怪的是,没有挂gdb泄露出的基址是正确的,也可以弹出计算器,但有时gdb一步步调试,泄露出的基地址是不对的,最后执行也会失败,这种情况可以多调试几次。可以确定该位置就是buf,之后所有的操作都是基于这一块内存进行操作

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

最后就是类似地劫持fd,把tcache的fd改到bss段,然后改函数指针为system,最后弹calculator 到达expilot部分的内存 断点可以设置在很多地方 比如设在codebase+0x1895AF的地方,这里的rdx寄存器存放的就是此时写入的地址,因为每次只能写4个字节,调试消耗的时间比较久 Ida如下

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

对应的是发送数据函数

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

这里挑选的bss地址是在程序中一定会执行到的,最后进行一次正常的通信,就会执行system打开计算器

虚拟机逃逸初探----2018rwctf_station-escape
图片.png

一些资料参考:https://www.cnblogs.com/studyskill/p/7279970.html


https://nafod.net/blog/2019/12/21/station-escape-vmware-pwn.html

https://xz.aliyun.com/t/7345

https://a1ex.online/2021/05/28/2018-RealWorld-Station-Escape/

https://matshao.com/2019/12/05/RealWorldCTF2018-Station-Escape/

https://www.anquanke.com/post/id/86483

推荐阅读:
ETW的攻与防
JNDI注入分析
浅谈EDR绕过
浅谈Windows传统取证
Learning Linux kernel exploitation P1- aying the groundwork(译文)


跳跳糖是一个安全社区,旨在为安全人员提供一个能让思维跳跃起来的交流平台。


跳跳糖持续向广大安全从业者征集高质量技术文章,可以是漏洞分析,事件分析,渗透技巧,安全工具等等。
通过审核且发布将予以500RMB-1000RMB不等的奖励,具体文章要求可以查看“投稿须知”。
阅读更多原创技术文章,戳“阅读全文

原文始发于微信公众号(跳跳糖社区):虚拟机逃逸初探----2018rwctf_station-escape

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年6月28日09:47:29
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   虚拟机逃逸初探----2018rwctf_station-escapehttps://cn-sec.com/archives/1140193.html

发表评论

匿名网友 填写信息