概述:
本文基于微软官方教程 编写 Hello World Windows 驱动程序 (KMDF) ,结合笔者在配置开发环境过程中踩的坑,详细讲解了如何使用 USB 连接主计算机和目标计算机,并配置相应的双机开发环境。最后,通过在 Hello World 程序入口添加断点来验证环境正确性。(ps:主计算机用于开发和调试,目标计算机用于运行编写的驱动程序)
核心步骤:
- 在主计算机上安装 visual studio 2022 + Windows 驱动程序工具包
- 编写 Hello World 驱动程序
- 生成 Hello World 驱动程序
- 本地测试 Hello World 驱动程序 (可选)
- 预配目标计算机
- 在目标计算机上部署解决方案
- 在目标计算机上安装驱动程序
- 使用 WinDBG + USB 的模式调试目标计算机
Step1:在主计算机上安装 visual studio 2022 + Windows 驱动程序工具包
- visual studio官方网址如下:https://visualstudio.microsoft.com/zh-hans/
- 个人学习使用的话,下载社区版本即可
- 安装时 工作负载 选择 使用 C++ 的桌面开发
- 安装时 单个组件 添加:
- MSVC v143 - VS 2022 C++ ARM64/ARM64EC Spectre 缓解库(最新版本)
- MSVC v143 - VS 2022 C++ x64/x86 Spectre 缓解库(最新版本)
- 带有 Spectre 缓解库的适用于最新 v143 生成工具的 C++ ATL (ARM64/ARM64EC)
- 适用于具有 Spectre 缓解功能的最新 v143 生成工具的 C++ ATL (x86 & x64)
- 带有 Spectre 缓解库的适用于最新 v143 生成工具的 C++ MFC (ARM64/ARM64EC)
- 适用于具有 Spectre 缓解措施的最新 v143 生成工具的 C++ MFC (x86 & x64)
- WDK下载链接,按照默认参数直接安装,一路 Next 即可
Step2:编写 Hello World 驱动程序
- 打开 Microsoft Visual Studio。 在“文件” 菜单上,选择“新建”>“项目” 。
- 在“新建项目”对话框的左侧下拉列表中,选择“C++”,在中间下拉列表中,选择“Windows”,然后在右侧下拉列表中,选择“驱动程序” 。
- 从项目类型列表中选择“内核模式驱动程序,空(KMDF)”。 选择“下一页”。
- 在“配置新项目”对话框中,在“项目名称”字段中输入“KmdfHelloWorld” 。
- 在“位置”字段中,输入要在其中创建新项目的目录。
- 选中“将解决方案和项目置于同一目录中”,然后选择“创建” 。
- 在“添加新项目”对话框中,选择“C++ 文件”。 对于“名称”,请输入“Driver.c”。
- 注意:名称以 .c 结尾!编写的是 c 文件!
- 将下列代码粘贴到 “Driver.c” 文件中。这是一份非常简单的 windows 驱动代码,在初始化和绑定设备时会打印相应的提示信息,详细的讲解请参考官方文档。
1 |
|
Step3:生成 Hello World 驱动程序
- 在“解决方案资源管理器”窗口中,选择并按住 (或右键单击) 解决方案“KmdfHelloWorld” (1 个项目) ,然后选择“Configuration Manager”。 为驱动程序项目选择配置和平台。 在本练习中,我们选择“调试”和“x64”。
- 在“解决方案资源管理器”窗口中,选择并按住 (或右键单击“) KmdfHelloWorld”,然后选择“属性”。 在“Wpp 跟踪”>“所有选项”中,将“运行 Wpp 跟踪”设置为“否”。 依次选择“应用”、“确定” 。
- 从“生成”菜单中选择“生成解决方案”。 Visual Studio 在“输出”窗口中显示生成进度。
- 若要查看生成的驱动程序,请在 文件资源管理器 中转到 KmdfHelloWorld 文件夹,然后转到 x64\Debug\KmdfHelloWorld。 该文件夹包括:
- KmdfHelloWorld.sys - 内核模式驱动程序文件
- KmdfHelloWorld.inf - 在安装驱动程序时 Windows 使用的信息文件
- KmdfHelloWorld.cat - 安装程序验证驱动程序的测试签名所使用的目录文件
Step4:本地测试 Hello World 驱动程序 (可选)
Windows 系统要求安装的驱动程序必须有微软的数字签名,但很显然我们在开发过程中写的驱动不会有签名。因此,为了在本地测试,我们需要先关闭 Windows 系统的强制签名检查
- 在开始菜单,按住shift,鼠标左键单击重新启动。该操作会打开 Windows 高级启动菜单
- 依次选择:疑难解答->高级选项->启动设置->按数字键7,选择禁用驱动程序强制签名
以管理员身份运行cmd,执行如下命令,创建一个服务(driverpath需要替换成上面工程生成的.sys文件路径)
sc create MyFirstDriver binPath= "driverpath" type= kernel
以管理员身份运行
DebugView.exe
,在菜单栏中勾选Capture Kernel
和Enable Verbose Kernel Output
- Debugview 是一个应用程序,支持你监视本地系统上或可通过TCP/IP 访问的网络上任何计算机上的调试输出。
- DebugView下载链接
在控制台输入如下命令,启动我们之前创建好的服务,可以在DebugView中看到DriverEntry函数输出的内容
sc start MyFirstDriver
测试完毕,使用如下命令关闭服务(卸载驱动)
sc stop MyFirstDriver
Step5:预配目标计算机
因为后续我们需要在主计算机端将生成的驱动文件(包)通过网络发送到目标计算机,并进行远程部署。所以我们需要预先对主计算机和目标计算机进行配置,下载一些工具包,并保证两者间网络连接畅通(能够互相ping通)。具体配置流程分主计算机侧和目标计算机侧两部分,我们先学习目标计算机侧的配置:
目标计算机侧操作
- 下载安装 WDK。WDK下载链接,按照默认参数直接安装,一路 Next 即可。
- 在 BIOS 中关闭 安全启动(如何进入 bios 请结合主板品牌 google 之)
- 运行与目标计算机平台匹配的 WDK 测试目标设置 MSI。可以在 Remote 下的 Windows 驱动程序工具包 (WDK) 安装目录中找到该 MSI。
- 默认路径:
C:\Program Files (x86)\Windows Kits\10\Remote\x64\WDK Test Target Setup x64-x64_en-us.msi
- 默认路径:
- ping 通主计算机
- 开启防火墙命令:
NetSh Advfirewall set allprofiles state on
- 关闭防火墙命令:
NetSh Advfirewall set allprofiles state off
- 开启防火墙命令:
主计算机侧操作
- ping 通目标计算机
- 在主机计算机上的 Visual Studio 中,选择“扩展”菜单,依次指向“驱动程序”和“测试”,然后选择“配置设备” 。
- 在“配置设备”对话框中,选择“添加新设备” 。
- 设备名称根据个人喜好任取。对于网络主机名,输入目标计算机的名称或本地 IP 地址。 选择“预配设备并选择调试程序设置”。

