Kernel Pwn: 从入门到入土

MISC

内核文件区别

vmlinux 是静态链接的可执行文件,未压缩的内核,最原始的文件,可以用来调试。

vmlinuz 是可引导的、压缩的内核。没有调试信息等数据,不可用于调试。启动时会自解压,通常会显示以下信息

1
2
Decompressing Linux... done
Booting the kernel.

zImage 是经过压缩的小内核(小于512KB)。

bzImage 是经过压缩的大内核(大于512KB)。

Initial Ramdisk

名字类似initramfs.cpio 文件,一般可以使用cpio读取其中的文件。

1
2
$ find . | cpio -o --format=newc > initramfs.cpio # compress
$ sudo cpio -idmv < initramfs.cpio # depress

有时也经过了gzip的压缩。

1
2
3
$ mv initramfs.cpio initramfs.cpio.gz
$ gunzip initramfs.cpio.gz	# 解压得到initramfs.cpio
$ cpio -idmv < initramfs.cpio

更改为正确的后缀之后,图形界面“归档管理器”也可以打开。

Arm Pwn

环境配置

1
$ sudo apt install qemu-user gdb-multiarch

安装完成后就可以运行平台上的静态链接文件了,会自动调用qemu执行。

动态链接程序

对于动态链接的程序,还需要安装跨平台的lib。

1
$ apt-cache search "libc" | grep arm

安装类似libc6-ARCH-cross。

动态链接库被安装在类似/usr/arm-linux-gnueabihf/的路径。qemu不知道动态链接的位置,它预期在类似/etc/qemu-binfmt/arm的路径,所以可以设置软链接来避免用-L来指定链接库位置。

1
2
3
$ sudo mkdir /etc/qemu-binfmt
$ sudo ln -s /usr/arm-linux-gnueabihf /etc/qemu-binfmt/arm
$ sudo ln -s /usr/aarch64-linux-gnu/ /etc/qemu-binfmt/aarch64 # 对于aarch64

pwnable.tw re-alloc_revenge

题目分析

防护比re-alloc多了FULL RELRO和PIE。其他没有改变。

总体思路

程序没有show函数,所以通过修改stdout的方式泄露libc。

将一个chunk同时释放到tcache和unsorted bin,partial overwrite fd部分,指向stdout,需要爆破4bit。取得stdout后修改进行泄露。

最后修改__realloc_hook为one_gadget得到shell。

主要难点在布局构造。

R7000梅林搭建ipv6代理

目前宽带基本都支持了ipv6(可能需要自己在光猫开启),为了在学校省流量,利用家庭宽带的ipv6环境搭一个代理。 R7000固件版本是kool

pwnable.tw tcache_tear seethefile

tcache_tear

分析

1
2
3
4
5
6
7
8
Arch:     amd64-64-little
RELRO:    Full RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      No PIE (0x400000)
FORTIFY:  Enabled

libc_version: Ubuntu GLIBC 2.27-3ubuntu1

程序开始在bss段上读入了一个0x20的名字

malloc: 输入指定size,分配,指针ptr同样存储在bss,读入size-16的字符,这里字符个数可以溢出

free: 释放ptr空间,指针悬空,可以double free,程序使用了tcache,且在这个版本释放没有任何的检查

info: 打印姓名

总体思路

利用tcache double free,可以对任意地址进行改写。在name处伪造一个chunk释放到unsorted bin,进行libc base的泄露。将__free_hook改写为system地址。

伪造chunk注意绕过free的所有检查。伪造完成的结构如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
+----------+
|          |
|          |
|  0x421   |
|          |
+----------+
|  0x21    |
+----------+
|  0x21    |
+----------+

tcache默认最多有64个,第1个是0x20大小,递推第64个也就是0x410。所以将name处伪造为0x420大小。第一个chunk的chunk->size=0x420|pre_in_use,避免backward consolidate,第三个chunk的chunk->size=0x20|pre_in_use,避免forward consolidate。