WAFILOG

Windows内核驱动食用教程

这篇笔记整理自微软官方 WDK 文档和我自己踩过的坑,覆盖 VS2022 该装哪些组件、WDK 装完却找不到 ntddk.h 到底为什么、最小 KMDF 驱动怎么写、编译部署和双机调试。我在 Windows 11 + VS2022 上都跑通了一遍,照着做应该没问题。

微软当前推荐用于生产的组合是 Visual Studio 2022 + WDK 26100.6584。WDK 从 10.0.26100.1 起以 NuGet 包和 VSIX 扩展形式分发,VS2022 安装时必须在"单个组件"中手动勾选 WDK 与对应的 Spectre-mitigated 库,否则项目模板和头文件都不会就位。

一、VS2022 工作负载与单个组件

打开 Visual Studio Installer,对已经装好的 VS2022 点「修改」,然后照着下面这个清单勾:

  1. 工作负载:勾选「使用 C++ 的桌面开发」。
  2. 单个组件(搜索框输入「64 latest」可快速定位):
    • MSVC v143 - VS 2022 C++ x64/x86 Spectre-mitigated libs (Latest)
    • MSVC v143 - VS 2022 C++ ARM64/ARM64EC Spectre-mitigated libs (Latest)
    • C++ ATL for latest v143 build tools with Spectre Mitigations (x86 & x64)
    • Windows Driver Kit
  3. Windows 10 SDK:选择与 WDK 版本匹配的 SDK(WDK 26100 对应 10.0.26100.x)。

安装完成后,C:\Program Files (x86)\Windows Kits\10\Include\ 下应出现对应版本的目录,且其中含有 km 子目录——ntddk.h 就位于 km\ntddk.h。

二、ntddk.h 找不到的根因与修复

有时明明在 VS Installer 里勾了 WDK,编译还是报 C1083: Cannot open include file: 'ntddk.h'。这通常不是 WDK 没装,而是WDK 的 Visual Studio 集成(VSIX 扩展)压根没真正生效,或者项目指向的那个 Windows SDK 版本下面压根没有 km 文件夹。

可能的根因

  • WDK VSIX 未安装:VS Installer 勾选 WDK 后,底层需要把 WDK.vsix 注册进 VS2022。集成未完全时,项目模板和头文件路径都不会注入。
  • 项目 Windows SDK 版本错误:项目属性的「Windows SDK Version」指向了一个没有 Include\km 的 SDK 版本。
  • 平台工具集不匹配:驱动项目必须使用 WindowsKernelModeDriver 工具集,选成普通 v143 会导致包含路径解析失败。

解决方案:从微软官网下载 WDK 独立安装包

最稳的办法,也是微软官方推荐的做法,是直接绕开 VS Installer 的勾选,用 WDK 独立安装包来注册:

  1. 访问微软官方 Download WDK 页面,下载 WDK 26100.6584 安装包(wdksetup.exe)。
  2. 运行安装包,过程中务必勾选「Debugging Tools for Windows」。
  3. 安装完成后,手动注册 WDK VSIX 扩展(关键步骤):
    C:\Program Files (x86)\Windows Kits\10\Vsix\VS2022\10.0.26100.0\amd64\WDK.vsix
    双击该文件或通过管理员 CMD 执行:
    VSIXInstaller.exe /q /a "C:\Program Files (x86)\Windows Kits\10\Vsix\VS2022\WDK.vsix"
  4. 重启 Visual Studio。新建项目时应能看到「Kernel Mode Driver, Empty (KMDF)」模板。

项目级兜底配置

如果模板已出现但仍报找不到 ntddk.h,按以下顺序检查项目属性:

  1. 常规 → Windows SDK 版本:选择 C:\Program Files (x86)\Windows Kits\10\Include\ 下真实存在 km 子目录的版本。
  2. C/C++ → 附加包含目录:手动加入
    C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\km
    C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\km\wdf
    C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\shared
    将 10.0.26100.0 替换为你本机实际版本号。
  3. 配置管理器 → 活动解决方案平台:必须为 x64,不要手动定义 AMD64(会导致 "No Target Architecture" 错误)。

排错思路其实就一句:先看 Include\km 文件夹在不在,再看项目 Windows SDK 版本有没有指到它,最后才轮到手动加包含路径。我见过的「ntddk.h 找不到」,几乎都出在前头那几步。

三、创建第一个 KMDF 驱动

WDK 安装就绪后,新建项目 → 搜索「Driver」→ 选择「Kernel Mode Driver, Empty (KMDF)」。项目名称不超过 32 字符(WDF 框架限制)。

右键项目 → 添加 → 新建项 → 命名为 Driver.c(必须是 .c,不能是 .cpp)。填入最小可运行代码:

#include <ntddk.h>
#include <wdf.h>

DRIVER_INITIALIZE DriverEntry;
EVT_WDF_DRIVER_DEVICE_ADD KmdfHelloWorldEvtDeviceAdd;

NTSTATUS
DriverEntry(
    _In_ PDRIVER_OBJECT  DriverObject,
    _In_ PUNICODE_STRING RegistryPath
)
{
    NTSTATUS status = STATUS_SUCCESS;
    WDF_DRIVER_CONFIG config;

    KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
              "KmdfHelloWorld: DriverEntry\n"));

    WDF_DRIVER_CONFIG_INIT(&config, KmdfHelloWorldEvtDeviceAdd);
    status = WdfDriverCreate(DriverObject, RegistryPath,
                             WDF_NO_OBJECT_ATTRIBUTES,
                             &config, WDF_NO_HANDLE);
    return status;
}

NTSTATUS
KmdfHelloWorldEvtDeviceAdd(
    _In_    WDFDRIVER        Driver,
    _Inout_ PWDFDEVICE_INIT  DeviceInit
)
{
    UNREFERENCED_PARAMETER(Driver);
    NTSTATUS status;
    WDFDEVICE hDevice;

    KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
               "KmdfHelloWorld: EvtDeviceAdd\n"));

    status = WdfDeviceCreate(&DeviceInit,
                             WDF_NO_OBJECT_ATTRIBUTES, &hDevice);
    return status;
}

选择 Debug / x64 配置,生成解决方案。编译成功后,在 x64\Debug\ 下会得到 .sys、.inf 等驱动包文件。

四、常见编译错误速查

错误 原因 修复
C1083: ntddk.h WDK 集成未生效 / SDK 版本无 km 重装 WDK + 手动注册 WDK.vsix
LNK2001: 无法解析 ntoskrnl 链接器缺内核库 链接器 → 忽略特定默认库:ntdll.lib
C2220 /WX 警告被视为错误 C/C++ → 将警告视为错误:否 (/WX-)
MSB8036 SDK 版本不匹配 项目属性 → Windows SDK 版本改选已安装版本
No Target Architecture 手动定义了 AMD64 宏 删除手动宏,仅通过配置管理器选 x64

五、测试签名与部署

Windows 默认禁止加载未签名驱动。开发阶段使用测试签名模式:

  1. 目标机开启测试签名(管理员 CMD):
    bcdedit /set testsigning on
    重启后桌面右下角会出现「调试模式」水印。
  2. 生成测试证书(使用 WDK 自带的 makecert):
    makecert -r -pe -ss PrivateCertStore -n "CN=TestCert" testcert.cer
  3. 用 SignTool 签名 .sys:
    signtool sign /v /s PrivateCertStore /n TestCert /fd SHA256 driver.sys
  4. 在目标机安装证书:双击 testcert.cer → 安装到「受信任的根证书颁发机构」。

六、双机调试环境

我一般拿虚拟机当目标机来调,省得本机直接蓝屏。常用的就两种:

  • 网络调试(推荐):宿主机与目标虚拟机通过网络直连,使用 WinDbg 的 net 协议。
  • 串口调试:虚拟机配置 COM 端口,波特率 115200。

目标机开启调试:

bcdedit /debug on
bcdedit /dbgsettings net hostip:192.168.1.10 port:50000

宿主机启动 WinDbg Preview,连接到目标机。常用命令:

bm KmdfHelloWorld!DriverEntry   # 在 DriverEntry 设断点
lm                              # 列出已加载模块
x KmdfHelloWorld!*              # 查看模块内符号
k                               # 查看调用栈

驱动加载后,KdPrintEx 的输出可通过 DebugView(勾选「Capture Kernel」)或 WinDbg 的调试窗口查看。

内核驱动这东西,一个没处理好的 IRQL 违规或者自旋锁用错,就可能直接 0x000000D1 蓝屏。我的习惯是每次只动一个点,用 WinDbg 单步跟进去看——一次性堆太多功能,真出事都不知道该怪哪段。

参考文献

  1. Microsoft. "Download the Windows Driver Kit (WDK)." 2025.
  2. Microsoft. "Write a Hello World Windows driver (Kernel-Mode Driver Framework)." 2025.
  3. Microsoft. "Debug Universal Drivers - Step by Step Lab (Echo Kernel Mode)." 2025.
  4. Microsoft. "Test-Signing a Driver Package." Windows Hardware Dev Center.
  5. microsoft/Windows-driver-samples. GitHub Repository.
← 返回首页