Windows内核安全

15、阶段合集

1、课程目标

  1. 综合运用内核安全技术
  2. 构建完整的进程保护系统
  3. 实现内核级安全监控框架
  4. 掌握驱动开发最佳实践

2、名词解释

术语 解释
EDR Endpoint Detection and Response终端检测与响应
内核回调 内核事件通知机制
对象监控 句柄访问控制
防护驱动 提供系统保护功能的内核驱动

3、使用工具

工具 用途
Visual Studio + WDK 驱动开发
WinDbg 内核调试
Driver Verifier 驱动验证
OSR Driver Loader 驱动加载

4、技术原理

4.1、综合防护架构

┌─────────────────────────────────────────────────────────────┐
│                    内核安全防护架构                          │
│                                                             │
│  用户模式 (Ring3)                                          │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  用户界面  │  配置管理  │  日志查看  │  策略引擎   │   │
│  └─────────────────────────────────────────────────────┘   │
│                           │                                 │
│                     DeviceIoControl                         │
│                           ↓                                 │
│  ─────────────────── Ring0/Ring3边界 ───────────────────   │
│                           ↓                                 │
│  内核模式 (Ring0)                                          │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                    主驱动程序                        │   │
│  │  ┌──────────┬──────────┬──────────┬──────────┐     │   │
│  │  │进程监控  │线程监控   │模块监控  │注册表监控│     │   │
│  │  └──────────┴──────────┴──────────┴──────────┘     │   │
│  │  ┌──────────┬──────────┬──────────┬──────────┐     │   │
│  │  │对象监控  │文件监控   │网络监控  │内存监控  │     │   │
│  │  └──────────┴──────────┴──────────┴──────────┘     │   │
│  │                                                     │   │
│  │  ┌─────────────────────────────────────────────┐   │   │
│  │  │              策略执行引擎                    │   │   │
│  │  │  ┌─────────┐ ┌─────────┐ ┌─────────┐       │   │   │
│  │  │  │白名单   │ │黑名单   │ │规则匹配  │       │   │   │
│  │  │  └─────────┘ └─────────┘ └─────────┘       │   │   │
│  │  └─────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

5、代码实现

5.1、项目1:综合安全驱动框架

// SecurityDriver.h - 安全驱动头文件
#ifndef SECURITY_DRIVER_H
#define SECURITY_DRIVER_H

#include <ntddk.h>
#include <wdm.h>

// 设备名称
#define DEVICE_NAME     L"\\Device\\SecurityDriver"
#define SYMBOLIC_NAME   L"\\DosDevices\\SecurityDriver"

// IOCTL定义
#define IOCTL_ADD_PROTECTED_PID     CTL_CODE(0x8000, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_REMOVE_PROTECTED_PID  CTL_CODE(0x8000, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_ADD_BLOCKED_IMAGE     CTL_CODE(0x8000, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_GET_EVENT_LOG         CTL_CODE(0x8000, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SET_PROTECTION_MODE   CTL_CODE(0x8000, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS)

// 保护模式
typedef enum _PROTECTION_MODE {
    MODE_MONITOR_ONLY = 0,  // 仅监控
    MODE_ALERT,             // 监控+告警
    MODE_BLOCK              // 监控+阻止
} PROTECTION_MODE;

// 事件类型
typedef enum _SECURITY_EVENT_TYPE {
    EVENT_PROCESS_CREATE = 1,
    EVENT_PROCESS_TERMINATE,
    EVENT_THREAD_CREATE_REMOTE,
    EVENT_MODULE_LOAD,
    EVENT_REGISTRY_MODIFY,
    EVENT_HANDLE_OPEN_BLOCKED,
    EVENT_IMAGE_BLOCKED
} SECURITY_EVENT_TYPE;

// 安全事件
typedef struct _SECURITY_EVENT {
    LARGE_INTEGER       Timestamp;
    SECURITY_EVENT_TYPE EventType;
    HANDLE              ProcessId;
    HANDLE              TargetId;
    WCHAR               Details[256];
} SECURITY_EVENT, *PSECURITY_EVENT;

// 驱动上下文
typedef struct _DRIVER_CONTEXT {
    PDEVICE_OBJECT      DeviceObject;
    PVOID               ProcessCallback;
    PVOID               ThreadCallback;
    PVOID               ImageCallback;
    PVOID               ObjectCallback;
    LARGE_INTEGER       RegistryCallback;
    PROTECTION_MODE     Mode;
    ULONG               ProtectedPids[64];
    ULONG               ProtectedCount;
    WCHAR               BlockedImages[32][260];
    ULONG               BlockedImageCount;
    LIST_ENTRY          EventList;
    KSPIN_LOCK          EventLock;
    ULONG               EventCount;
    FAST_MUTEX          ConfigMutex;
} DRIVER_CONTEXT, *PDRIVER_CONTEXT;

// 全局上下文
extern DRIVER_CONTEXT g_Context;

// 函数声明
NTSTATUS InitializeCallbacks();
VOID CleanupCallbacks();
BOOLEAN IsProcessProtected(HANDLE ProcessId);
BOOLEAN IsImageBlocked(PUNICODE_STRING ImagePath);
VOID LogSecurityEvent(SECURITY_EVENT_TYPE Type, HANDLE ProcessId, 
                      HANDLE TargetId, PCWSTR Details);

#endif
// SecurityDriver.c - 主驱动文件
#include "SecurityDriver.h"
#include <ntstrsafe.h>

DRIVER_CONTEXT g_Context = {0};

// 检查进程是否受保护
BOOLEAN IsProcessProtected(HANDLE ProcessId) {
    ExAcquireFastMutex(&g_Context.ConfigMutex);
    
    for (ULONG i = 0; i < g_Context.ProtectedCount; i++) {
        if (g_Context.ProtectedPids[i] == (ULONG)(ULONG_PTR)ProcessId) {
            ExReleaseFastMutex(&g_Context.ConfigMutex);
            return TRUE;
        }
    }
    
    ExReleaseFastMutex(&g_Context.ConfigMutex);
    return FALSE;
}

// 检查镜像是否被阻止
BOOLEAN IsImageBlocked(PUNICODE_STRING ImagePath) {
    if (!ImagePath || !ImagePath->Buffer) return FALSE;
    
    ExAcquireFastMutex(&g_Context.ConfigMutex);
    
    for (ULONG i = 0; i < g_Context.BlockedImageCount; i++) {
        UNICODE_STRING blocked;
        RtlInitUnicodeString(&blocked, g_Context.BlockedImages[i]);
        
        // 后缀匹配
        if (ImagePath->Length >= blocked.Length) {
            UNICODE_STRING suffix;
            suffix.Buffer = ImagePath->Buffer + 
                           (ImagePath->Length - blocked.Length) / sizeof(WCHAR);
            suffix.Length = blocked.Length;
            suffix.MaximumLength = blocked.Length;
            
            if (RtlEqualUnicodeString(&suffix, &blocked, TRUE)) {
                ExReleaseFastMutex(&g_Context.ConfigMutex);
                return TRUE;
            }
        }
    }
    
    ExReleaseFastMutex(&g_Context.ConfigMutex);
    return FALSE;
}

// 记录安全事件
VOID LogSecurityEvent(
    SECURITY_EVENT_TYPE Type,
    HANDLE ProcessId,
    HANDLE TargetId,
    PCWSTR Details
) {
    KIRQL oldIrql;
    
    PSECURITY_EVENT event = (PSECURITY_EVENT)ExAllocatePoolWithTag(
        NonPagedPool, sizeof(SECURITY_EVENT), 'tnvE');
    
    if (!event) return;
    
    KeQuerySystemTime(&event->Timestamp);
    event->EventType = Type;
    event->ProcessId = ProcessId;
    event->TargetId = TargetId;
    
    if (Details) {
        RtlStringCbCopyW(event->Details, sizeof(event->Details), Details);
    }
    
    KeAcquireSpinLock(&g_Context.EventLock, &oldIrql);
    
    // 限制事件数量
    if (g_Context.EventCount >= 10000) {
        PLIST_ENTRY oldest = RemoveHeadList(&g_Context.EventList);
        PSECURITY_EVENT oldEvent = CONTAINING_RECORD(oldest, SECURITY_EVENT, 
            *(PLIST_ENTRY)((PUCHAR)oldest - sizeof(LIST_ENTRY)));
        ExFreePoolWithTag(oldEvent, 'tnvE');
        g_Context.EventCount--;
    }
    
    InsertTailList(&g_Context.EventList, (PLIST_ENTRY)event);
    g_Context.EventCount++;
    
    KeReleaseSpinLock(&g_Context.EventLock, oldIrql);
    
    DbgPrint("[Security] Event: Type=%d, PID=%d, Target=%d, %ws\n",
             Type, (ULONG)(ULONG_PTR)ProcessId, 
             (ULONG)(ULONG_PTR)TargetId, Details ? Details : L"");
}

// 进程创建回调
VOID ProcessNotifyCallback(
    PEPROCESS Process,
    HANDLE ProcessId,
    PPS_CREATE_NOTIFY_INFO CreateInfo
) {
    UNREFERENCED_PARAMETER(Process);
    
    if (CreateInfo) {
        // 进程创建
        WCHAR details[256];
        
        if (CreateInfo->ImageFileName) {
            RtlStringCbPrintfW(details, sizeof(details), 
                L"Image: %wZ", CreateInfo->ImageFileName);
            
            // 检查是否需要阻止
            if (g_Context.Mode == MODE_BLOCK && 
                IsImageBlocked(CreateInfo->ImageFileName)) {
                
                LogSecurityEvent(EVENT_IMAGE_BLOCKED, 
                    CreateInfo->ParentProcessId, ProcessId, details);
                CreateInfo->CreationStatus = STATUS_ACCESS_DENIED;
                return;
            }
        }
        
        LogSecurityEvent(EVENT_PROCESS_CREATE, 
            CreateInfo->ParentProcessId, ProcessId, details);
    } else {
        // 进程退出
        LogSecurityEvent(EVENT_PROCESS_TERMINATE, ProcessId, NULL, NULL);
        
        // 从保护列表移除
        ExAcquireFastMutex(&g_Context.ConfigMutex);
        for (ULONG i = 0; i < g_Context.ProtectedCount; i++) {
            if (g_Context.ProtectedPids[i] == (ULONG)(ULONG_PTR)ProcessId) {
                g_Context.ProtectedPids[i] = 
                    g_Context.ProtectedPids[--g_Context.ProtectedCount];
                break;
            }
        }
        ExReleaseFastMutex(&g_Context.ConfigMutex);
    }
}

// 线程创建回调
VOID ThreadNotifyCallback(
    HANDLE ProcessId,
    HANDLE ThreadId,
    BOOLEAN Create
) {
    if (!Create) return;
    
    HANDLE currentPid = PsGetCurrentProcessId();
    
    // 检测远程线程
    if (currentPid != ProcessId && ProcessId != (HANDLE)4) {
        WCHAR details[256];
        RtlStringCbPrintfW(details, sizeof(details),
            L"Remote thread from PID %d", (ULONG)(ULONG_PTR)currentPid);
        
        LogSecurityEvent(EVENT_THREAD_CREATE_REMOTE, currentPid, ProcessId, details);
    }
}

// 模块加载回调
VOID ImageLoadCallback(
    PUNICODE_STRING FullImageName,
    HANDLE ProcessId,
    PIMAGE_INFO ImageInfo
) {
    if (ImageInfo->SystemModeImage) return;  // 忽略内核模块
    
    WCHAR details[256];
    RtlStringCbPrintfW(details, sizeof(details), L"%wZ", FullImageName);
    
    LogSecurityEvent(EVENT_MODULE_LOAD, ProcessId, NULL, details);
}

// 对象回调
OB_PREOP_CALLBACK_STATUS ObjectPreCallback(
    PVOID RegistrationContext,
    POB_PRE_OPERATION_INFORMATION OperationInfo
) {
    UNREFERENCED_PARAMETER(RegistrationContext);
    
    if (OperationInfo->ObjectType != *PsProcessType &&
        OperationInfo->ObjectType != *PsThreadType) {
        return OB_PREOP_SUCCESS;
    }
    
    HANDLE targetPid;
    
    if (OperationInfo->ObjectType == *PsProcessType) {
        targetPid = PsGetProcessId((PEPROCESS)OperationInfo->Object);
    } else {
        targetPid = PsGetThreadProcessId((PETHREAD)OperationInfo->Object);
    }
    
    HANDLE currentPid = PsGetCurrentProcessId();
    
    // 检查是否访问受保护进程
    if (targetPid != currentPid && IsProcessProtected(targetPid)) {
        // 不限制受保护进程自己
        if (!IsProcessProtected(currentPid)) {
            if (OperationInfo->Operation == OB_OPERATION_HANDLE_CREATE) {
                ACCESS_MASK denyMask = PROCESS_TERMINATE | PROCESS_VM_WRITE |
                    PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD |
                    THREAD_TERMINATE | THREAD_SUSPEND_RESUME | THREAD_SET_CONTEXT;
                
                ACCESS_MASK original = 
                    OperationInfo->Parameters->CreateHandleInformation.DesiredAccess;
                
                OperationInfo->Parameters->CreateHandleInformation.DesiredAccess &= ~denyMask;
                
                if (original != OperationInfo->Parameters->CreateHandleInformation.DesiredAccess) {
                    WCHAR details[256];
                    RtlStringCbPrintfW(details, sizeof(details),
                        L"Access 0x%X blocked for PID %d", 
                        original & denyMask, (ULONG)(ULONG_PTR)targetPid);
                    
                    LogSecurityEvent(EVENT_HANDLE_OPEN_BLOCKED, currentPid, targetPid, details);
                }
            }
        }
    }
    
    return OB_PREOP_SUCCESS;
}

// 注册表回调
NTSTATUS RegistryCallback(
    PVOID CallbackContext,
    PVOID Argument1,
    PVOID Argument2
) {
    UNREFERENCED_PARAMETER(CallbackContext);
    
    REG_NOTIFY_CLASS notifyClass = (REG_NOTIFY_CLASS)(ULONG_PTR)Argument1;
    
    if (notifyClass == RegNtPreSetValueKey || 
        notifyClass == RegNtPreDeleteValueKey) {
        
        LogSecurityEvent(EVENT_REGISTRY_MODIFY, 
            PsGetCurrentProcessId(), NULL, L"Registry modification");
    }
    
    return STATUS_SUCCESS;
}

// 初始化回调
NTSTATUS InitializeCallbacks() {
    NTSTATUS status;
    
    // 进程回调
    status = PsSetCreateProcessNotifyRoutineEx(ProcessNotifyCallback, FALSE);
    if (!NT_SUCCESS(status)) {
        DbgPrint("[Security] Failed to register process callback: 0x%X\n", status);
        return status;
    }
    
    // 线程回调
    status = PsSetCreateThreadNotifyRoutine(ThreadNotifyCallback);
    if (!NT_SUCCESS(status)) {
        PsSetCreateProcessNotifyRoutineEx(ProcessNotifyCallback, TRUE);
        return status;
    }
    
    // 模块回调
    status = PsSetLoadImageNotifyRoutine(ImageLoadCallback);
    if (!NT_SUCCESS(status)) {
        PsSetCreateProcessNotifyRoutineEx(ProcessNotifyCallback, TRUE);
        PsRemoveCreateThreadNotifyRoutine(ThreadNotifyCallback);
        return status;
    }
    
    // 对象回调
    OB_OPERATION_REGISTRATION opReg[2] = {
        { PsProcessType, OB_OPERATION_HANDLE_CREATE, ObjectPreCallback, NULL },
        { PsThreadType, OB_OPERATION_HANDLE_CREATE, ObjectPreCallback, NULL }
    };
    
    UNICODE_STRING altitude;
    RtlInitUnicodeString(&altitude, L"321000");
    
    OB_CALLBACK_REGISTRATION callbackReg = {
        OB_FLT_REGISTRATION_VERSION, 2, altitude, NULL, opReg
    };
    
    status = ObRegisterCallbacks(&callbackReg, &g_Context.ObjectCallback);
    if (!NT_SUCCESS(status)) {
        DbgPrint("[Security] Failed to register object callback: 0x%X\n", status);
        // 继续,对象回调可选
    }
    
    // 注册表回调
    RtlInitUnicodeString(&altitude, L"320000");
    status = CmRegisterCallbackEx(RegistryCallback, &altitude, 
        NULL, NULL, &g_Context.RegistryCallback, NULL);
    
    DbgPrint("[Security] Callbacks initialized\n");
    
    return STATUS_SUCCESS;
}

// 清理回调
VOID CleanupCallbacks() {
    PsSetCreateProcessNotifyRoutineEx(ProcessNotifyCallback, TRUE);
    PsRemoveCreateThreadNotifyRoutine(ThreadNotifyCallback);
    PsRemoveLoadImageNotifyRoutine(ImageLoadCallback);
    
    if (g_Context.ObjectCallback) {
        ObUnRegisterCallbacks(g_Context.ObjectCallback);
    }
    
    if (g_Context.RegistryCallback.QuadPart) {
        CmUnRegisterCallback(g_Context.RegistryCallback);
    }
    
    DbgPrint("[Security] Callbacks cleaned up\n");
}

5.2、项目2:用户模式控制程序

// SecurityClient.c - 用户模式控制程序
#include <windows.h>
#include <stdio.h>

#define DEVICE_NAME "\\\\.\\SecurityDriver"

// IOCTL定义(与驱动一致)
#define IOCTL_ADD_PROTECTED_PID     CTL_CODE(0x8000, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_REMOVE_PROTECTED_PID  CTL_CODE(0x8000, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_ADD_BLOCKED_IMAGE     CTL_CODE(0x8000, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_GET_EVENT_LOG         CTL_CODE(0x8000, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SET_PROTECTION_MODE   CTL_CODE(0x8000, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS)

typedef struct _SECURITY_CLIENT {
    HANDLE hDevice;
} SECURITY_CLIENT, *PSECURITY_CLIENT;

BOOL SecurityClient_Connect(PSECURITY_CLIENT client) {
    client->hDevice = CreateFileA(DEVICE_NAME,
        GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    
    return client->hDevice != INVALID_HANDLE_VALUE;
}

void SecurityClient_Disconnect(PSECURITY_CLIENT client) {
    if (client->hDevice != INVALID_HANDLE_VALUE) {
        CloseHandle(client->hDevice);
    }
}

BOOL SecurityClient_ProtectPid(PSECURITY_CLIENT client, DWORD pid, BOOL protect) {
    DWORD bytesReturned;
    DWORD ioctl = protect ? IOCTL_ADD_PROTECTED_PID : IOCTL_REMOVE_PROTECTED_PID;
    
    return DeviceIoControl(client->hDevice, ioctl,
        &pid, sizeof(pid), NULL, 0, &bytesReturned, NULL);
}

BOOL SecurityClient_BlockImage(PSECURITY_CLIENT client, const WCHAR* imageName) {
    DWORD bytesReturned;
    DWORD len = (DWORD)(wcslen(imageName) + 1) * sizeof(WCHAR);
    
    return DeviceIoControl(client->hDevice, IOCTL_ADD_BLOCKED_IMAGE,
        (PVOID)imageName, len, NULL, 0, &bytesReturned, NULL);
}

BOOL SecurityClient_SetMode(PSECURITY_CLIENT client, DWORD mode) {
    DWORD bytesReturned;
    
    return DeviceIoControl(client->hDevice, IOCTL_SET_PROTECTION_MODE,
        &mode, sizeof(mode), NULL, 0, &bytesReturned, NULL);
}

void PrintUsage(const char* name) {
    printf("Usage:\n");
    printf("  %s protect <pid>      - Protect a process\n", name);
    printf("  %s unprotect <pid>    - Remove protection\n", name);
    printf("  %s block <name.exe>   - Block an image\n", name);
    printf("  %s mode <0|1|2>       - Set protection mode\n", name);
    printf("                          0=Monitor, 1=Alert, 2=Block\n");
}

int main(int argc, char* argv[]) {
    SECURITY_CLIENT client = {0};
    
    printf("=== Security Driver Client ===\n\n");
    
    if (!SecurityClient_Connect(&client)) {
        printf("Failed to connect to driver. Error: %d\n", GetLastError());
        printf("Make sure the driver is loaded.\n");
        return 1;
    }
    
    printf("Connected to security driver.\n");
    
    if (argc < 2) {
        PrintUsage(argv[0]);
        SecurityClient_Disconnect(&client);
        return 0;
    }
    
    if (strcmp(argv[1], "protect") == 0 && argc >= 3) {
        DWORD pid = atoi(argv[2]);
        if (SecurityClient_ProtectPid(&client, pid, TRUE)) {
            printf("Process %d is now protected.\n", pid);
        } else {
            printf("Failed to protect process. Error: %d\n", GetLastError());
        }
    }
    else if (strcmp(argv[1], "unprotect") == 0 && argc >= 3) {
        DWORD pid = atoi(argv[2]);
        if (SecurityClient_ProtectPid(&client, pid, FALSE)) {
            printf("Process %d protection removed.\n", pid);
        }
    }
    else if (strcmp(argv[1], "block") == 0 && argc >= 3) {
        WCHAR imageName[260];
        MultiByteToWideChar(CP_ACP, 0, argv[2], -1, imageName, 260);
        
        if (SecurityClient_BlockImage(&client, imageName)) {
            printf("Image '%s' is now blocked.\n", argv[2]);
        }
    }
    else if (strcmp(argv[1], "mode") == 0 && argc >= 3) {
        DWORD mode = atoi(argv[2]);
        if (SecurityClient_SetMode(&client, mode)) {
            const char* modeNames[] = {"Monitor Only", "Alert", "Block"};
            printf("Protection mode set to: %s\n", modeNames[mode]);
        }
    }
    else if (strcmp(argv[1], "self") == 0) {
        // 保护当前进程
        DWORD pid = GetCurrentProcessId();
        if (SecurityClient_ProtectPid(&client, pid, TRUE)) {
            printf("Current process (%d) is now protected.\n", pid);
            printf("Try to kill this process with Task Manager...\n");
            printf("Press Enter to exit and remove protection.\n");
            getchar();
        }
    }
    else {
        PrintUsage(argv[0]);
    }
    
    SecurityClient_Disconnect(&client);
    return 0;
}

5.3、项目3:驱动IOCTL处理

// SecurityIoctl.c - IOCTL处理
#include "SecurityDriver.h"

NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
    UNREFERENCED_PARAMETER(DeviceObject);
    
    PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
    PVOID buffer = Irp->AssociatedIrp.SystemBuffer;
    ULONG inputLen = irpStack->Parameters.DeviceIoControl.InputBufferLength;
    ULONG outputLen = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
    NTSTATUS status = STATUS_SUCCESS;
    ULONG bytesReturned = 0;
    
    switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
        case IOCTL_ADD_PROTECTED_PID: {
            if (inputLen >= sizeof(ULONG)) {
                ULONG pid = *(PULONG)buffer;
                
                ExAcquireFastMutex(&g_Context.ConfigMutex);
                if (g_Context.ProtectedCount < 64) {
                    g_Context.ProtectedPids[g_Context.ProtectedCount++] = pid;
                    DbgPrint("[Security] Protected PID: %d\n", pid);
                } else {
                    status = STATUS_INSUFFICIENT_RESOURCES;
                }
                ExReleaseFastMutex(&g_Context.ConfigMutex);
            }
            break;
        }
        
        case IOCTL_REMOVE_PROTECTED_PID: {
            if (inputLen >= sizeof(ULONG)) {
                ULONG pid = *(PULONG)buffer;
                
                ExAcquireFastMutex(&g_Context.ConfigMutex);
                for (ULONG i = 0; i < g_Context.ProtectedCount; i++) {
                    if (g_Context.ProtectedPids[i] == pid) {
                        g_Context.ProtectedPids[i] = 
                            g_Context.ProtectedPids[--g_Context.ProtectedCount];
                        DbgPrint("[Security] Unprotected PID: %d\n", pid);
                        break;
                    }
                }
                ExReleaseFastMutex(&g_Context.ConfigMutex);
            }
            break;
        }
        
        case IOCTL_ADD_BLOCKED_IMAGE: {
            if (inputLen > 0 && buffer) {
                ExAcquireFastMutex(&g_Context.ConfigMutex);
                if (g_Context.BlockedImageCount < 32) {
                    RtlCopyMemory(g_Context.BlockedImages[g_Context.BlockedImageCount],
                                  buffer, min(inputLen, 260 * sizeof(WCHAR)));
                    g_Context.BlockedImageCount++;
                    DbgPrint("[Security] Blocked image added\n");
                }
                ExReleaseFastMutex(&g_Context.ConfigMutex);
            }
            break;
        }
        
        case IOCTL_SET_PROTECTION_MODE: {
            if (inputLen >= sizeof(ULONG)) {
                ULONG mode = *(PULONG)buffer;
                if (mode <= MODE_BLOCK) {
                    g_Context.Mode = (PROTECTION_MODE)mode;
                    DbgPrint("[Security] Mode set to: %d\n", mode);
                }
            }
            break;
        }
        
        case IOCTL_GET_EVENT_LOG: {
            // 返回事件日志
            KIRQL oldIrql;
            KeAcquireSpinLock(&g_Context.EventLock, &oldIrql);
            
            // 实现事件导出...
            
            KeReleaseSpinLock(&g_Context.EventLock, oldIrql);
            break;
        }
        
        default:
            status = STATUS_INVALID_DEVICE_REQUEST;
    }
    
    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = bytesReturned;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    
    return status;
}

6、课后作业

  1. 扩展驱动添加文件系统监控
  2. 实现事件日志的持久化存储
  3. 添加网络连接监控功能
  4. 实现规则配置文件的加载

7、最佳实践

  1. 安全编码

    • 所有用户输入必须验证
    • 使用安全的字符串函数
    • 正确处理异常
  2. 性能优化

    • 避免在回调中执行耗时操作
    • 使用工作项处理复杂任务
    • 合理使用缓存
  3. 稳定性

    • 充分测试各种边界条件
    • 使用Driver Verifier
    • 正确处理卸载
  4. 兼容性

    • 测试多个Windows版本
    • 考虑32/64位兼容
    • 处理版本差异

8、扩展阅读

  • Windows驱动开发最佳实践
  • EDR产品架构分析
  • 内核安全对抗技术