赶在今年结束前把CTF中出现过的虚拟机逃逸利用都复现了,Vmware Workstation 和 VirtualBox、Qemu相比最大的难度自然是需要逆向方面,即使有Writeup的帮助还是花了不少时间。完成了这道题目感觉又向目标迈进了一步。😎
This is a chanllenge from Real World CTF 2018, heard about the party this year, really want to be there but didn’t earn a ticket in the qualification. Anyway, I’m following the writeup from r3kapig
: Real World CTF 2018 Finals Station-Escape Writeup and try to reproduce the escape exploit.
You can setup the challenge environment with following information:
1 | guest os:Ubuntu x64 1804 |
Recon
As it is showed in the writeup, the patches happen in 0x1893c9
and 0x1893e6
.
1 | // finish recv reply command |
in close_channel_handler(0x17700)
:
1 | void __fastcall close_channel_handler(RPCI_Channel *a1, unsigned __int16 channel_id, char flag) |
if we send a finish_recv_reply
command with reply_id | 0x20
, it will free the channel->outbuf
but did not set it to 0, which leads to an UAF.
The GuestRPC backdoor interface
The GuestRPC
backdoor interface was discussed in detailed in previous writeup. You can also found an outdated document from: https://sites.google.com/site/chitchatvmback/backdoor. r3kapig
developed the exploit in C language, but I read about a blog from zdi, talking about how to develop a vmware backdoor interface in python: Pythonizing the VMware Backdoor. So I decide to develop my own exploit in python, with familiar library pwntools
.
The first step is porting the assembly snippet to python, I found a method to execute assembly code with ctype
.
1 | libc = CDLL("libc.so.6") |
With the help of the handy asm
function from pwntools
and the recipe from previous writeup, I develop a python class to interactive with GuestRPC
:
1 | class GuestRPC(): |
We can test the channel like:
1 | c1 = GuestRPC(True) |
Exploit
Let’s use some graphs to illustrate the exploit step:
first we allocate a out buffer with channel2.
1 | Channel1.run_cmd("info-set guestinfo.a "A"*100") |
then we trigger the bug and free the outbuf, and make it occupied by channel3->outbuf
1 | cmd = "info-get guestinfo.a" |
then we close channel2 to free the outbuf again and make a sturcture to occupy it by sending vmx.capability.dnd_version
command. Then we can leak a address from .text
by receiving reply from channel3.
1 | Channel2.close() |
After leaking the .text
address and bypass ASLR, the exploit is straightforward, using the tcache posion technique, we can overwrite a function pointer on bss at 0xfe95b8
, I called it rpic_cmd_handler
, because it will be hitted when a command is received. We have system@plt
on the binary so no need to leak the libc address.
the code is as follow:
1 | # leak |
Demo