首页
社区
课程
招聘
[原创]ubuntu 内核源码调试方法(双机调试)
发表于: 2019-1-29 11:22 30299

[原创]ubuntu 内核源码调试方法(双机调试)

2019-1-29 11:22
30299

20190129更新,ubuntu内核调试也可以使用qemu+gdb,并且这种方式似乎更快更简单。

原文:

由于想要学习root的原理,分析linux内核的本地提权漏洞(CVE-2017-8890),因此需要对linux kernel做源码调试。这篇文章主要参考张银奎前辈的三篇文章,主要记录如何下载调试需要的image、vmlinux和source code,以及借助vmware在两个ubuntu之间做linux kernel源码调试的方法。

选择ubuntu的一个好处是kernel已经开启了KGDB调试选项,可以通过cat /boot/config-uname -r| grep -i "GDB"查看当前内核是否支持KGDB。搭建过程持续了一周(2018/3/13 - 2018/3/17),环境搭建过程还是比较累的。
环境:

CVE-2017-8890在 Linux 4.11-rc8 版本中已经被启明星辰ADLab发现。启明星辰ADLab已第一时间将“Phoenix Talon”漏洞反馈给了Linux 内核社区,漏洞上报后Linux社区在Linux 4.12-rc1中合并了修复该问题的补丁。
http://www.cnnetsec.com/2619.html

虽然漏洞公告中给出了受影响的kernel version list,但是实际测试时,POC在kernel 4.4.X也有受影响。本来考虑选择在 Linux 4.11-rc8 kernel分析和调试。问题在于:Linux 4.11-rc8 可以下载到kernel 的image 和 header二进制文件,却下载不到对应准确版本的符号文件vmlinux。因此,首先搜索ubuntu哪些版本的linux kernel的vmlinux和 source code可以已下载到:

kernel image是内核会运行的文件,dbgsym一般是gdb用来调试的vmlinux,source code就是源码。

也可以从网站上下载deb包后安装:

重启并验证新的内核已经被使用 uname -sr

增加符号文件对应的source.list ,更新源文件。

通过apt-get下载dbgsym,默认保存在/usr/lib/debug/boot中,文件名是vmlinux-4.10.0-19-generic。

(可选)另一种搜索当前内核的 dbgsym的方法:

一、apt安装
打开/etc/apt/sources.list,启用deb-src,执行sudo apt-get update更新源文件:

第一种方法搜索kernel source code时只存在几个大版本,如4.10.0,下载之后发现可能是4.10.0的一个细分版本:4.10.0-xx(Makefile中的前几行定义了源码的版本)。所以猜测实际上运行的kernel和source code还是有一些出入的,gdb调试的时候对应关系可能不太一致。

二、 下载linux kernel源码切换分支
查看git仓库地址:https://wiki.ubuntu.com/Kernel/Dev/KernelGitGuide
git clone git://kernel.ubuntu.com/ubuntu/ubuntu-xenial.git
git tag | grep 4.10.0-19
git checkout ubuntu-4.10.0-19........

这时的源码和内核二进制文件就是一一对应的了。

一切都安装好了之后,就可以把ubuntu复制一份了,一份作为debugging(调试机),一份作为debuggee(被调试机、目标机)。

在vmware中实现ubuntu双机调试的原理,是建立两台ubuntu之间的串口通信,在虚拟机设置中增加serial port。假设两台ubuntu一台是debugging、一台是debuggee。配置debugging 的串口为server,debuggee的串口为client。两者通过串口借助物理机(linux)的/tmp/serial 通信,如果是windows需要设置为//./pipe/com_1。
Alt text
注意这里有几个坑点:

安装好了kernel之后,ubuntu默认会选择进入一个最新的kernel,也可以在开机时按住SHIFT选择想进入的kernel版本。

配置debuggee
需要让debuggee在开机时进入KGDB的被调试状态,首先需要修改grub文件,增加grub引导时的菜单项(menuentry)。

修改的内容可以从/boot/grub/grub.cfg中复制。在菜单名中增加调试信息,并在内核命令行中增加KGDB选项。

更新grub后,重启按住SHIFT 进入grub选择刚才的menu即可等到进入被调试模式。

一开始并没有加入nokaslr选项时。会存在不能下断点,bt栈回溯无法获取地址对于的文件信息。本来以为是linux内核的编译选项导致,这里也有人遇到了同样的情况(https://linux.cn/forum.php?mod=viewthread&tid=16243)。

配置debugging

关于源码的查看:
在gdb中使用l可以查看相应的源码,但是由于vmlinux编译时似乎是使用绝对路径编译的,因此可以建立相应的绝对路径把source code放进去。还有一种方法是,设置set substitute-path PATH1 PATH2,PATH1是vmlinux中的路径信息,PATH2是source code存放的真实路径。

c运行内核后,debuggee就跑起来了。这时,基本的gdb命令都可以使用,但是如果用n单步运行时,可能过了很久都没有反应。举个栗子:

经过一番探索之后,找到了解决方案:

注:debuggee如果不能进入kgdb中断,可用cat /sys/module/kgdboc/parameters/kgdboc检查的kgdboc参数是否设置正确。

sysrq还有很多强大的功能,具体可以参考这里:https://www.cnblogs.com/justin-y-lin/p/5424555.html

调试后期,由于借助kgdb来调试时,一旦执行到用户态的shellcode时,gdb中就会输出大量的垃圾信息,这时可以借助kdump来看oops信息,使用过程如下:

Alt text

至此调试环境搭建完成。(由于现在换到windows下调试了,补一张windows的vmware截图:
Alt text

内核跑起来后,在debuggee中运行CVE-2017-8890的poc,发现程序崩溃了。oops信息可以在gdb中看到,如果在gdb中看不到,可以尝试用CTRL+SHIFT+F1/F7 切换到命令行模式,可以看到很完整的oops信息。
Alt text

查看崩溃点<ip_mc_leave_src+37>: mov ecx,DWORD PTR [rbx+0x4],此时rbx为0x2,因此从0x6中取值失败,存在对空指针引用。

 
 
 
 
 
 
 
 
 
 
 
 
linux-source - Linux kernel source with Ubuntu patches
linux-source-4.4.0 - Linux kernel source for version 4.4.0 with Ubuntu patches
linux-source-4.10.0 - Linux kernel source for version 4.10.0 with Ubuntu patches
linux-source-4.11.0 - Linux kernel source for version 4.11.0 with Ubuntu patches
linux-source-4.13.0 - Linux kernel source for version 4.13.0 with Ubuntu patches
linux-source-4.8.0 - Linux kernel source for version 4.8.0 with Ubuntu patches
# 增加source.list
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
# 添加访问符号服务器的秘钥文件
wget -O - http://ddebs.ubuntu.com/dbgsym-release-key.asc | sudo apt-key add -
# 更新源文件
sudo apt-get update
sudo apt-get install linux-image-`uname -r`-dbgsym
sudo apt-get install aptitude
sudo aptitude search 'linux-image-'$(uname -r)'-dbgsym'
deb-src http://cn.archive.ubuntu.com/ubuntu/ xenial main restricted
sudo vim /etv/grub.d/40_custom
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
menuentry 'Ubuntu, KGDB with nokaslr' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-bf306d0a-28c8-49c6-bffc-446be272ddcf' {
    recordfail
    load_video
    gfxmode $linux_gfx_mode
    insmod gzio
    if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
    insmod part_msdos
    insmod ext2
    set root='hd0,msdos1'
    if [ x$feature_platform_search_hint = xy ]; then
      search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1  bf306d0a-28c8-49c6-bffc-446be272ddcf
    else
      search --no-floppy --fs-uuid --set=root bf306d0a-28c8-49c6-bffc-446be272ddcf
    fi
    echo 'Loading Linux 4.10.0-19 with KGDB built by GEDU lab...'
    linux /boot/vmlinuz-4.10.0-19-generic root=UUID=bf306d0a-28c8-49c6-bffc-446be272ddcf ro find_preseed=/preseed.cfg auto noprompt priority=critical locale=en_US quiet kgdbwait kgdb8250=io,03f8,ttyS0,115200,4 kgdboc=ttyS0,115200 kgdbcon nokaslr
    echo 'Loading initial ramdisk ...'
    initrd    /boot/initrd.img-4.10.0-19-generic
}
sudo update-grub 
reboot
stty -F /dev/ttyS0 115200
set architecture i386:x86-64:intel
target remote /dev/ttyS0
gdb -s /usr/lib/debug/boot/vmlinux-4.10.0-19-generic
gdb> source config
#查看
cat /proc/sys/kernel/sysrq 
#配置
echo X >/proc/sys/kernel/sysrq 
#或修改/etc/sysctl.conf中设置kernel.sysrq=1
echo m > /proc/sysrq-trigger 导出内存分配信息
echo t > /proc/sysrq-trigger 导出当前任务状态信息
echo p > /proc/sysrq-trigger 导出当前CPU寄存器和标志位信息
echo c > /proc/sysrq-trigger 产生空指针panic事件,人为导致系统崩溃
echo s > /proc/sysrq-trigger 即时同步所有挂载的文件系统
echo u > /proc/sysrq-trigger 即时重新挂载所有的文件系统为只读
echo w > /proc/sysrq-trigger转储处于uninterruptable阻塞状态的任务
#安装kdump
sudo apt-get install  linux-crashdump
service kdump-tools start
#检查kdump是否可用
查看/boot/grub/grub.cfg是否含有crashkernel
如果是自定义启动项,手工修改/etc/grub.d/40-custom中增加crashkernel
#检查另一个kernel是否启动
/sys/kernel/kexec_crash_loaded 1表示已经加载 0表示没有加载
#测试
echo c > "/etc/sysrq-trigger"
....等待重启后在/var/crash下生成了日志
解压 crash  /usr/lib/debug/boot/vmlinux-4.10.0-19-generic  /tmp/kernel-crash
查看/tmp/kernel-crash/VmCoreDmesg信息即可。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2019-1-29 12:26 被心许雪编辑 ,原因:
收藏
免费 7
支持
分享
最新回复 (12)
雪    币: 3344
活跃值: (10982)
能力值: ( LV9,RANK:240 )
在线值:
发帖
回帖
粉丝
2
谢谢楼主分享,我学习的Linux内核,版本是2.4.0,非常的老,前段时间找了一个redhat7.3的镜像,安装过程虽然看起来有点问题,但还是在上面把Linux-2.4.0的vmlinux编译出来了,2.38MB,感觉好小,有时间我要试下可不可以调试。
2019-1-29 14:38
0
雪    币: 4366
活跃值: (353)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
3
xinpoo 谢谢楼主分享,我学习的Linux内核,版本是2.4.0,非常的老,前段时间找了一个redhat7.3的镜像,安装过程虽然看起来有点问题,但还是在上面把Linux-2.4.0的vmlinux编译出来了, ...
赞~加油。
2019-1-29 23:57
0
雪    币: 234
活跃值: (23)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
加油
2019-1-30 15:44
0
雪    币: 540
活跃值: (41)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
感谢分享!
2019-3-21 14:21
0
雪    币: 10
活跃值: (163)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6

最后于 2019-4-9 21:29 被呐呐编辑 ,原因:
2019-4-9 15:29
0
雪    币: 11314
活跃值: (2907)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
学习学习,感觉不学习工作都跟不上了
2019-9-23 17:26
0
雪    币: 200
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
为啥我调试的时候需要等很长时间gdb才能动 我用的是ubuntu16调试的

需要等好长时间5分钟起步怎么回事
2019-9-24 18:54
0
雪    币: 295
活跃值: (64)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
为师傅打call!!!
2019-9-29 22:23
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
mb_ayxljcbf 为啥我调试的时候需要等很长时间gdb才能动 我用的是ubuntu16调试的需要等好长时间5分钟起步怎么回事
和你一样 太慢了  感觉十分钟 起步了  似乎还是qemu划算一点
2020-2-18 18:01
0
雪    币: 4366
活跃值: (353)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
11
mb_ayxljcbf 为啥我调试的时候需要等很长时间gdb才能动 我用的是ubuntu16调试的需要等好长时间5分钟起步怎么回事
可以尝试给虚拟机多分配几个CPU看看?
2020-3-28 23:23
0
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
感谢分享!
2022-5-4 22:15
0
雪    币: 4460
活跃值: (6706)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
好文章谢谢了
2022-5-4 23:09
0
游客
登录 | 注册 方可回帖
返回
//