准备
查看内核版本1
2$ uname -a
Linux guo 4.15.0-22-generic #24-Ubuntu SMP Wed May 16 12:15:17 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
查看内核是否支持调试(在Ubuntu 16.04默认开启)1
2
3
4
5
6
7
8
9
10$ cat /boot/config-4.8.0-36-generic | grep GDB
# CONFIG_CFG80211_INTERNAL_REGDB is not set
CONFIG_SERIAL_KGDB_NMI=y
CONFIG_GDB_SCRIPTS=y
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_KGDB=y
CONFIG_KGDB_SERIAL_CONSOLE=y
# CONFIG_KGDB_TESTS is not set
CONFIG_KGDB_LOW_LEVEL_TRAP=y
CONFIG_KGDB_KDB=y
如果不支持调试或者需要其他版本的内核
选择kernel版本1
2
3
4# 搜索含有dbgsym的内核版本
apt-cache search linux-image | grep dbgsym | grep 4.8
# 搜索特定source code的内核版本
apt-cache search linux-source
安装内核1
2
3
4
5
6# 搜索要下载的linux内核版本
apt-cache search linux-image | grep linux-image | grep generic
# 安装内核
sudo apt-get install linux-image-4.8.0-36-generic
# 查看安装的内核版本
sudo dpkg --list | grep linux-image
安装符号文件
1 | codename=$(lsb_release -c | awk '{print $2}') |
http://ddebs.ubuntu.com 是 Ubuntu 的符号服务器。执行下面的命令添加密钥:1
wget -O - http://ddebs.ubuntu.com/dbgsym-release-key.asc | sudo apt-key add -
执行sudo apt update
更新
下载符号文件包:1
sudo apt-get install linux-image-`uname -r`-dbgsym
完成后,符号文件将会放在下面的目录下:1
/usr/lib/debug/boot/vmlinux-4.8.0-36-generic
安装kernel对应的源代码
打开/etc/apt/sources.list
,启用deb-src
,sudo apt update
更新1
2
3
4
5
6vim /etc/apt/sources.list
# 去掉下面这句话的注释
deb-src http://us.archive.ubuntu.com/ubuntu/ xenial main restricted
...
sudo apt-get update
搜索所有版本的source code:apt-cache search linux-source
安装指定版本的source code:sudo apt-get install linux-source-4.8.0
下载好的源代码会放在/usr/src
目录下
解压源代码sudo tar -xvf linux-source-4.8.0.tar.bz2
配置VMware
移除打印机,添加串口,保证串口名称相同。
- 在target机上添加串口,确认该端为服务器端。
- 在host机上添加串口,确定该端为客户机端。
配置target机的启动项
需要让target在开机时候进入kgdb的调试状态,首先需要修改grub文件,增加grub引导时候的菜单项。1
sudo vim /etc/grub.d/40_custom
修改的内容从/boot/grub/grub.cfg里复制,复制一个菜单项(menuentry)过来,再把菜单名中增加调试信息,然后在内核命令行中增加KGDB选项,即下面这样:
新增部分:kgdbwait kgdb8250=io,03f8,ttyS0,115200,4 kgdboc=ttyS0,115200 kgdbcon nokaslr1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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-4.10.0-19-generic-advanced-32ee8e9c-31e6-494c-a9ea-1a416cbfeca7' {
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 32ee8e9c-31e6-494c-a9ea-1a416cbfeca7
else
search --no-floppy --fs-uuid --set=root 32ee8e9c-31e6-494c-a9ea-1a416cbfeca7
fi
echo 'Ubuntu,KGDB with nokaslr ...'
linux /boot/vmlinuz-4.10.0-19-generic root=UUID=32ee8e9c-31e6-494c-a9ea-1a416cbfeca7 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
}
修改/etc/default/grub
文件,使虚拟机开机是出现选择内核界面。1
2
3
4
5$ sudo vim /etc/default/grub
# 注释该这一行
GRUB_HIDDEN_TIMEOUT=0
# 开机选择界面等待时间 s
GRUB_TIMEOUT=10
配置host
设置串口通信的波特率1
sudo stty -F /dev/ttyS0 115200
要查看是否设置成功1
sudo stty -F /dev/ttyS0
每次host重启都需要重新设置。
调试
编写config,用source加载(直接在gdb里输入也可)
1 | set architecture i386:x86-64:intel |
使用gdb来调试带符号的vmlinux (此处gdb需要sudo权限,切gdb插件pwndbg不能使用)1
2gdb -s /usr/lib/debug/boot/vmlinux-4.10.0-19-generic
gdb > source config
查看源码遇到的问题
1 | in /build/linux-hwe-eyfT8D/linux-hwe-4.8.0/net/core/skbuff.c:758 |
list本来应该显示具体的源码,但是这里只是打印出了它所在的文件,这是因为在这个路径下没有源码。
所以说我们就建立这个路径,然后把源码放进去。
然后dir设置好目录1
dir /build/linux-hwe-eyfT8D/linux-hwe-4.8.0
现在就可以查看源码了。
单步调试
当target端成功启动,并且host端成功挂载gdb时。如果我们需要调试exp程序,只需要在target端输入:1
sudo su && echo g > "/proc/sysrq-trigger"
此时,target端处于假死状态,在host端可以使用gdb下断点调试内核。