之前介绍了如何编写一个简单的驱动程序,相比exe程序,可以直接拖进OD内调试,驱动文件必须依赖操作系统才能执行。所以需要依靠Windbg进行双机调试来实现(配置双机调试可以参考这里)。具体如何调试驱动,下面一起来看看吧
PDB文件
在学习驱动调试之前,先要了解PDB文件。PDB文件(Program DeBug database)有什么用呢?我们来看个例子:
在Windbg中,通过u(unassemble)指令可以看到指定地址的汇编;当我们给定一个特定的地址时,它往往可以识别出这个函数,亦或是给定一个函数名,它可以直接定位到特定的地址 这到底是如何做到的呢? 我们先看定义,PDB文件是一类用于存储程序调试信息的属性文件。它会伴随着源文件编译时创建出来。 结合上图和定义可以发现,无论是exe,dll还是sys文件,都有对应的pdb文件,且pdb文件体积很大,这是因为pdb包含了大量调试用的信息,这也是为什么Windbg能够快速识别各类0环函数信息,因为它加载了Windows符号表。Windows符号表是一组包含了内核函数调试信息的pdb文件。
加载符号表
加载符号表的步骤非常简单,之前进行过双击调试的小伙伴应该已经自行加载过了,这里再演示一遍:
- 进入Windbg界面,File -> SymbolFilePath
- 进入后,可以看到,这是我导入的Windows符号表,里面包含了内核函数的pdb文件 由于Windows官方不再提供符号表,这里我使用的是Xp sp3的符号表,可以作为参考(提取码:3akx ) 实际情况最好选择与操作系统版本相适应的符号表
- 导入符号表后,在Windbg中键入.reload指令完成符号信息加载
驱动调试示例
有了前面的基础,我们来尝试一下如何调试一个驱动程序吧
首先,写一个驱动程序,加入用于测试的代码
Code1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include "ntddk.h"
VOID DriverUnload(PDRIVER_OBJECT driver)
{
DbgPrint("驱动程序已停止.\r\n");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
//中断到调试器
_asm {
int 3
mov eax, eax
mov eax, eax
mov ecx, ecx
}
DbgPrint("驱动程序已运行.\r\n");
DriverObject->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}这里面嵌入了一段汇编,这样可以在程序执行时中断到调试器
然后,我们将该驱动程序的pdb文件路径拷贝到Windbg的SymbolFilePath中 这样Windbg就加载了我们驱动程序的符号文件了
有了符号文件,就可以用Windbg调试驱动了:
这样,一次简单的驱动调试就完成啦
参考教程:https://www.bilibili.com/video/BV1NJ411M7aE?p=58
参考文章: