首页
社区
课程
招聘
[原创]Linux内核漏洞调试环境搭建的经验分享
发表于: 2019-6-30 19:44 17881

[原创]Linux内核漏洞调试环境搭建的经验分享

2019-6-30 19:44
17881

【演示视频】

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上编译所消耗的时间,不惧编译失败:)
5、目标机安装啥版本内核都可以,即便是想使用512MB内存启动内核都可以:)不再有上面情况4所说的问题。
6、不会有上面情况6那种抓狂BUG
7、这个环境可以:一键使用Syzkaller进行Kernel Fuzzing;一键启动内核;一键调试内核;一键打开内核编译选项;一键编译内核;
8、被调试机器启动速度快,在15秒左右(仍然是在我老掉牙的2015款Macbook上测试的时间)

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上编译所消耗的时间,不惧编译失败:)
5、目标机安装啥版本内核都可以,即便是想使用512MB内存启动内核都可以:)不再有上面情况4所说的问题。
5、目标机安装啥版本内核都可以,即便是想使用512MB内存启动内核都可以:)不再有上面情况4所说的问题。
6、不会有上面情况6那种抓狂BUG
6、不会有上面情况6那种抓狂BUG
7、这个环境可以:一键使用Syzkaller进行Kernel Fuzzing;一键启动内核;一键调试内核;一键打开内核编译选项;一键编译内核;
7、这个环境可以:一键使用Syzkaller进行Kernel Fuzzing;一键启动内核;一键调试内核;一键打开内核编译选项;一键编译内核;
8、被调试机器启动速度快,在15秒左右(仍然是在我老掉牙的2015款Macbook上测试的时间)
8、被调试机器启动速度快,在15秒左右(仍然是在我老掉牙的2015款Macbook上测试的时间)

5、搭建该环境所需的前提准备(正文开始)


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2019-7-1 10:42 被OxLucifer编辑 ,原因:
收藏
免费 10
支持
分享
最新回复 (3)
雪    币: 144
活跃值: (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
Syzkaller 教程里面提供的文件系统脚本太牛了,感谢
(可能需要先make一下defconfig生成.config文件,“这里有个tips链接是127.0.0.1”)
关于FAQ0如果defconfig里面默认也是不编译不使用的驱动文件的,如果两次编译之间没有make mrproper/clean/distclean 那么编译速度加快的原因很可能是未修改文件已经编译好了*.o,再进行编译实际上只进行了修改部分文件的编译和链接。
2019-7-11 16:34
0
雪    币: 0
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
您好,请问在运行syzcaller的create-image.sh时出现了一些package下载失败的情况,导致create-image直接退出,请问要怎么解决这个问题呢?
2020-3-7 12:27
0
雪    币: 220
活跃值: (79)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
相见恨晚,我花了好多个5小时,才知道make clean不能随便用。感谢
2022-7-20 14:27
1
游客
登录 | 注册 方可回帖
返回
//