Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save puppykitten/443cf0b3902416a4c15d6fea453a8494 to your computer and use it in GitHub Desktop.
Save puppykitten/443cf0b3902416a4c15d6fea453a8494 to your computer and use it in GitHub Desktop.
EC3
The challenge:
* Players are provided with a custom build qemu binary and a minimal linux system image.
* After connecting to the remote service root access is granted to the qemu guest.
* The qemu binary contains an extra pci device, called ooo. Which is heavily based on the EDU pci device present in the qemu sources.
* The relevant parts of this pci device are the mmio read and write functions which are used to implement a conventional CTF style menu system.
* This menu system can be navigated by addressing different mmio registers.
* The following primitives are implemented by the device:
* mallocate memory with given size
* free previously allocated memory
* read and write allocated memory with a user provided, unchecked, signed short offset
* The qemu binary is compiled with a "win" function that prints the flag.
Exploit plan:
* Use fastbin poisoning to get a fastbin allocation in the data section
* This must be in the close proximity of the got so the entries there can be overwritten with the unchecked write primitive
* Overwrite got entry to redirect execution flow to the "win" function
Actual exploit:
* I wrote simple kernel driver that interfaces with the pci device and compiled it against the same ubuntu kernel that is used by the guest
* To send the driver to the remote host I stripped the module then gzipped it then base64 encoded it
* Also written a simple gdb script that scans the area around the got for potential fastbin chunk candidates. They need to satisfy the following set of criteria:
* First qword must contain fastbin size (between 0x20 and 0xa0)
* The IS_MMAPPED bit (2nd) must be set, otherwise the assert at end of libc_malloc fails. This is because we are trying to allocate a main arena chunk from a different arena. Simply setting the NON_MAINARENA bit is insufficient because then the get arena function leads to null pointer dereference. If the IS_MMAPPED bit is set the assert is always passed regardless of the value of the two other bits.
* The second qword must be null to avoid corrupting the fastbin freelist.
* The exploit first makes a few hundred allocation of the designated fastbin size to empty the corresponding free list.
* After that, it frees few of the chunks and corrupts the forward pointer in one of them so that it points to the victim chunk.
* Then it allocates 15 chunks to ensure that we get back the poisoned chunk.
* The got contains plt addresses for unresolved relocations, which are known values at a known offset from the victim chunk. They can be used to verify which chunk is the correct one.
* Overwrite the got entry for free and free a chunk to get the flag.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment