Menu

EC3 write-up (DEF CON CTF 2018 Quals)

You're dropped into a Linux virtual machine with root privileges, and your objective is to escape from the VM to read the flag on the host filesystem. Task description mentions some custom PCI device.

This virtual device's implementation has heap overflow vulnerability allowing read-write out-of-bounds access and UAF vulnerability. Although this is more than enough to leverage well-known heap exploitation techniques, due to my inadequate pwn skills, I decided to resort to heap spraying instead.

Reverse engineering

You're given an archive containing custom qemu-system-x86_64 binary along with some less interesting files like the kernel, initramfs image, bios-256k.bin and so on.

Nothing is known about this virtual PCI device at this point: no drivers, no documentation. The only option is to reverse-engineer its implementation. Although the binary is rather large (because it's a patched QEMU), finding the device wasn't too hard.

The device itself is really simple. It allocates so-called MMIO region in the RAM. Unlike ordinary RAM, memory accesses in MMIO range are intercepted by the device, and can cause side-effects. For example, if device in question was a serial port, read from certain location (so-called register) could pop next value from the input queue, and write could push given value into the output queue. Some other register may contain bitmask that describes current state of the devices: output queue full, input queue non-empty, current speed, and so on. Both real hardware devices and devices emulated by hypervisors are usually interacted with this way.

There're several bugs in there. First, you can access (both read and write) offsets from -32768 to 32767 from the allocated buffer regardless of its actual size. Second, you can use buffers after free.

Additionally, the binary also includes unreferenced function that calls system("cat flag"). So if we took control of the program counter (RIP), we can just jump there.

Exploitation

Although PCI devices are usually interacted with using kernel modules, Linux also provides a way to do so from userspace (provided you have root). The interface is described in Documentation/filesystems/sysfs-pci.txt.

In short, you need to open file /sys/devices/pci0000:00/0000:00:04.0/resource0 (numbers may obviously vary), mmap it into memory and access required offsets.

Since the initramfs contains very few binaries (basically, only busybox), exploit has to be written in C, compiled on some other machine into a statically linked binary, and then transferred to the VM (uuencode/uudecode is my tool of the choice for these kind of tasks).

Although vulnerabilities present were enough to gain RCE using well known heap exploitation techniques, I wasn't feeling confident enough to do so properly. I decided to play the dirty way.

The heap where overflow occurs is actually heap of QEMU itself. It has to contain some useful structures that can be overwritten, right?

Hoping that it would contain some function pointers, I scanned the heap for all values that looked like pointers into .text section of QEMU binary, and replaced all of them with address of aforementioned system("cat flag") gadget.

Unfortunately, these pointers were never called, and I got stuck for several hours.

My thought process was as follows. Assuming there're actually live pointers (as opposed to remainings of already freed memory), in order to increase the chances that they will be called, guest operating system has to ask the hypervisor or its virtual devices to do something. The more intricate, the better. There were very few of the devices available, and poking them would require to write some "drivers" for them, which would be rather troublesome.

Suddenly, an idea popped into my mind. ACPI is a known clusterfuck of weird shit. Attempting to suspend the machine will surely do something interesting. Suspend has to put all the devices to some sleep state, maybe even reset some of them, and so on.

And it actually did the trick. Attempting to suspend the guest operating system after running heap spraying exploit gives the flag (and then crashes the hypervisor :)).