Linux内核调试
字数 1091 2025-08-25 22:59:03

Linux内核调试技术详解

0x00 前言

Linux内核调试是二进制安全研究的重要组成部分。由于不同Linux系统版本和内核版本中驱动模块和函数加载地址的差异,直接使用他人提供的exp往往无法成功利用漏洞。掌握内核调试技术对于内核漏洞分析和提权研究至关重要。

0x01 内核编译配置

调试内核首先需要准备特定版本的内核源码,可以从官方仓库获取所有历史版本。编译前需要进行正确的配置:

$ make menuconfig

关键配置项:

  1. Kernel Hacking 部分:

    • Compile the kernel with debug info(必须选中)
    • Compile the kernel with frame pointers(必须选中)
    • KGDB: kernel debugging with remote gdb(选中并启用所有子选项)
  2. Processor type and features 部分:

    • 取消 Paravirtualized guest support
  3. Kernel Hacking 部分:

    • 取消 Write protect kernel read-only data structures(否则无法使用软件断点)

配置完成后执行:

$ make
$ make modules_install
$ make install

0x02 使用KVM和GDB调试内核

环境准备

  1. 检查CPU是否支持虚拟化:
$ grep vmx /proc/cpuinfo
  1. 安装必要组件:
$ sudo apt-get install kvm qemu libvirt-bin virtinst virt-manager virt-viewer
  1. 添加用户到相关组:
$ sudo adduser 用户名 kvm
$ sudo adduser 用户名 libvirtd
$ groups
  1. 启动服务:
$ sudo service libvirt-bin start

配置虚拟机

  1. 启动virt-manager:
$ gksudo virt-manager
  1. 添加GDB调试支持配置:
<qemu:commandline>
  <qemu:arg value='-S'/>
  <qemu:arg value='-gdb'/>
  <qemu:arg value='tcp::1234'/>
</qemu:commandline>

调试步骤

  1. 主机端启动GDB:
$ gdb vmlinux
(gdb) target remote 127.0.0.1:1234
(gdb) b drv_open  # 设置断点
(gdb) c  # 继续执行
  1. 虚拟机中加载驱动模块:
$ insmod drv.ko

0x03 使用QEMU和GDB调试内核

更简单的方法是直接使用QEMU启动内核:

qemu-system-x86_64 -s -S -kernel arch/i386/boot/bzImage \
-hda /boot/initrd.img -append "root=/dev/hda" -gdb tcp::1234

参数说明:

  • -s:相当于-gdb tcp::1234的简写
  • -S:启动时暂停CPU执行
  • -kernel:指定内核镜像
  • -hda:指定硬盘镜像
  • -append:内核启动参数

无图形界面模式添加:

-nographic

GDB连接方式与KVM相同。

0x04 使用KDB和KGDB调试内核驱动模块

环境准备

  1. 准备两台VMware虚拟机(一台作为调试机,一台作为目标机)

  2. 配置串行端口:

    • 删除并行端口
    • 添加串行端口
    • 一台设为客户端,一台设为服务端
  3. 测试串口连接:

    • 客户机:
    $ cat /dev/ttyS0
    
    • 目标机:
    $ echo test > /dev/ttyS0
    

配置串口调试

修改/etc/default/grub

GRUB_CMDLINE_LINUX_DEFAULT="... kgdboc=ttyS1,115200 text"

更新配置并重启:

$ update-grub

调试步骤

  1. 目标机:

    • 加载驱动模块:
    $ insmod drv.ko
    
    • 查看驱动基址:
    $ dmesg
    

    $ cat /proc/modules | grep drv
    
    • 进入调试状态:
    # echo g > /proc/sysrq-trigger
    
  2. 客户机:

    • 启动GDB并连接:
    $ gdb vmlinux
    (gdb) target remote /dev/ttyS1
    
    • 加载符号文件并设置断点:
    (gdb) add-symbol-file drv.ko 0xffffffffa0000000
    (gdb) b device_ioctl
    (gdb) b device_open
    (gdb) c
    
  3. 目标机运行测试程序触发断点:

#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "drv.h"

#define DEVICE_PATH "/dev/vulndrv"

int main(int argc, char **argv) {
    int fd;
    struct drv_req req;
    req.offset = atoll(argv[1]);
    fd = open(DEVICE_PATH, O_RDONLY);
    if (fd == -1) {
        perror("open");
    }
    ioctl(fd, 0, &req);
    return 0;
}

0x05 参考链接

  1. QEMU直接启动Linux内核文档
  2. IBM开发者文档:使用KGDB调试Linux内核
Linux内核调试技术详解 0x00 前言 Linux内核调试是二进制安全研究的重要组成部分。由于不同Linux系统版本和内核版本中驱动模块和函数加载地址的差异,直接使用他人提供的exp往往无法成功利用漏洞。掌握内核调试技术对于内核漏洞分析和提权研究至关重要。 0x01 内核编译配置 调试内核首先需要准备特定版本的内核源码,可以从官方仓库获取所有历史版本。编译前需要进行正确的配置: 关键配置项: Kernel Hacking 部分: Compile the kernel with debug info (必须选中) Compile the kernel with frame pointers (必须选中) KGDB: kernel debugging with remote gdb (选中并启用所有子选项) Processor type and features 部分: 取消 Paravirtualized guest support Kernel Hacking 部分: 取消 Write protect kernel read-only data structures (否则无法使用软件断点) 配置完成后执行: 0x02 使用KVM和GDB调试内核 环境准备 检查CPU是否支持虚拟化: 安装必要组件: 添加用户到相关组: 启动服务: 配置虚拟机 启动virt-manager: 添加GDB调试支持配置: 调试步骤 主机端启动GDB: 虚拟机中加载驱动模块: 0x03 使用QEMU和GDB调试内核 更简单的方法是直接使用QEMU启动内核: 参数说明: -s :相当于 -gdb tcp::1234 的简写 -S :启动时暂停CPU执行 -kernel :指定内核镜像 -hda :指定硬盘镜像 -append :内核启动参数 无图形界面模式添加: GDB连接方式与KVM相同。 0x04 使用KDB和KGDB调试内核驱动模块 环境准备 准备两台VMware虚拟机(一台作为调试机,一台作为目标机) 配置串行端口: 删除并行端口 添加串行端口 一台设为客户端,一台设为服务端 测试串口连接: 客户机: 目标机: 配置串口调试 修改 /etc/default/grub : 更新配置并重启: 调试步骤 目标机: 加载驱动模块: 查看驱动基址: 或 进入调试状态: 客户机: 启动GDB并连接: 加载符号文件并设置断点: 目标机运行测试程序触发断点: 0x05 参考链接 QEMU直接启动Linux内核文档 IBM开发者文档:使用KGDB调试Linux内核