Windows 驱动开发入门
2023-4-23 16:17:40 Author: www.freebuf.com(查看原文) 阅读量:13 收藏

0x00 前言

随着 windows 系统的更新迭代,windows 驱动开发技术也是不断的升级:从最早期的 VXD(Virtual X Driver)(已废弃)到 windows 2000 上推出的 WDM(Windows Driver Model)驱动模型,随后从 windows vista 推出的 WDF(Windows Driver Foudation)驱动模型,沿用至今;WDF 是 WDM 的升级版,并且在一定程度上兼容,WDF 是微软目前推荐的驱动开发模型。

WDF 还可以细分为内核模式 KMDF(Kernel-Mode Driver Framework) 和用户模式 UMDF(User-Mode Driver Framework),顾名思义 UMDF 将受到更多的限制从而换来更高的操作系统稳定性,其二进制扩展名为*.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

image

开发软件需要 SDK(Software Development Kit),而开发 windows 驱动则需要 WDK(Windows Driver Kit);现在我们来配置 WDK 环境,从官网(https://learn.microsoft.com/zh-cn/windows-hardware/drivers/download-the-wdk)下载 WDK 在线安装包(版本必须和 SDK 一致),按如下进行安装:

对于 WDF 驱动模型其开发环境叫 WDK(Windows Driver Kit)
对于 WDM 驱动模型其开发环境叫 DDK(Driver Development Kit)

image

安装完毕后,其窗口会默认勾选为Visual Studio安装 WDK 扩展插件,按照指导进行安装即可,随后我们可以在Visual Studio的创建项目页面,就看到 KMDF/UMDF 等选项,表示 windows 驱动开发环境配置成功。

image

windows 驱动开发环境可能会受操作系统、Visual Studio、SDK、WDK 的版本影响,配置过程需要多留心这些环节,如遇见问题可以参考如下版本信息 https://learn.microsoft.com/en-us/windows-hardware/drivers/other-wdk-downloads。

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,编译生成项目发现如下错误:

image

Visual Studio默认开启了缓解 Spectre 攻击的机制,可在 VS 安装器中选择安装指定的支持库,我们实验环境下可以直接关闭该功能,在项目属性-C/C++-代码生成-Spectre Mitigation设置为Disable

image

随后便可以成功编译,在[src]/x64/Debug/下,可以看到生成的二进制文件KmdfHelloWorld.sys

0x03 部署和测试

驱动程序一般以服务(service)或设备(device)的方式运行工作,这点和普通应用程序不同,所以不能像应用程序那样进行调试和测试。官方指导中提供一种基于双机调试环境的驱动调试方法,这种方式较为繁琐,我们这里进行简要介绍;想了解更方便的本机调试驱动程序的小伙伴,可跳转至「0x04 本机调试驱动程序」。

按照官方指导,我们将驱动程序作为设备进行运行调试,在此之前需要再提供一台主机作为被调试机(debugee),驱动程序将在被调试机上(debugee)进行部署和测试,而本台主机即作为开发主机同时作为调试机(debugger),如下:

image

首先在被调试机(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中添加新设备,我们这里使用网络双机调试的方式,默认参数即可:

image

随后将自动完成配置,如下:

image

Visual Studio中将被调试机(debugee)添加完毕后,在如下窗口选择该主机并设置驱动的硬件 ID 为Root\KmdfHelloWorld,如下:

image

配置完成后,我们在Visual Studio菜单中生成-部署解决方案,驱动程序将自动部署在被调试机上(debugee)并进行测试运行:

image

在被调试机(debugee)上我们在设备管理器中可以看到KmdfHelloWorld已经成功部署了:

image

如果想调试驱动程序,则可以使用 WinDBG 依据以上的双机调试环境对驱动程序进行调试。

image

0x04 本机调试驱动程序

官方提供的驱动程序部署和测试方法,虽然有效的隔离开发环境和调试环境,但实在是过于繁琐了,更不用说其中双机调试环境下的各种问题。而驱动程序还可以以服务的方式进行运行,我们通过这种方式可以更加方便的在本机调试驱动程序。

在日常安全工作中,我更喜欢使用这种方式,因为大多数情况我只需要工作在内核层的驱动代码,而不关心其是否是完整的 windows 驱动设备,这种方式能帮助我快速进行安全验证工作。

创建 KMDF 项目并编写代码如下:

#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,编译生成项目。

在运行测试前,我们需要在本机(即开发主机)上打开测试模式(重启生效),使得操作系统可以加载我们编译的驱动程序,使用管理员权限打开 powershell:

# 打开测试模式
bcdedit /set testsigning on

重启主机后,使用管理员权限打开 powershell,通过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

创建服务如下:

image

随后便可以使用sc.exe命令启动驱动程序运行,并使用DebugView查看调试输出(需要勾选Capture KernelEnable Verbose Kernel Output才能看到输出):

# 启动运行驱动程序
sc.exe start test
# 停止运行驱动程序
sc.exe stop test

运行如下:

image

当我们更新了驱动代码、编译项目后,可以再次start/stop这个服务,便可以快捷的进行驱动程序代码的测试和调试。

0x05 References

https://learn.microsoft.com/zh-cn/windows-hardware/drivers/gettingstarted/
https://github.com/microsoft/Windows-driver-samples</https://github.com/microsoft/Windows-driver-samples>
https://visualstudio.microsoft.com/
https://learn.microsoft.com/zh-cn/windows-hardware/drivers/download-the-wdk</https://learn.microsoft.com/zh-cn/windows-hardware/drivers/download-the-wdk>
https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/sc-create</https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/sc-create>


文章来源: https://www.freebuf.com/articles/database/364562.html
如有侵权请联系:admin#unsafe.sh