Loading...

文章背景图

阶段六:驱动开发

### 摘要 本文是**Windows驱动开发**学习阶段的详细指南,分为四大模块: 1. **WDK环境搭建**:介绍Visual Studio、WDK、SDK的安装步骤,配置测试签名模式和内核调试环境(WinDbg+虚拟机)。 2. **驱动基础**: - 驱动入口/卸载函数实现 - 设备对象与符号链接创建 - IRP请求处理机制 - 驱动与应用层通信(通过DeviceIoControl) 3. **内核编程**: - 内存操作(分页/非分页内存分配、跨进程读写) - 进程/线程操作(枚举、上下文切换) - 内核回调(监控进程/线程创建、模块加载) 4. **VT虚拟化技术**: - VT-x基础概念(VMX Root/Non-Root模式) - VMCS结构及VM-Exit处理 - 检测CPU对VT的支持 **检查点**包括环境配置、驱动通信实现、内核内存操作及VT基础理解。**推荐资源**涵盖经典书籍(如《寒江独钓》)、开源项目(HyperPlatform)及Intel官方文档。 本阶段需10-12周,要求掌握内核编程核心技能,为高级系统开发打下基础。 (字数:200)

a0yark a0yark
|
2025-12-03
|
1
|
-
|
- min
|

阶段六:驱动开发

📅 创建日期: 2025-01-XX
⏱️ 预计学时: 10-12 周
🎯 学习目标: 掌握 Windows 内核编程、驱动开发、VT 虚拟化技术
📋 前置要求: [[阶段五:核心逆向技术]]
🔗 返回: [[逆向与驱动开发学习路径(详细版)]]


📚 本阶段内容概览

  • [[#6.1 WDK环境搭建|6.1 WDK环境搭建]]
  • [[#6.2 驱动基础|6.2 驱动基础]]
    • [[#6.2.1 驱动入口与卸载|驱动入口与卸载]]
    • [[#6.2.2 设备对象与符号链接|设备对象与符号链接]]
    • [[#6.2.3 IRP请求处理|IRP请求处理]]
    • [[#6.2.4 驱动与应用通信|驱动与应用通信]]
  • [[#6.3 内核编程|6.3 内核编程]]
    • [[#6.3.1 内核内存操作|内核内存操作]]
    • [[#6.3.2 进程线程操作|进程线程操作]]
    • [[#6.3.3 内核回调|内核回调]]
  • [[#6.4 VT虚拟化技术|6.4 VT虚拟化技术]]

6.1 WDK环境搭建

📝 学习笔记

安装步骤

  1. 安装 Visual Studio 2019/2022 (带C++桌面开发)
  2. 安装 Windows SDK (与系统版本匹配)
  3. 安装 Windows Driver Kit (WDK)
  4. 安装 Spectre缓解库(可选)

测试环境配置

推荐配置:
- 主机: Windows 10/11
- 虚拟机: VMware/VirtualBox + Windows 10
- 调试: WinDbg + 内核调试

开启测试签名模式

# 以管理员运行
bcdedit /set testsigning on
bcdedit /set nointegritychecks on
bcdedit /debug on

# 重启生效
shutdown /r /t 0

内核调试设置(虚拟机)

# 被调试机 (虚拟机)
bcdedit /debug on
bcdedit /dbgsettings serial debugport:1 baudrate:115200

# VMware: 添加串口 -> Named Pipe -> \\.\pipe\com_1
# WinDbg: File -> Kernel Debug -> COM -> Pipe: \\.\pipe\com_1

6.2 驱动基础

6.2.1 驱动入口与卸载

📝 学习笔记

最简驱动框架

#include <ntddk.h>

// 驱动卸载函数
VOID DriverUnload(PDRIVER_OBJECT DriverObject) {
    UNREFERENCED_PARAMETER(DriverObject);
    DbgPrint("[MyDriver] Driver unloaded\n");
}

// 驱动入口点
extern "C" NTSTATUS DriverEntry(
    PDRIVER_OBJECT DriverObject,
    PUNICODE_STRING RegistryPath
) {
    UNREFERENCED_PARAMETER(RegistryPath);
    
    DbgPrint("[MyDriver] Driver loaded\n");
    
    // 设置卸载函数
    DriverObject->DriverUnload = DriverUnload;
    
    return STATUS_SUCCESS;
}

DRIVER_OBJECT 关键字段

字段 类型 说明
DriverUnload PDRIVER_UNLOAD 卸载回调
DeviceObject PDEVICE_OBJECT 设备对象链表
MajorFunction PDRIVER_DISPATCH[] IRP处理函数表
DriverName UNICODE_STRING 驱动名称

6.2.2 设备对象与符号链接

📝 学习笔记

#define DEVICE_NAME L"\\Device\\MyDevice"
#define SYMLINK_NAME L"\\??\\MyDevice"

PDEVICE_OBJECT g_DeviceObject = NULL;

NTSTATUS CreateDevice(PDRIVER_OBJECT DriverObject) {
    NTSTATUS status;
    UNICODE_STRING deviceName, symlinkName;
    
    RtlInitUnicodeString(&deviceName, DEVICE_NAME);
    RtlInitUnicodeString(&symlinkName, SYMLINK_NAME);
    
    // 创建设备对象
    status = IoCreateDevice(
        DriverObject,
        0,                          // DeviceExtension大小
        &deviceName,
        FILE_DEVICE_UNKNOWN,
        FILE_DEVICE_SECURE_OPEN,
        FALSE,                      // 非独占
        &g_DeviceObject
    );
    
    if (!NT_SUCCESS(status)) {
        DbgPrint("IoCreateDevice failed: 0x%X\n", status);
        return status;
    }
    
    // 创建符号链接(用户态可访问)
    status = IoCreateSymbolicLink(&symlinkName, &deviceName);
    
    if (!NT_SUCCESS(status)) {
        IoDeleteDevice(g_DeviceObject);
        return status;
    }
    
    // 设置通信方式
    g_DeviceObject->Flags |= DO_BUFFERED_IO;
    g_DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
    
    return STATUS_SUCCESS;
}

VOID DeleteDevice() {
    UNICODE_STRING symlinkName;
    RtlInitUnicodeString(&symlinkName, SYMLINK_NAME);
    
    IoDeleteSymbolicLink(&symlinkName);
    if (g_DeviceObject) {
        IoDeleteDevice(g_DeviceObject);
    }
}

[!important] 符号链接路径

  • \Device\xxx - 内核设备名
  • \??\xxx\DosDevices\xxx - 用户态符号链接
  • 用户态访问: \\.\xxx (如 \\.\MyDevice)

6.2.3 IRP请求处理

📝 学习笔记

IRP 分发函数

// 通用IRP处理
NTSTATUS DefaultDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
    UNREFERENCED_PARAMETER(DeviceObject);
    
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    
    return STATUS_SUCCESS;
}

// DeviceIoControl处理
NTSTATUS DeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
    UNREFERENCED_PARAMETER(DeviceObject);
    
    NTSTATUS status = STATUS_SUCCESS;
    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
    ULONG controlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
    
    PVOID inputBuffer = Irp->AssociatedIrp.SystemBuffer;
    ULONG inputLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
    PVOID outputBuffer = Irp->AssociatedIrp.SystemBuffer;
    ULONG outputLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
    
    ULONG bytesReturned = 0;
    
    switch (controlCode) {
        case IOCTL_MY_COMMAND:
            // 处理自定义命令
            break;
        default:
            status = STATUS_INVALID_DEVICE_REQUEST;
    }
    
    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = bytesReturned;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    
    return status;
}

// 注册分发函数
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {
    // ... 创建设备 ...
    
    for (int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
        DriverObject->MajorFunction[i] = DefaultDispatch;
    }
    
    DriverObject->MajorFunction[IRP_MJ_CREATE] = DefaultDispatch;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = DefaultDispatch;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl;
    
    return STATUS_SUCCESS;
}

常用 IRP 主功能码

功能码 触发条件
IRP_MJ_CREATE CreateFile
IRP_MJ_CLOSE CloseHandle
IRP_MJ_READ ReadFile
IRP_MJ_WRITE WriteFile
IRP_MJ_DEVICE_CONTROL DeviceIoControl

6.2.4 驱动与应用通信

📝 学习笔记

定义 IOCTL 码

// 驱动和应用共享的头文件
#define MY_DEVICE_TYPE 0x8000

#define IOCTL_READ_MEMORY CTL_CODE(MY_DEVICE_TYPE, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_WRITE_MEMORY CTL_CODE(MY_DEVICE_TYPE, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)

// 通信结构
typedef struct _MEMORY_REQUEST {
    ULONG ProcessId;
    PVOID Address;
    SIZE_T Size;
    PVOID Buffer;
} MEMORY_REQUEST, *PMEMORY_REQUEST;

应用层代码

#include <Windows.h>
#include "shared.h"  // 包含IOCTL定义

int main() {
    // 打开设备
    HANDLE hDevice = CreateFile(
        L"\\\\.\\MyDevice",
        GENERIC_READ | GENERIC_WRITE,
        0, NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL
    );
    
    if (hDevice == INVALID_HANDLE_VALUE) {
        printf("Failed to open device: %d\n", GetLastError());
        return 1;
    }
    
    // 发送请求
    MEMORY_REQUEST req = {};
    req.ProcessId = 1234;
    req.Address = (PVOID)0x12345678;
    req.Size = 4;
    
    BYTE buffer[4];
    DWORD bytesReturned;
    
    BOOL success = DeviceIoControl(
        hDevice,
        IOCTL_READ_MEMORY,
        &req, sizeof(req),      // 输入
        buffer, sizeof(buffer), // 输出
        &bytesReturned,
        NULL
    );
    
    if (success) {
        printf("Read successful: %02X %02X %02X %02X\n",
               buffer[0], buffer[1], buffer[2], buffer[3]);
    }
    
    CloseHandle(hDevice);
    return 0;
}

6.3 内核编程

6.3.1 内核内存操作

📝 学习笔记

内存分配

// 分页内存(可换出)
PVOID paged = ExAllocatePoolWithTag(PagedPool, 1024, 'tseT');

// 非分页内存(常驻物理内存)
PVOID nonPaged = ExAllocatePoolWithTag(NonPagedPool, 1024, 'tseT');

// 释放
ExFreePoolWithTag(paged, 'tseT');

// Windows 10+ 新API
PVOID mem = ExAllocatePool2(POOL_FLAG_NON_PAGED, 1024, 'tseT');
ExFreePool(mem);

跨进程内存读写

NTSTATUS ReadProcessMemory(HANDLE ProcessId, PVOID Address, PVOID Buffer, SIZE_T Size) {
    PEPROCESS process;
    NTSTATUS status;
    
    // 通过PID获取EPROCESS
    status = PsLookupProcessByProcessId(ProcessId, &process);
    if (!NT_SUCCESS(status)) return status;
    
    SIZE_T bytes = 0;
    
    // 复制内存
    status = MmCopyVirtualMemory(
        process,        // 源进程
        Address,        // 源地址
        PsGetCurrentProcess(), // 目标进程(当前驱动上下文)
        Buffer,         // 目标缓冲区
        Size,
        KernelMode,
        &bytes
    );
    
    ObDereferenceObject(process);
    return status;
}

MDL 映射物理内存

PVOID MapPhysicalMemory(PHYSICAL_ADDRESS PhysAddr, SIZE_T Size) {
    PMDL mdl = IoAllocateMdl(NULL, (ULONG)Size, FALSE, FALSE, NULL);
    if (!mdl) return NULL;
    
    MmBuildMdlForNonPagedPool(mdl);
    
    // 映射物理地址
    PVOID mapped = MmMapLockedPagesSpecifyCache(
        mdl,
        KernelMode,
        MmNonCached,
        NULL,
        FALSE,
        NormalPagePriority
    );
    
    return mapped;
}

6.3.2 进程线程操作

📝 学习笔记

进程枚举

VOID EnumerateProcesses() {
    PEPROCESS process = PsGetCurrentProcess();
    PLIST_ENTRY listHead = (PLIST_ENTRY)((ULONG_PTR)process + ActiveProcessLinksOffset);
    PLIST_ENTRY current = listHead->Flink;
    
    while (current != listHead) {
        PEPROCESS proc = (PEPROCESS)((ULONG_PTR)current - ActiveProcessLinksOffset);
        
        // 获取进程信息
        HANDLE pid = PsGetProcessId(proc);
        PUCHAR name = PsGetProcessImageFileName(proc);
        
        DbgPrint("PID: %d, Name: %s\n", (ULONG)(ULONG_PTR)pid, name);
        
        current = current->Flink;
    }
}

进程操作 API

API 功能
PsLookupProcessByProcessId 通过PID获取EPROCESS
PsGetProcessId 获取进程PID
PsGetProcessImageFileName 获取进程名
PsGetProcessPeb 获取PEB指针
KeAttachProcess 切换到目标进程上下文
KeStackAttachProcess 安全版进程切换

进程上下文切换

NTSTATUS ReadInProcessContext(PEPROCESS Process, PVOID Address, PVOID Buffer, SIZE_T Size) {
    KAPC_STATE apcState;
    
    // 切换到目标进程
    KeStackAttachProcess(Process, &apcState);
    
    __try {
        // 验证地址可读
        ProbeForRead(Address, Size, 1);
        RtlCopyMemory(Buffer, Address, Size);
    }
    __except(EXCEPTION_EXECUTE_HANDLER) {
        KeUnstackDetachProcess(&apcState);
        return GetExceptionCode();
    }
    
    KeUnstackDetachProcess(&apcState);
    return STATUS_SUCCESS;
}

6.3.3 内核回调

📝 学习笔记

进程创建回调

VOID ProcessNotifyCallback(
    PEPROCESS Process,
    HANDLE ProcessId,
    PPS_CREATE_NOTIFY_INFO CreateInfo
) {
    if (CreateInfo) {
        // 进程创建
        DbgPrint("Process created: PID=%d, Image=%wZ\n",
                 (ULONG)(ULONG_PTR)ProcessId,
                 CreateInfo->ImageFileName);
        
        // 可以阻止进程创建
        // CreateInfo->CreationStatus = STATUS_ACCESS_DENIED;
    } else {
        // 进程退出
        DbgPrint("Process exited: PID=%d\n", (ULONG)(ULONG_PTR)ProcessId);
    }
}

// 注册回调
NTSTATUS status = PsSetCreateProcessNotifyRoutineEx(ProcessNotifyCallback, FALSE);

// 卸载时移除
PsSetCreateProcessNotifyRoutineEx(ProcessNotifyCallback, TRUE);

线程创建回调

VOID ThreadNotifyCallback(HANDLE ProcessId, HANDLE ThreadId, BOOLEAN Create) {
    if (Create) {
        DbgPrint("Thread created: PID=%d, TID=%d\n",
                 (ULONG)(ULONG_PTR)ProcessId,
                 (ULONG)(ULONG_PTR)ThreadId);
    }
}

PsSetCreateThreadNotifyRoutine(ThreadNotifyCallback);
PsRemoveCreateThreadNotifyRoutine(ThreadNotifyCallback);

模块加载回调

VOID LoadImageCallback(
    PUNICODE_STRING FullImageName,
    HANDLE ProcessId,
    PIMAGE_INFO ImageInfo
) {
    DbgPrint("Image loaded: PID=%d, Base=%p, Name=%wZ\n",
             (ULONG)(ULONG_PTR)ProcessId,
             ImageInfo->ImageBase,
             FullImageName);
}

PsSetLoadImageNotifyRoutine(LoadImageCallback);
PsRemoveLoadImageNotifyRoutine(LoadImageCallback);

对象操作回调 (ObRegisterCallbacks)

OB_PREOP_CALLBACK_STATUS PreOperationCallback(
    PVOID RegistrationContext,
    POB_PRE_OPERATION_INFORMATION OperationInformation
) {
    // 可以修改访问权限
    if (OperationInformation->ObjectType == *PsProcessType) {
        // 移除某些权限
        OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= 
            ~PROCESS_TERMINATE;
    }
    return OB_PREOP_SUCCESS;
}

// 注册
OB_OPERATION_REGISTRATION opReg = {};
opReg.ObjectType = PsProcessType;
opReg.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
opReg.PreOperation = PreOperationCallback;

OB_CALLBACK_REGISTRATION cbReg = {};
cbReg.Version = OB_FLT_REGISTRATION_VERSION;
cbReg.OperationRegistrationCount = 1;
cbReg.OperationRegistration = &opReg;
RtlInitUnicodeString(&cbReg.Altitude, L"12345");

PVOID regHandle;
ObRegisterCallbacks(&cbReg, &regHandle);

6.4 VT虚拟化技术

📝 学习笔记

VT-x 基础概念

术语 说明
VMX Root 主机模式(Hypervisor运行)
VMX Non-Root 客户机模式(Guest运行)
VMCS 虚拟机控制结构
VM-Exit Guest退出到Host
VM-Entry Host进入Guest

检测 VT 支持

BOOLEAN CheckVTSupport() {
    int cpuInfo[4];
    
    // 检查CPUID
    __cpuid(cpuInfo, 1);
    if (!(cpuInfo[2] & (1 << 5))) {  // ECX.VMX
        return FALSE;
    }
    
    // 检查MSR
    ULONG64 featureControl = __readmsr(0x3A);  // IA32_FEATURE_CONTROL
    if (!(featureControl & 1)) {  // Lock bit
        // 可以启用
    }
    if (!(featureControl & 4)) {  // VMXON outside SMX
        return FALSE;
    }
    
    return TRUE;
}

简化的 VT 框架结构

// VMCS区域
typedef struct _VMCS_REGION {
    ULONG RevisionId;
    ULONG AbortIndicator;
    UCHAR Data[4088];
} VMCS_REGION, *PVMCS_REGION;

// 每个处理器的虚拟化状态
typedef struct _VCPU {
    PVOID VmxonRegion;
    PHYSICAL_ADDRESS VmxonRegionPA;
    PVMCS_REGION VmcsRegion;
    PHYSICAL_ADDRESS VmcsRegionPA;
    BOOLEAN VmxEnabled;
} VCPU, *PVCPU;

// 初始化VT
NTSTATUS InitializeVT() {
    // 1. 分配VMXON区域
    // 2. 执行VMXON
    // 3. 分配VMCS
    // 4. VMCLEAR + VMPTRLD
    // 5. 设置VMCS字段
    // 6. VMLAUNCH
}

// VM-Exit处理
VOID VmExitHandler(PGUEST_CONTEXT Context) {
    ULONG exitReason = __vmx_vmread(VMCS_EXIT_REASON);
    
    switch (exitReason) {
        case EXIT_REASON_CPUID:
            HandleCpuid(Context);
            break;
        case EXIT_REASON_MSR_READ:
            HandleMsrRead(Context);
            break;
        // ... 其他退出原因
    }
}

[!tip] VT 学习资源

  • Intel SDM Volume 3C: VMX章节
  • SimpleVisor: 开源轻量级Hypervisor
  • HyperPlatform: 功能完整的示例

✅ 阶段检查点

环境搭建检查

  • [ ] 安装配置WDK开发环境
  • [ ] 配置内核调试环境
  • [ ] 能加载和卸载测试驱动

驱动基础检查

  • [ ] 编写基本的驱动框架
  • [ ] 创建设备对象和符号链接
  • [ ] 实现驱动与应用的通信

内核编程检查

  • [ ] 掌握内核内存分配和释放
  • [ ] 实现跨进程内存读写
  • [ ] 使用内核回调监控系统事件

VT技术检查

  • [ ] 理解VT-x基本概念
  • [ ] 了解VMCS结构
  • [ ] 学习开源Hypervisor代码

📖 学习资料

资源类型 名称 说明
📕 书籍 Windows内核原理与实现 潘爱民著,深入内核
📕 书籍 寒江独钓:Windows内核安全编程 经典驱动开发
📕 文档 Intel SDM VT-x官方文档
🔧 项目 HyperPlatform VT研究项目
🔧 项目 SimpleVisor 轻量级Hypervisor
🌐 网站 OSR Online 驱动开发社区

🔗 导航

← [[阶段五:核心逆向技术]] | [[逆向与驱动开发学习路径(详细版)| 返回主目录]] | [[阶段七:图形渲染]] →

分享文章

未配置分享平台

请在主题设置中启用分享平台

评论