安装 Visual Studio 2022
下载 Visual Studio 2022,这里选用的社区版,选择使用 C++ 的桌面开发,然后在单个组件中选择以下两项:
- MSVC v143 – VS 2022 C++ x64/x86 Spectre 缓解库 (最新)
- Windows 驱动程序工具包 (WDK)

安装好后在 Visual Studio Installer 中显示,截止到目前 WDK 并未适配 Visual Studio 2026,请勿在 Visual Studio 2026 上进行驱动程序开发

上述的缓解库是必须的,否则编译不通过。Windows 驱动程序工具包 (WDK) 为驱动开发的 VSIX 扩展,扩展安装好后会在菜单上显示

安装 SDK
默认选择使用 C++ 的桌面开发带的 SDK 不是最新的,例如我这里的 SDK 版本为 Windows 11 SDK (10.0.26100.7175),截止到目前,官网已发布的最新 SDK 版本号为 Windows 11 SDK (10.0.26100.7463)

版本号说明,例如 10.0.26100.7175,26100 为构建号,7175 为 QFE 号,在后面安装 WDK 时需要记住这个构建号,因为 SDK 的构建号要与 WDK 的构建号对应,以免出现莫名其妙的错误。
安装 WDK
下载最新的 WDK 的安装程序,截止到目前,WDK 最新版本号为 10.0.26100.6584,与上一步中的 SDK 版本的构建号相同,说明两者是匹配的,至于 QFE 号不同,如果不需要用到最新 QFE 号更新的内容则可忽略

从 Visual Studio 17.11.0 版本开始,WDK VSIX 作为独立包组件包含在 Visual Studio 中。安装 WDK 前,安装程序会检查是否已安装兼容版本的 VSIX。如果找不到 WDK VSIX,安装程序会提示您安装,VSIX 已在安装 Visual Studio 2022 时已安装好了,所以检测通过,接下来选择安装目录一路 Next 即可。
这里还需要提一下,WDK 中包含了 windbg 调试器,这个后面在调试驱动程序时需要用到

当然也可以从微软商店下载安装 Windbg

编译第一个驱动程序
启动 Visual Studio 2022,创建一个空的 WDM 驱动工程 (这里以 WDM 框架为例),工程名 MyDriver1