点击 下一步,跳转至如下界面,此时需要注意以下几点:
- Port Number 和 Key 后续可能会用到(如果使用 WinDBG + 以太网 调试的话),建议保存下来。
- 如果主计算机有多个 IP 地址,要在 Host IP 下拉框中选择能 ping 通的!
点击 下一步,正式开始配置目标计算机,此过程大概持续2-3分钟。预配成功的话,结果如下图所示。
Step6:在目标计算机上部署解决方案
在“解决方案资源管理器”窗口中,选择并按住(或右键单击)KmdfHelloWorld 项目,然后选择“属性” 。
在“KmdfHelloWorld 属性页”窗口中,转到“配置属性”>“驱动程序安装”>“部署”,如下所示。
选中“部署前删除以前的驱动程序版本” 。
对于“目标设备名称” ,请选择先前配置的用于测试和调试的计算机名,本例中为
MyComputer
选择“硬件 ID 驱动程序更新” ,然后输入驱动程序的硬件 ID。
在“生成”菜单上,选择“部署解决方案”。 Visual Studio 会自动将安装和运行驱动程序所需的文件复制到目标计算机。 部署可能需要一两分钟。
切到目标计算机,访问
C:\drivertest\drivers
文件夹,验证驱动文件是否成功复制。
Step7:在目标计算机上安装驱动程序
在目标计算机上找到
DevCon
工具。笔者是在C:\DriverTest
文件夹找到的DevCon.exe
文件。如果找不到也可以在主计算机的 WDK 文件夹C:\Program Files (x86)\Windows Kits\10\Tools\x64\devcon.exe
中找到并复制到目标计算机在目标计算机上,导航到包含驱动程序文件的文件夹(本例中为:
C:\drivertest\drivers
),然后运行 DevCon 工具,以安装驱动程序。- 使用 DevCon 工具安装驱动程序的语法:
devcon install <INF file><hardware ID>
。 - 以管理员身份启动终端,输入命令:
..\devcon.exe install KMDFHelloWorld.inf root\kmdfhelloworld
- 使用 DevCon 工具安装驱动程序的语法:
可以在目标计算机上使用
driverquery
命令验证 HelloWorld 驱动是否安装成功。
Step8:使用 WinDBG + USB 的模式调试目标计算机
什么是 WinDBG ?
- WinDbg是Microsoft Windows上的多用途调试器,可从微软网站上免费下载安装使用。用于调试用户态下的应用程序、驱动程序,以及核心态下的操作系统自身。
- WinDBG 支持以下类型的双机连接模式:
- 以太网
- USB 2.0 / USB 3.0
- 串行(也称为零调制解调器)
- 如果使用 以太网 或 USB 进行双机调试,对 目标计算机 的 网卡型号 或 USB端口 有一定要求。笔者一开始按照微软官方教程搭建环境,一直卡在双机通信这一步,两台机器虽然能够相互 ping 通,但是 WinDBG 始终连接不上。后来才发现是因为 目标计算机 的网卡型号不满足要求,故转战 USB 连接。下面将分别给出针对 网卡型号 和 USB 端口 的检查方式,请读者结合实际情况选择合适的连接方案。
如何检查网卡型号?
WinDBG 仅对 目标计算机 的网卡型号有要求哦,因此后续步骤均在 目标计算机 执行。
以管理员身份启动终端,并切换到 Windows 驱动程序工具包(WDK)目录,默认路径为:
C:\Program Files (x86)\Windows Kits\10\Debuggers\x64
执行如下命令:
.\kdnet.exe
若 网卡型号符合要求 则输出情况如下:
若 网卡型号不符合要求 则输出情况如下:
如何检查USB端口?
在目标计算机上,启动 UsbView 工具。 UsbView 工具包含在适用于 Windows 的调试工具中。
在 UsbView 中,展开 xHCI 主机控制器的节点。 查找主机控制器上的端口支持调试的指示。如果
Is Port Debug Capable
字段为yes
则表明该端口支持 WinDBG。记下要用于调试的 xHCI 控制器的总线、设备和函数号。 UsbView 会显示这些数字。

