通过一道简单的例题了解Linux内核PWN (3)

接下来我们复制exp到文件系统下,然后使用cpio命令重新打包:

unravel@unravel:~/pwn$ cp exp core/tmp/ unravel@unravel:~/pwn$ cd core/ unravel@unravel:~/pwn/core$ ls bin etc home init lib linuxrc proc rootfs.cpio sbin sys tmp usr unravel@unravel:~/pwn/core$ find . | cpio -o --format=newc > rootfs.cpio cpio: File ./rootfs.cpio grew, 3522560 new bytes not copied 14160 blocks unravel@unravel:~/pwn/core$ cp rootfs.cpio ..

下一步就可以重新运行内核了。执行boot.sh启动内核后,在刚才拷贝的/tmp目录下找到exp可执行程序:

/ $ ls -la /tmp/ total 864 drwxrwxr-x 2 ctf ctf 0 Dec 16 09:35 . drwxrwxr-x 13 ctf ctf 0 Dec 17 08:35 .. -rwxrwxr-x 1 ctf ctf 883168 Dec 17 08:30 exp

执行后可得到root权限,提权成功:

/ $ id uid=1000(ctf) gid=1000(ctf) groups=1000(ctf) / $ /tmp/exp [ 115.517513] device open [ 115.522342] device open [ 115.527241] alloc done [ 115.532132] device release [+] root now. / # id uid=0(root) gid=0(root) groups=1000(ctf)

调试

可以在boot.sh文件中添加-s参数来使用gdb调试,它默认端口1234。也可以指定端口号进行调试,只需要使用-gdb tcp:port即可。在启动的内核中使用lsmod查看加载的驱动基地址,得到0xffffffffc0000000,然后启动gdb,使用target remote指定调试IP和端口号进行调试,然后添加babydriver的符号信息,过程如下:

# 在QEMU运行的内核中运行如下命令 / $ lsmod babydriver 16384 0 - Live 0xffffffffc0000000 (OE) # 启动gdb,配置调试信息 gdb -q gef➤ target remote localhost:1234 Remote debugging using localhost:1234 gef➤ add-symbol-file pwn/core/lib/modules/4.4.72/babydriver.ko 0xffffffffc0000000 add symbol table from file "pwn/core/lib/modules/4.4.72/babydriver.ko" Reading symbols from pwn/core/lib/modules/4.4.72/babydriver.ko...

这里建议使用gef插件,pwndbg和peda调试内核总有一些玄学问题。如果gef报错context相关问题(如下图),在gdb中输入命令python set_arch()就可以查看调试上下文了:

通过一道简单的例题了解Linux内核PWN

我们之前在gdb中使用add-symbol-file命令加载了babydriver.ko的符号信息,并指定了加载基地址,在下断点的时候可以直接使用符号来打断点:

通过一道简单的例题了解Linux内核PWN

总结

通过一道题认识了内核PWN的解题步骤,以及如何对内核进行调试。对于不知道用法的内核函数和结构体,可以在manned.org网站或者源码中查看。

参考资料

CTF-WIKI链接:

Linux在线源码:

MannedOrg:https://manned.org/kmalloc.3

QEMU手册:https://www.qemu.org/docs/master/system/quickstart.html

UNICORN:https://www.unicorn-engine.org/docs/

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgzfwz.html