Linux kernel调试环境:10分钟开箱即用

下载文件系统

https://github.com/PKFXXXX/kbin
这里也可以换成busybox自己编译,见下文,但是我懒,就找同事要了一个。
直接下载解压即可。

首先apt安装qemu

直接sudo apt install qemu

编写 boot.sh

bzImage是内核镜像 由vmlinux压缩而来 initramfs.img是磁盘镜像。

1
2
3
4
5
6
7
8
9
qemu-system-x86_64 \
-m 256M \
-kernel ./bzImage \
-initrd ./initramfs.img \
-smp 1 \
-append "root=/dev/ram rw console=ttyS0 oops=panic panic=1 nokaslr quiet" \
-s \
-netdev user,id=t0, -device e1000,netdev=t0,id=nic0 \
-nographic \

-s选项是gdb调试用的 端口默认是1234.

然后./boot.sh则进入qemu虚拟机。

添加文件

如果需要添加什么文件,就解压然后放入文件之后重新打包

  • 解压磁盘镜像

    1
    2
    3
    4
    mkdir core
    cp initramfs.img core/
    cd core
    cpio -idv < ./initramfs.img
  • 重打包

    1
    2
    cd core
    find . | cpio -o --format=newc > ../initramfs.img

gdb attach调试

1
2
3
sakura@ubuntu:~/kbin/kernel_env$ gdb -q
(gdb) set arch i386:x86-64
(gdb) target remote localhost:1234

这里set arch i386:x86-64是为了解决一些奇妙的bug,如果不加可以调试就不用加了。

查看函数地址

如果要查看函数的地址,可以通过cat /proc/kallsyms搜索,但是需要root权限
在本地获得root权限可以直接去改磁盘镜像根目录下的init文件。这个init文件会在kernel初始化后执行。
sakura@ubuntu:~/kbin/kernel_env/core$ cat init

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/sh

mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs devtmpfs /dev

exec 0</dev/console
exec 1>/dev/console
exec 2>/dev/console

echo -e "\nBoot took $(cut -d' ' -f1 /proc/uptime) seconds\n"
setsid /bin/cttyhack setuidgid 0 /bin/sh
umount /proc
umount /sys
poweroff -d 0 -f

这里的重点是setuidgid 0则创建一个root shell。
然后断下来就是这样。

编译busybox[可选]

1
2
3
4
5
6
7
wget https://busybox.net/downloads/busybox-1.30.0.tar.bz2
tar -jxvf busybox-1.30.0.tar.bz2
cd busybox-1.30.0
make menuconfig
进Settings,勾上Build static binary (no shared libs)

make install -j4

编译完成后跟目录多了一个_install的目录,就是我们编译的结果了。

1
2
3
4
5
cd _install
mkdir proc
mkdir sys
touch init
chmod +x init

其中init中添加如下内容

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/sh
echo "{==DBG==} INIT SCRIPT"
mkdir /tmp
mount -t proc none /proc
mount -t sysfs none /sys
mount -t debugfs none /sys/kernel/debug
mount -t tmpfs none /tmp
# insmod /xxx.ko # load ko
mdev -s # We need this to find /dev/sda later
echo -e "{==DBG==} Boot took $(cut -d' ' -f1 /proc/uptime) seconds"
setsid /bin/cttyhack setuidgid 1000 /bin/sh #normal user
# exec /bin/sh #root

然后打包
find . | cpio -o --format=newc > ../initramfs.img

编译内核,替换原本的bzImage

1
2
3
4
5
sudo apt-get install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison
wget https://mirrors.tuna.tsinghua.edu.cn/kernel/v5.x/linux-5.3.tar.gz
tar -xf linux-5.3.tar.gz
cd linux-5.3/
make menuconfig


如图可以通过dir命令设置好内核源码目录,就可以带源码调试。

总结

总结一下,下载最前面我发的环境,然后直接./boot.sh就可以启动了,然后另开一个终端gdb attach上去就能调试了。
以后要调试别的版本的内核,也就只要自己编译一个对应版本的,替换掉原先的bzImage即可。
需要执行自己写的poc,就解压文件系统,然后放进去,然后重打包就好了,嫌麻烦的话,自己搭建一个server存文件,然后wget也可以,不过qemu里面的network环境相当神奇。