- 找到支持调试的 xHCI 控制器后,下一步是查找与 xHCI 控制器上的端口关联的物理 USB 连接器。 请将任何 USB 3.0 设备插入目标计算机上的任何 USB 连接器(说白了就是试,把每个口都插一插,然后刷新 UsbView,看看连接信息是否更新,如果更新了就找到了)。 刷新 UsbView 以查看设备所在的位置。 如果 UsbView 显示设备连接到所选的 xHCI 主机控制器,则表明你找到了可用于 USB 3.0 调试的物理 USB 连接器。
如何使用 USB 建立双机连接?
在 ”如何检查USB端口“” 一节我们已经找到了目标计算机上可用的 USB 接口,因此我们要先建立物理链路上的连接,即用数据线连接两台机器。
在目标计算机上,以管理员身份打开命令提示符窗口,然后输入以下命令:
1
2bcdedit /debug on
bcdedit /dbgsettings usb targetname:<TargetName>- TargetName 是为目标计算机创建的名称。 请注意, TargetName 不一定是目标计算机的官方名称;只要满足以下限制,它就可以是创建的任何字符串:
- 字符串不得在 TargetName 中的任何位置包含“debug”,大小写或大写的任意组合。 例如,如果在 targetname 中的任何位置使用“DeBuG”或“DEBUG”,则调试无法正常工作。
- 字符串中唯一的字符是连字符 ( ) 、下划线 (_) 、数字 0 到 9,以及字母 A 到 Z (大写或小写) 。
- 字符串的最大长度为 24 个字符。
- TargetName 是为目标计算机创建的名称。 请注意, TargetName 不一定是目标计算机的官方名称;只要满足以下限制,它就可以是创建的任何字符串:
继续执行以下命令:
bcdedit /set "{dbgsettings}" busparams <b.d.f>
- 其中,b,d,f 是 USB 主控制器的总线、设备和功能编号。均采用 10 进制。
- 在 ”如何检查USB端口“ 一节我们记录过这个 PCIe 域地址哦,忘了的家人可以再去瞅一眼。
在“设备管理器”中,导航到 xHCI 主控制器的节点。 右键单击“节点”,然后选择“属性”。 如果有 “电源管理 ”选项卡,请打开该选项卡,然后清除 “允许计算机关闭此设备以节省电源 ”复选框。
重新启动目标计算机。
在 主计算机 上下载并安装最新版 WinDBG,最新版的 GUI 界面比老版好的不要太多。下载链接
以 管理员身份 运行 WinDBG,选择 file -> Attach to kernel -> USB -> 输入本节第2步起的 targetname -> 选择 Break on connection -> OK
随后会进入如下界面,显示 “Waiting to reconnect”
重新启动 目标计算机。由于我们之前勾选了 ”连接时中断“,因此在 目标计算机 再次启动加载 Windows 操作系统时会停住。主计算机 WinDBG 窗口显示如下内容。
至此,WinDBG 成功连接到目标计算机,并让其中断在初始化阶段,我们可以在任何想要的地方打断点!
使用
bu 驱动名!函数名
命令在 HelloWorld 驱动初始化函数处打断点,使用bl
命令验证打断点成功(在bd>后面输入命令)
debug: