作者:0x7F@知道創宇404實驗室
時間:2023年4月18日

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

1.安裝VisualStudio

開發軟件需要 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)

2.安裝WDK

安裝完畢后,其窗口會默認勾選為 Visual Studio 安裝 WDK 擴展插件,按照指導進行安裝即可,隨后我們可以在 Visual Studio 的創建項目頁面,就看到 KMDF/UMDF 等選項,表示 windows 驅動開發環境配置成功。

3.vs創建kmdf項目

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,編譯生成項目發現如下錯誤:

4.spectre緩解設置

Visual Studio 默認開啟了緩解 Spectre 攻擊的機制,可在 VS 安裝器中選擇安裝指定的支持庫,我們實驗環境下可以直接關閉該功能,在 項目屬性-C/C++-代碼生成-Spectre Mitigation 設置為 Disable

5.spectre緩解設置

隨后便可以成功編譯,在 [src]/x64/Debug/ 下,可以看到生成的二進制文件 KmdfHelloWorld.sys

0x03 部署和測試

驅動程序一般以服務(service)或設備(device)的方式運行工作,這點和普通應用程序不同,所以不能像應用程序那樣進行調試和測試。官方指導中提供一種基于雙機調試環境的驅動調試方法,這種方式較為繁瑣,我們這里進行簡要介紹;想了解更方便的本機調試驅動程序的小伙伴,可跳轉至「0x04 本機調試驅動程序」。

按照官方指導,我們將驅動程序作為設備進行運行調試,在此之前需要再提供一臺主機作為被調試機(debugee),驅動程序將在被調試機上(debugee)進行部署和測試,而本臺主機即作為開發主機同時作為調試機(debugger),如下:

6.網絡雙機調試環境

首先在被調試機(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 中添加新設備,我們這里使用網絡雙機調試的方式,默認參數即可:

7.初始化被調試機信息

隨后將自動完成配置,如下:

8.自動配置雙機調試環境

Visual Studio 中將被調試機(debugee)添加完畢后,在如下窗口選擇該主機并設置驅動的硬件 ID 為 Root\KmdfHelloWorld,如下:

9.配置目標設備信息

配置完成后,我們在 Visual Studio 菜單中 生成-部署解決方案,驅動程序將自動部署在被調試機上(debugee)并進行測試運行:

10.vs自動部署驅動程序

在被調試機(debugee)上我們在設備管理器中可以看到 KmdfHelloWorld 已經成功部署了:

11.部署和測試驅動程序

如果想調試驅動程序,則可以使用 WinDBG 依據以上的雙機調試環境對驅動程序進行調試。

12.windbg查看驅動模塊

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

創建服務如下:

13.sc.exe創建服務

隨后便可以使用 sc.exe 命令啟動驅動程序運行,并使用 DebugView 查看調試輸出(需要勾選 Capture KernelEnable Verbose Kernel Output 才能看到輸出):

# 啟動運行驅動程序
sc.exe start test
# 停止運行驅動程序
sc.exe stop test

運行如下:

14.sc.exe啟動和停止服務

當我們更新了驅動代碼、編譯項目后,可以再次 start/stop 這個服務,便可以快捷的進行驅動程序代碼的測試和調試。

0x05 References

https://learn.microsoft.com/zh-cn/windows-hardware/drivers/gettingstarted/
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/en-us/windows-server/administration/windows-commands/sc-create


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/2063/