作者:[email protected]知道创宇404实验室
日期:2023年4月18日
0x00 前言
*.dll
;UMDF 和 KMDF 开发基本相同,本文这里仅介绍使用更广泛的 KMDF 开发。windows 10 专业版 x64 1909
Visual Studio 2019
SDK 10.0.19041.685
WDK 10.0.19041.685
0x01 搭建驱动开发环境
Visual Studio 2019
的 C/C 开发环境(https://visualstudio.microsoft.com/),按 Visual Studio 官方教程,自动下载安装「使用C的桌面开发」,其中 SDK 默认为 10.0.19041.0
:Visual Studio
安装 WDK 扩展插件,按照指导进行安装即可,随后我们可以在 Visual Studio
的创建项目页面,就看到 KMDF/UMDF 等选项,表示 windows 驱动开发环境配置成功。0x02 HelloWorld开发
Visual Studio
中创建空的 KMDF
项目,并在其中创建 Driver.c
文件,编写代码如下:#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 variable to record success or failure
NTSTATUS status = STATUS_SUCCESS;
// Allocate the driver configuration object
WDF_DRIVER_CONFIG config;
// Print "Hello World" for DriverEntry
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: DriverEntry\n"));
// Initialize the driver configuration object to register the
// entry point for the EvtDeviceAdd callback, KmdfHelloWorldEvtDeviceAdd
WDF_DRIVER_CONFIG_INIT(&config,
KmdfHelloWorldEvtDeviceAdd
);
// Finally, create the driver object
status = WdfDriverCreate(DriverObject,
RegistryPath,
WDF_NO_OBJECT_ATTRIBUTES,
&config,
WDF_NO_HANDLE
);
return status;
}
NTSTATUS
KmdfHelloWorldEvtDeviceAdd(
_In_ WDFDRIVER Driver,
_Inout_ PWDFDEVICE_INIT DeviceInit
)
{
// We're not using the driver object,
// so we need to mark it as unreferenced
UNREFERENCED_PARAMETER(Driver);
NTSTATUS status;
// Allocate the device object
WDFDEVICE hDevice;
// Print "Hello World"
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: KmdfHelloWorldEvtDeviceAdd\n"));
// Create the device object
status = WdfDeviceCreate(&DeviceInit,
WDF_NO_OBJECT_ATTRIBUTES,
&hDevice
);
return status;
}
在「配置管理器」中设置为 Debug/x64
,编译生成项目发现如下错误:
Visual Studio
默认开启了缓解 Spectre 攻击的机制,可在 VS 安装器中选择安装指定的支持库,我们实验环境下可以直接关闭该功能,在 项目属性-C/C++-代码生成-Spectre Mitigation
设置为 Disable
:
随后便可以成功编译,在 [src]/x64/Debug/
下,可以看到生成的二进制文件 KmdfHelloWorld.sys
。
0x03 部署和测试
debugee
),驱动程序将在被调试机上(debugee
)进行部署和测试,而本台主机即作为开发主机同时作为调试机(debugger
),如下:debugee
)上也安装上 WDK 环境,随后在 WDK 的安装目录下运行该工具 WDK Test Target Setup
,默认路径:C:\Program Files (x86)\Windows Kits\10\Remote\x64\WDK Test Target Setup x64-x64_en-us.msi
;在之后调试机(debugger
)中的 Visual Studio
将连接被调试机(debugee
)的 WDK Test Target Setup
的工具,自动完成双机调试环境的配置。debugger
)初始化被调试机的相关信息,在 项目属性-Driver Install-Deployment
中添加新设备,我们这里使用网络双机调试的方式,默认参数即可:Visual Studio
中将被调试机(debugee
)添加完毕后,在如下窗口选择该主机并设置驱动的硬件 ID 为 Root\KmdfHelloWorld
,如下:Visual Studio
菜单中 生成-部署解决方案
,驱动程序将自动部署在被调试机上(debugee
)并进行测试运行:debugee
)上我们在设备管理器中可以看到 KmdfHelloWorld
已经成功部署了:0x04 本机调试驱动程序
#include <ntddk.h>
#include <wdf.h>VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "test: unload driver\n"));
}NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
UNREFERENCED_PARAMETER(DriverObject);
UNREFERENCED_PARAMETER(RegistryPath);KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "test: driver entry\n"));
DriverObject->DriverUnload = OnUnload;
return STATUS_SUCCESS;
}
Debug/x64
,编译生成项目。# 打开测试模式
bcdedit /set testsigning on
sc.exe
命令为驱动程序创建服务(命令详解请参考:https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/sc-create):# 创建服务名为 test,类型为 kernel,启动方式为 demand 的服务,并指定驱动程序路径
# (注意参数等号后必须有一个空格)
sc.exe create test type= kernel start= demand binPath= C:\Users\john\Desktop\workspace\kmdf_test\x64\Debug\kmdf_test\kmdf_test.sys# 使用 queryex 查看创建的服务信息
sc.exe queryex test
sc.exe
命令启动驱动程序运行,并使用 DebugView
查看调试输出(需要勾选 Capture Kernel
和 Enable Verbose Kernel Output
才能看到输出):# 启动运行驱动程序
sc.exe start test
# 停止运行驱动程序
sc.exe stop test
start/stop
这个服务,便可以快捷的进行驱动程序代码的测试和调试。0x05 References
作者名片