# qemu搭建Ubuntu发行版源码级内核调试环境 ## 前言 在进行CVE复现和写exp时经常会有需要一个Linux发行版的内核调试环境这样的需求。在发行版中内核编译参数通常不是默认的 defconfig 会开启额外的安全特性和一些优化策略,而且每个发行版通常单独维护一个内核版本,因此搭建一个发行版内核调试环境是很有必要的。本文以搭建 Ubuntu 18.04 为例介绍,发行版源码级内核调试环境的搭建过程。 ## 搭建流程 镜像获取地址: [1] https://releases.ubuntu.com/ [2] http://old-releases.ubuntu.com/releases/ 创建镜像文件并安装: ```shell $qemu-img create -f qcow2 ubuntu.img 20G $qemu-system-x86_64 -enable-kvm -boot d -cdrom /path/to/ubuntu-18.04-live-server-amd64.iso -m 1024 -hda /path/to/ubuntu.img ``` 安装中注意: - 分区磁盘时,请勿启用LVM; - 在安装步骤中换源以后会有ssh key 校验失败的问题,不换源又因为众所周知的原因安装缓慢,建议断网安装。 按如下方式启动: ```shell $qemu-system-x86_64 -enable-kvm -m 2048 -drive format=qcow2,file=/path/to/ubuntu.img,if=ide,cache=writeback -s -net user,hostfwd=tcp::2222-:22 -net nic ``` 至此,最低限度的设置已经完成,但使用图形界面启动qemu,传输文件会非常不方便,还需要再开启ssh服务: ```shell $sudo apt update $sudo apt-get install openssh-server $sudo service ssh start ``` 虚拟机外用 ssh 连接: ```shell $ssh -p 2222 user@localhost ``` ssh接入后将`/boot/vmlinuz-4.15.0-112-generic`拷贝到本机,之后通过如下命令启动qemu,这样可以绕过GRUB,关闭KASLR以及关闭图形界面。 ```shell qemu-system-x86_64 -enable-kvm \ -m 2048 \ -hda ./ubuntu.img \ -kernel ./vmlinuz-4.15.0-112-generic \ -append "root=/dev/sda2 nokaslr console=ttyS0" \ -nographic \ -monitor /dev/null \ -net user,hostfwd=tcp::2222-:22 \ -net nic \ -s \ ``` 至此内核调试环境已经搭建完毕,下面开始为该内核配置符号表: 在调试环境中添加GPG key: ```shell sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C8CAB6595FDFF622 ``` Ubuntu 16.04以下使用如下 key: ```shell sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys ECDCAD72428D7C01 ``` 添加源: ```shell codename=$(lsb_release -c | awk '{print $2}') sudo tee /etc/apt/sources.list.d/ddebs.list << EOF deb http://ddebs.ubuntu.com/ ${codename} main restricted universe multiverse deb http://ddebs.ubuntu.com/ ${codename}-security main restricted universe multiverse deb http://ddebs.ubuntu.com/ ${codename}-updates main restricted universe multiverse deb http://ddebs.ubuntu.com/ ${codename}-proposed main restricted universe multiverse EOF ``` 更新后,下载当前内核版本符号表: ```shell sudo apt-get update sudo apt-get install linux-image-$(uname -r)-dbgsym ``` 安装完成后可在`/usr/lib/debug/boot`目录下找到符号表。 最后一步,需要下载当前版本源码。 这里有两种方式,一种是直接 git 下载 ubuntu 官方维护的内核然后切换到要调试的分支即可。( 这种方法需要代理。) ```shell $git clone -b Ubuntu-4.15.0-112.113 git://kernel.ubuntu.com/ubuntu/ubuntu-bionic.git ``` 另一种是直接下载当前大版本的代码压缩包及到小版本的补丁包,patch后即可。(若无代理推荐此方法。) ```shell $ wget https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/linux/4.15.0-112.113/linux_4.15.0.orig.tar.gz $ wget https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/linux/4.15.0-112.113/linux_4.15.0-112.113.diff.gz /linux-4.15$ zcat ../linux_4.15.0-112.113.diff.gz | patch -p1 ``` 引入在调试环境中安装的符号表以及源码便可以开始愉快的调试了。 ```shel $ cat gdb.sh gdb \ -ex 'set arch i386:x86-64' \ -ex 'target remote localhost:1234'\ -ex 'file usr/lib/debug/boot/vmlinux-4.15.0-112-generic'\ -ex 'set substitute-path /build/linux-WiQfz7/linux-4.15.0 /path/to/your/source/linux-4.15' ``` ## 后话 以上为完整的搭建流程,其实还可以先下载要调试内核版本的 `.config` 配置文件之后用源码自行编译, ```shell $sudo apt-get install linux-headers-4.15.0-112-generic ``` 安装完成后的config配置文件在如下路径:`/usr/src/linux-headers-4.15.0-112-generic/.config`。之后再按照上文方法下载内核源码后,用该config文件直接 menuconfig 、开启debug的相关选项后编译即可。 ## 参考链接 [1] https://wiki.ubuntu.com/Kernel/SourceCode [2] https://hadibrais.wordpress.com/2017/03/13/installing-ubuntu-kernel-debugging-symbols/ [3] https://wiki.ubuntu.com/Kernel/BuildYourOwnKernel [4] https://www.hiroom2.com/2016/07/20/ubuntu-16-04-debug-ubuntu-16-04-kernel-with-qemu-gdb-stub/ [5] https://launchpad.net/ubuntu/+source/linux/4.15.0-112.113 [6] https://github.com/PaoloMonti42/salt/blob/cc658855c8589df280da098ef26d379e72e0df78/docs/0x01_getting_started.md