内核准备
打开调试
make menuconfig
开启如下选项:
Kernel hacking -> Compile-time checks and compiler options -> Compile the kernel with debug info
Kernel hacking -> Generic Kernel Debugging Instruments -> KGDB: kernel debugger
qemu-system-x86_64 关闭 Kernel ALSR 以便于调试内核:
-append "nokaslr"
调试内核时,为了加载 vmlinux 符号表,必须额外指定 -append “nokaslr"以关闭 kernel ASLR。这样符号表才能正确的对应至内存中的指定位置,否则将无法给目标函数下断点,
还可以通过内核选项关闭aslr:
Processor type and features ---> [ ] Randomize the address of the kernel image (KASLR)
内核中的对齐宏:__ALIGN_KERNEL
1
2
| #define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1)
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))
|
其本质就是对齐的地位补0,以8字节对齐为例:
int size = 8; <----> 1000(bin)
计算a以size为倍数的下界数:
就让这个数(要计算的这个数)表示成二进制时,最后三位为0就可以达到这个目标。只要下面这个数与a进行"与运算"就可以了:
11111111 11111111 11111111 11111000
而上面这个数实际下就是 ~(size - 1),可以将该数称为size的对齐掩码size_mask.
#define alignment_up(a, size) ((a+size-1) & (~ (size-1)))
注: 上界数的计算方法,如果要求出比a大的是不是需要加上8就可以了?可是如果a本身就是8的倍数,这样加8不就错了吗,所以在a基础上加上(size - 1), 然后与size的对齐掩码进行与运算.
所以0x123 八字节对齐为:
1
2
3
4
5
6
7
8
9
| 0001 0010 0011(bin)
+
0111
=
0001 0010 1010
&
1000
=
0001 0010 1000(0x128)
|
debug 启动参数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| export IMAGE=~/mywork/linux-5.4.230/rootfs/ubuntu-rootfs-build
export KERNEL=~/mywork/linux-5.11.14
qemu-system-x86_64 -cpu host \
-m 2G -smp 2 \
-kernel $KERNEL/arch/x86/boot/bzImage \
-append "console=ttyS0 root=/dev/sda rw earlyprintk=serial net.ifnames=0 nokaslr" \
-drive file=$IMAGE/rootfs.img,format=raw \
-net user,host=10.0.2.10,hostfwd=tcp:127.0.0.1:10021-:22 \
-net nic,model=e1000 \
-virtfs local,path=~/mywork,mount_tag=tag001,security_model=mapped-xattr \
-enable-kvm \
-nographic \
-gdb tcp::12345 \
-S \
-pidfile vm.pid 2>&1 | tee vm.log
|
-S :表示启动后就挂起,等待 gdb 连接;
-gdb tcp::12345 也可以改成-s 表示:-gdb tcp::1234
此时启动gdb:
1
2
3
4
| gdb
gef➤ file vmlinux
gef➤ target remote localhost:12345
gef➤ gef-remote localhost 12345
|
一个简单的启动脚本:
1
2
3
4
5
6
| gdb \
-ex "add-auto-load-safe-path ~/mywork/linux-5.11.14/" \
-ex "file ~/mywork/linux-5.11.14/vmlinux" \
-ex "target remote localhost:1234" \
-ex "b cmdline_proc_show" \
-ex "c"
|
效果图: