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.
← 返回首页