在 Source Files 下创建 First.c 文件,内容如下
#include <ntddk.h>
VOID DriverUnload(PDRIVER_OBJECT DriverObject) {
if (DriverObject != NULL) {
DbgPrint("[%ws]Driver Upload, Driver Object Address: %p", __FUNCTIONW__, DriverObject);
}
return;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {
DbgPrint("[%ws]Hello Kernel World.\n", __FUNCTIONW__);
if (RegistryPath != NULL) {
DbgPrint("[%ws]Driver RegistryPath: %wZ\n", __FUNCTIONW__, RegistryPath);
}
if (DriverObject != NULL) {
DbgPrint("[%ws]Driver Object Address: %p\n", __FUNCTIONW__, DriverObject);
DriverObject->DriverUnload = DriverUnload;
}
return STATUS_SUCCESS;
}
右键项目,点击生成,在生成之前,删除默认的 inf 文件,这是配置驱动程序安装文件,在这里暂时不需要它

.sys 文件是我们需要的,它代表的是一个驱动程序文件,驱动程序文件不能像 exe 程序那样直接双击运行,它是以服务方式运行。另外还有一点区别是 64 位的操作系统能运行 64 位和 32 位 exe 程序,但是不能运行 32 位驱动程序,64 位只能运行 64 位,32 位只能运行 32 位。
运行驱动程序
如何运行 MyDriver1.sys,能够实时看到 DbgPrint 函数输出的内容。在运行之前,需要做以下操作:
- 操作系统需以测试模式启动,除非你有正式签名 (需要购买申请)
- 加载驱动程序方式 (sc 命令或第三方驱动程序加载工具)
- dbgview 工具
如果没有正式签名,操作系统会默认禁止加载,所以需要开启测试模式,使用 bcdedit 命令
bcdedit /set testsigning on
接着重启,重启后桌面右下角会有测试模式的水印,为了方便操作及安全,测试环境用虚拟机环境,这里我用的是 Windows10 22H2,将 MyDriver1.sys 拖放到目标测试机上,以管理员方式打开命令行,执行 sc 命令
sc create FirstDriver binPath= "C:\Users\zer0daysec\Desktop\MyDriver1.sys" type= kernel start= demand
sc create 表示创建一个服务,binPath 指定要测试 sys 驱动程序的位置,type 为驱动的类型,start 表示服务启动类型,demand 为手动启动,注意,上述命令 = 后面需要有一个空格。
接下来启动 dbgview 程序,以管理员方式启动,打开后设置以下两项

然后启动服务
sc start FirstDriver
启动后再停止删除
sc stop FirstDriver
sc delete FirstDriver
dbgview 程序输出

当然也可以使用第三方驱动程序加载工具进行加载运行,这样就省去了每次输 sc 命令,这里放个第三方驱动加载工具截图

第三方驱动加载工具方便点,这里说下 sc 和工具原理,因为驱动只能以服务方式运行,上述都是通过调用与服务相关的 API 实现:
- OpenSCManager
- CreateService
- OpenService
- StartService
- ControlService
- DeleteService
你也可以根据以上 API 自己编写一个驱动加载工具,具体使用说明请参阅微软 API 文档。
调试驱动程序
如何对驱动程序进行调试,在上面这一节中,使用 DbgPrint 方式是一种,但这种方式效率是非常低的,在开发驱动程序过程中需要进行动态调试,以下讲解如何动态调试驱动程序。
使用 Net 方式
测试目标虚拟机 (VMware):
- 操作系统:Windows10 22H2
- IP:192.168.254.133
物理机:
- 操作系统:Windows11 25H2
- IP:192.168.1.101
目标机防火墙需要关闭,两端需要互相 Ping 通,在目标机上以管理员方式执行如下命令
bcdedit /dbgsettings net hostip:192.168.254.133 port:50010
执行完后,会生成一个 key,将这个 key 复制到物理机上文本中,后面要用到这个 key,再到 Visual Studio 中设置

点击 Configure Devices,设置好以下值

Next

完成后,Configure Devices 显示刚添加的配置

一切准备就绪后,为了方便调试,需要先在 DriverEntry 中的开始部分添加以下这句
KdBreakPoint();
KdBreakPoint() 函数只会在 Debug 版下有效,Release 版需换成 DbgBreakPoint()。一旦调试启动,会自动在此处断下,重新编译生成 sys 文件并将其拖放到目标机桌面上,在 Visual Studio 中打开调试菜单,选择附加到进程

连接目标选择 MyDriver1,选中 Kernel 后启动

接着就会等待连接,重启目标机,重启后就会连上

连上后还需加载 sys 文件,我这里就不用 sc 命令了,直接用第三方驱动加载工具,加载后 Visual Studio 自动断在开始处,目标机处于 “卡死” 状态

后面就可以按正常方式进行动态调试了。不过 Visual Studio 调试有个问题,无法在源码文件下一行一行调试,提示帧不在堆栈上,如果你知道原因可以告知我。当调试完毕后,不要急着在 Visual Studio 中点击停止调试 (用的是第三方驱动加载工具),先点击运行,此时目标机 “卡死” 状态恢复。再到目标机上的驱动加载工具点击停止,再到 Visual Studio 中点击停止调试,否则目标机继续 “卡死” 一小会,最后在工具处进行卸载。
虽然在 Visual Studio 能直接调试,但还是喜欢用 Windbg 调试,WDK 自带 Windbg 程序,但我这里没用它,用的是微软商店下载的,界面更加现代化。
在 Windbg 中设置 Net 方式调试设置,在设置此方式前,先设置下源代码文件路径及调试符号路径

最后选择 Attach to kernel,再设置如下数值

启动后等待连接,连上后加载驱动,自动断在 KdBreakPoint 处

后面就可以按正常方式进行动态调试了。
通过串口方式
将目标虚拟机关机,添加一个串行端口并设置好参数

使用命名管道,管道名为
\\.\pipe\com_1
在 Windbg 端,设置好以下参数值

启动目标机后,以管理员方式执行以下命令

重启目标机,选择 Debug,也就是上面 /d 参数后面的值

稍等片刻,加载驱动后,Windbg 自动断在入口处

后面就可以按正常方式进行动态调试了。