admin 发表于 3 天前

Windows内核驱动开发-读写驱动-第8章

Windows内核驱动开发-读写驱动-第8章
在 Windows 内核驱动开发中,系统回调机制是实现进程、线程、模块加载及注册表操作监控的核心技术。以下从技术原理、实现方法和实战案例三个维度,结合 Windows 内核架构和驱动开发规范,系统解析系统回调的应用逻辑:
一、系统回调机制的核心原理
Windows 内核通过事件通知机制允许驱动程序注册回调函数,以拦截关键系统操作。主要回调类型包括:

[*]进程 / 线程回调:通过PsSetCreateProcessNotifyRoutineEx和PsSetCreateThreadNotifyRoutine注册,监控进程 / 线程的创建、终止等生命周期事件。

[*]模块加载回调:使用PsSetLoadImageNotifyRoutine拦截模块加载事件,可获取模块路径、哈希值等信息。

[*]注册表回调:通过CmRegisterCallback注册,监控注册表键的创建、删除、修改等操作。
这些回调函数在内核模式下执行,可通过返回特定状态码(如STATUS_ACCESS_DENIED)直接干预系统行为。
二、关键技术实现路径
(一)进程监控与控制

[*]注册回调:
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) {
    UNREFERENCED_PARAMETER(RegistryPath);
    NTSTATUS status = PsSetCreateProcessNotifyRoutineEx(ProcessCreateCallback, TRUE);
    if (!NT_SUCCESS(status)) {
      return status;
    }
    DriverObject->DriverUnload = DriverUnload;
    return STATUS_SUCCESS;
}


[*]回调函数实现:
NTSTATUS ProcessCreateCallback(
    _Inout_ PEPROCESS Process,
    _In_ HANDLE ProcessId,
    _In_opt_ PPS_CREATE_NOTIFY_INFO CreateInfo
) {
    UNREFERENCED_PARAMETER(ProcessId);
    UNREFERENCED_PARAMETER(CreateInfo);

    // 获取进程名称
    PCHAR processName = PsGetProcessImageFileName(Process);

    // 禁止启动notepad.exe
    if (_stricmp(processName, "notepad.exe") == 0) {
      return STATUS_ACCESS_DENIED;
    }
    return STATUS_SUCCESS;
}

(二)模块加载控制

[*]注册回调:
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) {
    UNREFERENCED_PARAMETER(RegistryPath);
    PsSetLoadImageNotifyRoutine(ImageLoadCallback);
    DriverObject->DriverUnload = DriverUnload;
    return STATUS_SUCCESS;
}


[*]回调函数实现:
VOID ImageLoadCallback(
    _In_ PUNICODE_STRING FullImageName,
    _In_ HANDLE ProcessId,
    _In_ PIMAGE_INFO ImageInfo
) {
    UNREFERENCED_PARAMETER(ProcessId);

    // 禁止加载恶意模块
    if (wcsstr(FullImageName->Buffer, L"malware.dll") != NULL) {
      ZwUnloadDriver(ImageInfo->ImageBaseAddress);
    }
}

(三)注册表操作锁定

[*]注册回调:
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) {
    UNREFERENCED_PARAMETER(RegistryPath);
    OBJECT_ATTRIBUTES objAttr;
    InitializeObjectAttributes(&objAttr, NULL, 0, NULL, NULL);
    NTSTATUS status = CmRegisterCallback(RegistryCallback, &objAttr, NULL, &CallbackHandle);
    if (!NT_SUCCESS(status)) {
      return status;
    }
    DriverObject->DriverUnload = DriverUnload;
    return STATUS_SUCCESS;
}


[*]回调函数实现:
NTSTATUS RegistryCallback(
    _In_ PVOID CallbackContext,
    _In_ PVOID Argument1,
    _In_ PVOID Argument2
) {
    UNREFERENCED_PARAMETER(CallbackContext);

    PREG_NOTIFY_INFORMATION notifyInfo = (PREG_NOTIFY_INFORMATION)Argument1;
    if (notifyInfo->Type == RegNtPreCreateKey) {
      // 禁止创建特定注册表键
      if (wcsstr(notifyInfo->ObjectPath->Buffer, L"Software\\Malware") != NULL) {
            return STATUS_ACCESS_DENIED;
      }
    }
    return STATUS_SUCCESS;
}

三、实战应用与优化策略
(一)多场景监控方案

[*]进程防护:结合PsSetCreateProcessNotifyRoutineEx和PsSetLoadImageNotifyRoutine,实现进程创建与模块加载的双重拦截,防止恶意程序注入。

[*]注册表保护:通过CmRegisterCallback监控RegNtPreCreateKey和RegNtPreSetValueKey事件,阻止关键注册表项的修改。

[*]线程监控:使用PsSetCreateThreadNotifyRoutine拦截线程创建,可检测隐蔽线程等恶意行为。
(二)性能优化与稳定性保障

[*]异步处理:在回调函数中避免长时间阻塞,使用IoQueueWorkItem将耗时操作转移到工作线程。

[*]错误处理:对PsGetProcessImageFileName等可能返回NULL的函数进行防御性编程。

[*]兼容性适配:针对 Windows 版本差异,使用条件编译适配PsSetCreateProcessNotifyRoutineEx等 API 的参数变化。
(三)安全加固措施

[*]驱动签名:通过 Windows 硬件开发者中心获取数字签名,确保驱动可在 64 位系统加载。

[*]内存保护:使用ExAllocatePoolWithTag分配非分页内存,并通过ProbeForRead/Write进行边界检查。

[*]日志审计:通过DbgPrint输出关键操作日志,结合WinDbg进行调试和问题定位。
四、典型案例解析
(一)禁止特定进程启动
通过进程创建回调函数,拦截notepad.exe的启动:
NTSTATUS ProcessCreateCallback(...) {
    PCHAR processName = PsGetProcessImageFileName(Process);
    if (_stricmp(processName, "notepad.exe") == 0) {
      // 记录日志
      DbgPrint("Blocked process: %s", processName);
      return STATUS_ACCESS_DENIED;
    }
    return STATUS_SUCCESS;
}

(二)阻止恶意模块加载
在模块加载回调中,检查模块路径并卸载恶意模块:
VOID ImageLoadCallback(...) {
    if (wcsstr(FullImageName->Buffer, L"malware.dll") != NULL) {
      // 记录日志
      DbgPrint("Blocked module: %wZ", FullImageName);
      ZwUnloadDriver(ImageInfo->ImageBaseAddress);
    }
}

(三)锁定注册表关键路径
通过注册表回调禁止创建Software\\Malware键:
NTSTATUS RegistryCallback(...) {
    if (notifyInfo->Type == RegNtPreCreateKey &&
      wcsstr(notifyInfo->ObjectPath->Buffer, L"Software\\Malware") != NULL) {
      // 记录日志
      DbgPrint("Blocked registry key: %wZ", notifyInfo->ObjectPath);
      return STATUS_ACCESS_DENIED;
    }
    return STATUS_SUCCESS;
}

五、开发注意事项

[*]权限控制:驱动程序需运行在内核模式,具有最高系统权限,需严格限制回调函数的执行逻辑。

[*]版本兼容性:Windows 10/11 引入PsSetCreateProcessNotifyRoutineEx2等新 API,需使用#ifdef适配不同版本。

[*]调试工具:推荐使用WinDbg进行内核调试,结合kdnet实现远程调试。

[*]代码规范:遵循微软 WDM 驱动开发规范,避免使用未文档化的函数(如PsTerminateSystemThread)。
六、参考资源

[*]微软官方文档:


[*]PsSetCreateProcessNotifyRoutineEx


[*]PsSetLoadImageNotifyRoutine


[*]CmRegisterCallback

[*]经典书籍:


[*]《Windows 驱动开发技术详解》(张帆等著)


[*]《深入解析 Windows 操作系统》(Mark Russinovich 等著)
通过系统回调机制,开发者可实现对 Windows 系统关键操作的细粒度控制。在实际开发中,需结合具体场景设计回调逻辑,并严格遵循内核编程规范,确保驱动程序的稳定性和安全性。

**** Hidden Message *****



页: [1]
查看完整版本: Windows内核驱动开发-读写驱动-第8章