[原创]Linux内核漏洞调试环境搭建的经验分享
发表于:
2019-6-30 19:44
17930
【演示视频】
Q:为什么内核编译速度快了(只需20分钟左右)?
A:我觉得因为只编译了 bzImage和vmlinux文件,没编译其他内核模块,所以速度变快了。这里有个tips ,就是可以输入make help命令,查看make后面到底可以接哪些子命令。
Q:如何对目标机的物理内存进行读写操作?
A:在目标机命令行窗口中,按下Ctrl+A组合键后,再单独按下C键一次,即可完成从qemu前端和后端的切换。进入后端后输入help命令可看到qemu的内置命令。比如xp命令可以读目标机的物理内存空间。但是qemu貌似没提供目标机物理内存写的能力。但是这里有一个Trick:)就是利用qemu的gpa2hva命令。这个命令可以将目标机的物理地址转化为qemu进程的虚拟地址。所以需要对目标机的某个物理地址进行写时,可以将该目标机的物理地址先用gpa2hva命令转化为qemu进程的虚拟地址,然后再启用一个gdb attach住qemu进程,再对该虚拟地址进行写操作即可。
Q:在VMware中再启动一个QEMU虚拟机,在QEMU中的运行速度不会慢么?
A:理论上不会影响很多(感官上也没什么影响,反而因为只启动内核而不像发行版Linux那样需要加载很多软件,速度其实快了很多),根本原因是因为Nested虚拟化技术,所以速度很快。
网上其实已经有很多大牛们发过关于Linux内核调试环境搭建的文章,但是我在使用的时候或多或少都遇到过一些这样或那样的问题。
这方面之前确实也踩了很多坑,不过最终的实现效果,我觉得对我自己而言还算是比较完美的一个调试环境。
这篇文章也谈不上是教程或者什么的,只是自己站在前辈们的肩膀上,自己做了一些微调,然后现在把它share出来;
OK现在我们开始:)
2、最终效果展示
【演示视频】
3、常规Linux内核调试环境在使用时遇到的问题(也可以跳过,这部分在碎碎念之前遇到的坑 T T)
既然要写这个话题,主要是因为之前自己搭建Linux调试环境的时候总会有一些用起来不是很舒适的情况,比如:
情况1:如果使用两个VMware进程分别作为调试端和被调试端,并使用named pipe方式通讯,这样就要启动两个VMware进程。这样其实比较浪费CPU和内存资源 。而且用named pipe方式调试速度很慢不说,而且也不会像在用户态使用GDB那样直接Ctrl+C就可以断下,而是必须要用“ echo g >/proc/sysrq-trigger” 这种方式主动断下,很不方便;
情况2:如果按照情况1中的方法搭建环境,一般来说是在一个VMware中编译并安装好内核,然后复制一份这个虚拟机,分别作为调试端和被调试端。但是这样带来的结果就是一个完整的调试环境至少要占用60GB左右 (甚至更高),无论是存储还是拷贝给其他人都不是很方便
情况3:如果按照情况1中的方法搭建环境,据我本人尝试在Ubuntu中如果安装最新版Linux内核,不知为什么,安装好后的Ubuntu至少需要把RAM设置为4GB以上才能启动成功,也就是说RAM的消耗量变得很多 (如果机器只有8GB内存,那么这种情况就很麻烦)
情况4:还是情况1,用这种方式搭建的环境每次如果需要对内核代码进行更改,再make clean后重新编译至少需要几个小时 (在我2015年初版的Macbook上编译至少需要5个小时左右,而且这期间啥也不能干,稍微出错就前功尽弃)。
情况5:用VMware双机调试的时候,对需要物理内存调试的漏洞(比如脏牛)调试起来很不方便 (或者就是实现不了)。比如使用KGDB调试的时候就没法对物理内存调试,想调试很麻烦。
情况6:Virtualbox搭建双机调试环境时,我明明开启了对内核内存空间的读写编译选项,可还是无法下断点,迷の抓狂BUG 。 T T
情况7:如果是下载Ubuntu官方提供的Symbol的方式来调试Ubuntu,对被调试内核仍然不能做到随意修改然后调试 ,所以调试起来依然有很大局限性。
4、本文描述的Linux调试环境具有的特点
1、省硬盘空间省CPU省内存 :全调试环境占用空间不到30GB(比上述情况2缩减一半),只需要VMware启动一个虚拟机实例即可。节省CPU和内存资源。
2、调试会话交互速度快 :调试时可随时用Ctrl+C方式断下,而且速度很快,比named pipe方式调试明显感官上感觉速度快很多(因为使用了IP+端口方式调试而非串口调试)
4、内核编译速度快 :如果需要重新编译内核,每次仅需20分钟。这是在我2015款Macbook上编译所消耗的时间,不惧编译失败:)
7、这个环境可以:一键使用Syzkaller进行Kernel Fuzzing;一键启动内核;一键调试内核;一键打开内核编译选项;一键编译内核;
5、搭建该环境所需的前提准备(正文开始)
1、VMware安装至可用(不推荐Virtualbox,用过一段时间,总感觉有很多隐形BUG)
2、VMware上安装一个Ubuntu(建议最新版)
3、在VMware中配置该Ubuntu虚拟机的CPU选项,打开所有与虚拟化相关的选项。CPU核心数设置的大一些,比如我设置了4(注意这里其实只在需要编译的情况下才需要设置4,一般情况下如果只是调试漏洞设置1就可以)。内存我设置了2GB。
4、建议在VMware中设置Ubuntu虚拟机的兼容性升级到最新版。
6、具体操作步骤
其实聪明的小伙伴看到本文第2部分的时候,就可能会猜到我这个环境是基于Syzkaller那个环境基础上修改的
参考Google的这篇Syzkaller搭建帮助文档( https://github.com/google/syzkaller/blob/master/docs/linux/setup_ubuntu-host_qemu-vm_x86-64-kernel.md )。需要注意的几个地方:
1、注意上述的Syzkaller搭建文档中的Kernel小节,本小节中所有的make命令(make defconfig、make kvmconfig、make oldconfig等命令 )一概不需要执行,只需要执行一条命令即可:“ make bzImage -j8 && make vmlinux -j8 ”(划重点!!每次修改内核代码后直接这么编译就行了,不放心的话就在执行这条make命令之前make clean一下,依然只需要20分钟或更短时间 )。这条命令不会编译模块,只会编译bzImage和vmlinux两个文件,所以速度会大幅提高 。注意最后的-j8是因为我为Ubuntu配置了4核。这里的数字不要太大,最好就是核心数*2。否则make过程可能会导致Ubuntu直接秒重启,看不到任何报错(之前遇到过的坑)
2、如果需要Syzkaller,则需将上述文档中所有步骤全部操作完,否则最后一步Syzkaller部分不用做
3、原文档中的那个sshd启动脚本(在文档中搜索sshd关键字可找到),在其中加两行,分别为 -s和 -cpu host。-s是让qemu开启gdbserver,并在1234端口监听,-cpu host是让qemu内跑的Linux内核以为当前CPU和真机CPU一个型号(在某些漏洞调试环境下有用,建议保持开启)。我的修改后的qemu启动脚本如下:
qemu-system-x86_64 \
-kernel $KERNEL/arch/x86/boot/bzImage \
-append "console=ttyS0 root=/dev/sda nokaslr slub_debug=P kmemleak=off"\
-hda $IMAGE/stretch.img \
-net user,hostfwd=tcp::2222-:22 -net nic \
-enable-kvm \
-cpu host \
-nographic \
-serial mon:stdio \
-m 1G \
-s \
-smp 1 \
-pidfile Kernel.Boot.pid \
2>&1 | tee Kernel.Boot.log
4、一键调试脚本:
cd Linux-Kernel && gdb vmlinux --eval-command="target remote tcp::1234"
7、一些FAQ(其实是自己想的)
Q:为什么内核编译速度快了(只需20分钟左右)?
A:我觉得因为只编译了 bzImage和vmlinux文件,没编译其他内核模块,所以速度变快了。这里有个tips ,就是可以输入make help命令,查看make后面到底可以接哪些子命令。
Q:如何对目标机的物理内存进行读写操作?
A:在目标机命令行窗口中,按下Ctrl+A组合键后,再单独按下C键一次,即可完成从qemu前端和后端的切换。进入后端后输入help命令可看到qemu的内置命令。比如xp命令可以读目标机的物理内存空间。但是qemu貌似没提供目标机物理内存写的能力。但是这里有一个Trick:)就是利用qemu的gpa2hva命令。这个命令可以将目标机的物理地址转化为qemu进程的虚拟地址。所以需要对目标机的某个物理地址进行写时,可以将该目标机的物理地址先用gpa2hva命令转化为qemu进程的虚拟地址,然后再启用一个gdb attach住qemu进程,再对该虚拟地址进行写操作即可。
Q:在VMware中再启动一个QEMU虚拟机,在QEMU中的运行速度不会慢么?
A:理论上不会影响很多(感官上也没什么影响,反而因为只启动内核而不像发行版Linux那样需要加载很多软件,速度其实快了很多),根本原因是因为Nested虚拟化技术,所以速度很快。
网上其实已经有很多大牛们发过关于Linux内核调试环境搭建的文章,但是我在使用的时候或多或少都遇到过一些这样或那样的问题。
这方面之前确实也踩了很多坑,不过最终的实现效果,我觉得对我自己而言还算是比较完美的一个调试环境。
这篇文章也谈不上是教程或者什么的,只是自己站在前辈们的肩膀上,自己做了一些微调,然后现在把它share出来;
OK现在我们开始:)
既然要写这个话题,主要是因为之前自己搭建Linux调试环境的时候总会有一些用起来不是很舒适的情况,比如:
情况1:如果使用两个VMware进程分别作为调试端和被调试端,并使用named pipe方式通讯,这样就要启动两个VMware进程。这样其实比较浪费CPU和内存资源 。而且用named pipe方式调试速度很慢不说,而且也不会像在用户态使用GDB那样直接Ctrl+C就可以断下,而是必须要用“ echo g >/proc/sysrq-trigger” 这种方式主动断下,很不方便;
情况2:如果按照情况1中的方法搭建环境,一般来说是在一个VMware中编译并安装好内核,然后复制一份这个虚拟机,分别作为调试端和被调试端。但是这样带来的结果就是一个完整的调试环境至少要占用60GB左右 (甚至更高),无论是存储还是拷贝给其他人都不是很方便
情况3:如果按照情况1中的方法搭建环境,据我本人尝试在Ubuntu中如果安装最新版Linux内核,不知为什么,安装好后的Ubuntu至少需要把RAM设置为4GB以上才能启动成功,也就是说RAM的消耗量变得很多 (如果机器只有8GB内存,那么这种情况就很麻烦)
情况4:还是情况1,用这种方式搭建的环境每次如果需要对内核代码进行更改,再make clean后重新编译至少需要几个小时 (在我2015年初版的Macbook上编译至少需要5个小时左右,而且这期间啥也不能干,稍微出错就前功尽弃)。
情况5:用VMware双机调试的时候,对需要物理内存调试的漏洞(比如脏牛)调试起来很不方便 (或者就是实现不了)。比如使用KGDB调试的时候就没法对物理内存调试,想调试很麻烦。
情况6:Virtualbox搭建双机调试环境时,我明明开启了对内核内存空间的读写编译选项,可还是无法下断点,迷の抓狂BUG 。 T T
情况7:如果是下载Ubuntu官方提供的Symbol的方式来调试Ubuntu,对被调试内核仍然不能做到随意修改然后调试 ,所以调试起来依然有很大局限性。
4、本文描述的Linux调试环境具有的特点
1、省硬盘空间省CPU省内存 :全调试环境占用空间不到30GB(比上述情况2缩减一半),只需要VMware启动一个虚拟机实例即可。节省CPU和内存资源。
1、省硬盘空间省CPU省内存 :全调试环境占用空间不到30GB(比上述情况2缩减一半),只需要VMware启动一个虚拟机实例即可。节省CPU和内存资源。 2、调试会话交互速度快 :调试时可随时用Ctrl+C方式断下,而且速度很快,比named pipe方式调试明显感官上感觉速度快很多(因为使用了IP+端口方式调试而非串口调试)
2、调试会话交互速度快 :调试时可随时用Ctrl+C方式断下,而且速度很快,比named pipe方式调试明显感官上感觉速度快很多(因为使用了IP+端口方式调试而非串口调试)
4、内核编译速度快 :如果需要重新编译内核,每次仅需20分钟。这是在我2015款Macbook上编译所消耗的时间,不惧编译失败:)
4、内核编译速度快 :如果需要重新编译内核,每次仅需20分钟。这是在我2015款Macbook上编译所消耗的时间,不惧编译失败:)
6、不会有上面情况6那种抓狂BUG
7、这个环境可以:一键使用Syzkaller进行Kernel Fuzzing;一键启动内核;一键调试内核;一键打开内核编译选项;一键编译内核;
7、这个环境可以:一键使用Syzkaller进行Kernel Fuzzing;一键启动内核;一键调试内核;一键打开内核编译选项;一键编译内核;
5、搭建该环境所需的前提准备(正文开始)
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2019-7-1 10:42
被OxLucifer编辑
,原因: