<index> / <windows-internals> / dev-setup
[ en | fr ]
┌───────────────────────┐
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
└───────────────────────┘
Windows Driver Dev Environment Setup
~ lululufr
CONTENTS
  0  why we need a driver
  1  required software
  2  system configuration
  3  first project — kmdf hello world
  4  running the driver
  5  kernel debugging with windbg

──[ 0. Why We Need a Driver ]──

A device driver is what lets an OS talk to hardware. For what we want — kernel 
callbacks, minifilters, EDR internals — we need kernel-mode code, so a driver. Windows Driver Frameworks (WDF) sits on top of the raw WDM (Windows Driver
Model) and handles a chunk of boilerplate for you:
    KMDF (Kernel-Mode Driver Framework)
        Runs in Ring 0. Full kernel access. One bug = BSOD.
        What you need for callbacks, minifilters, DKOM, etc.

    UMDF (User-Mode Driver Framework)
        Runs in Ring 3. Much safer, very limited scope.
        Useless for EDR work.

This series uses KMDF throughout.
──[ 1. Required Software ]──

Target OS: Windows 11 Pro (what this course was built on).

Visual Studio 2022
    Microsoft's standard IDE. During setup, pick:
    "Desktop Development with C++"

    Then add these individual components:

        MSVC v143 — VS 2022 C++ x64/x86 Spectre-mitigated libs
        MSVC v143 — VS 2022 C++ ARM64/ARM64EC Spectre-mitigated libs
        C++ ATL for latest v143 build tools with Spectre (x86 & x64)
        C++ ATL for latest v143 build tools with Spectre (ARM64/ARM64EC)
        C++ MFC for latest v143 build tools with Spectre (x86 & x64)
        C++ MFC for latest v143 build tools with Spectre (ARM64/ARM64EC)
        Windows Driver Kit
Visual Studio — individual components selection
Visual Studio — installation in progress
Windows SDK
    Goes with the WDK. ~3.5 GB. Install it before the WDK.
Windows SDK — installer
Windows Driver Kit (WDK)
    ~2 GB. Kernel headers, libs, driver build system. Needs Visual Studio
    and the SDK installed first.
WDK — installer
──[ 2. System Configuration ]──

Two system settings have to change before you can do anything.

Test Signing Mode
    Windows refuses unsigned drivers by default (DSE). Test signing lets
    you load self-signed or unsigned drivers:
        bcdedit /set testsigning on
Note: Secure Boot has to be off first — test signing and Secure Boot
    don't cohabit (see the ELAM article for why).

Kernel Debug Output
    Drivers write debug output via KdPrintEx(). To see it, enable kernel
    debugging:
        bcdedit /debug on
bcdedit — debug mode enabled output
Then create the debug filter in the registry:
        Registry key: HKLMSYSTEMCurrentControlSetControl
                      Session ManagerDebug Print Filter
        New DWORD:    DEFAULT = 8
Registry — Debug Print Filter DWORD set to 8
──[ 3. First Project — KMDF Hello World ]──

Create a new KMDF driver project in Visual Studio, add a .c source file.
Visual Studio — new KMDF driver project dialog
Visual Studio — project creation wizard (step 2)
Visual Studio — add new .c source file
Visual Studio — .c file added to project
If ntddk.h isn't found, add the include path manually:
    C:Program Files (x86)Windows Kits10Include<build>km
VS — additional include directories config
VS — include path added
    #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;
        WDF_DRIVER_CONFIG config;

        KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,
            "HelloWorld: 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,
            "HelloWorld: DeviceAdd\n"));

        status = WdfDeviceCreate(&DeviceInit,
            WDF_NO_OBJECT_ATTRIBUTES, &hDevice);

        return status;
    }
VS — preprocessor definitions (KMDF config)
──[ 4. Running the Driver ]──

Build: Build → Build Solution in Visual Studio.
VS — Build Solution menu
Load via Service Control Manager (admin terminal):
    sc.exe create MyDriver type=kernel binPath="C:\path\to\driver.sys"
    sc.exe start MyDriver
sc.exe — driver loaded and started
Unload:
    sc.exe stop MyDriver
    sc.exe delete MyDriver
──[ 5. Kernel Debugging with WinDbg ]──

Real debugging needs two machines: a host (WinDbg) and a target (your driver). 
The kernel debugger gives you breakpoints, memory inspection, live kernel
introspection.
WinDbg — Microsoft kernel debugger interface
Setup on the target machine
    Same bcdedit commands as step 2, plus the network target:
        bcdedit /dbgsettings net hostip:<HOST_IP> port:50000
Install the WDK test target MSI on the target:
        "C:\Program Files (x86)\Windows Kits\10\Remote\x64\
         WDK Test Target Setup x64-x64_en-us.msi"
Crank up debug verbosity:
        reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\
                 Debug Print Filter" /v IHVDRIVER /t REG_DWORD /d 0xFFFFFFFF /f
Target VM — debug mode configured
Setup on the host
    Install WinDbg from the Microsoft Store.
    Configure the remote debugging target in Visual Studio.
VS — remote debugger target configuration (step 1)
VS — remote debugger target configuration (step 2)
VS — remote debugger target configuration (step 3)
Hook WinDbg up to the target over the network.
WinDbg — launched and waiting for target
WinDbg — connected to target kernel
Useful WinDbg commands
    bu MyDriver!DriverEntry     Breakpoint on DriverEntry
    g                           Continue until next breakpoint
    t                           Step Into (enters called functions)
    p                           Step Over (skips called functions)
    lm                          List loaded modules
    !process 0 0                List all processes
    db <addr>                   Dump bytes at address
WinDbg — waiting for process launch (run and hit breakpoint)
WinDbg — stopped at DriverEntry breakpoint
WinDbg — debugging indicator active
sequenceDiagram
    participant V as Visual Studio (Host)
    participant W as WinDbg (Host)
    participant T as Windows Target

    V->>T: Deploy .sys file
    W->>T: Attach via network
    T->>W: Break at DriverEntry
    Note over W: Set breakpoints, inspect memory
    W->>T: g (continue)
    T->>W: KdPrintEx output visible
Once the debugger is attached you can pause the target kernel, inspect registers 
and memory, and step through your driver code instruction by instruction.
WinDbg — KdPrintEx output visible after stepping