当配套应用未运行时,正确禁用Windows内核模式驱动活动的方法
核心思路:驱动侧主动监控应用存活状态
因为应用被强制终止(如任务管理器结束进程)时无法主动发送IRP通知驱动,所以必须由驱动主动检测应用进程的存活状态,而非被动等待应用的关闭指令。以下是针对不同驱动类型的具体实现方案:
方案一:通过进程句柄等待实现精准监控
这是最直接可靠的方式,适用于所有Windows驱动类型:
- 应用启动后,通过IRP向驱动传递自身的进程ID(PID);驱动收到后,调用
ZwOpenProcess打开该进程的句柄,权限仅需SYNCHRONIZE即可。 - 驱动使用
PsCreateSystemThread创建一个系统线程,线程内调用WaitForSingleObject等待进程句柄进入SIGNALED状态(进程终止时会自动触发)。 - 等待返回后,驱动立即切换到“禁用”状态:比如在全局变量中标记
g_DriverEnabled = FALSE,后续所有核心业务逻辑(如minifilter的预操作回调、网络驱动的数据包处理)都先检查该状态,若为FALSE则直接跳过处理。
简化代码示例:
// 驱动全局状态 HANDLE g_AppProcessHandle = NULL; KSPIN_LOCK g_StatusLock; BOOLEAN g_DriverEnabled = TRUE; // 应用监控线程函数 VOID AppMonitorThread(PVOID Context) { NTSTATUS status = WaitForSingleObject(g_AppProcessHandle, INFINITE); if (status == WAIT_OBJECT_0) { // 应用已终止,禁用驱动 KeAcquireSpinLock(&g_StatusLock, NULL); g_DriverEnabled = FALSE; KeReleaseSpinLock(&g_StatusLock, NULL); ZwClose(g_AppProcessHandle); g_AppProcessHandle = NULL; } PsTerminateSystemThread(STATUS_SUCCESS); } // 处理应用发送PID的IRP回调 NTSTATUS HandleSetAppIrp(PIRP Irp) { ULONG targetPid = *(PULONG)Irp->AssociatedIrp.SystemBuffer; OBJECT_ATTRIBUTES objAttr; InitializeObjectAttributes(&objAttr, NULL, 0, NULL, NULL); CLIENT_ID clientId = { (HANDLE)targetPid, NULL }; NTSTATUS status = ZwOpenProcess(&g_AppProcessHandle, SYNCHRONIZE, &objAttr, &clientId); if (NT_SUCCESS(status)) { HANDLE threadHandle; status = PsCreateSystemThread(&threadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, AppMonitorThread, NULL); if (NT_SUCCESS(status)) { ZwClose(threadHandle); // 驱动无需持有线程句柄 } } Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; }
方案二:全局进程终止通知(适用于Vista及以上系统)
利用Windows内核的进程通知机制,全局监控进程终止事件:
- 应用启动时,通过IRP向驱动传递自身的**进程图像名(如myapp.exe)**或PID,驱动保存该标识。
- 驱动调用
PsSetCreateProcessNotifyRoutineEx注册全局进程回调,当收到进程终止通知时,检查是否为目标应用的PID。 - 匹配成功后,立即切换驱动到禁用状态。
针对不同驱动类型的细节处理
- Minifilter微筛选器:在
PreOperationCallback等核心回调中先检查g_DriverEnabled状态,若为FALSE则直接返回FLT_PREOP_SUCCESS_NO_CALLBACK,跳过所有过滤逻辑;如需完全暂停,可调用FltDetachVolume暂时分离卷,待应用重启后再重新附加。 - 网络驱动:NDIS驱动可在
ProtocolReceiveNetBufferLists回调中直接丢弃数据包;WDM网络驱动则在IRP_MJ_READ/WRITE等处理函数中返回STATUS_SUCCESS,不执行核心转发逻辑。
关键注意事项
- 权限控制:驱动打开进程时仅请求
SYNCHRONIZE权限,避免过高权限触发安全软件拦截。 - 状态重置:当应用重启并重新连接驱动时,需处理对应的IRP,重置
g_DriverEnabled为TRUE并重启监控逻辑。 - 线程安全:全局状态变量必须用自旋锁(如
KSPIN_LOCK)保护,避免多线程竞争导致的状态异常。 - 边界测试:需测试应用强制终止、系统重启后驱动状态恢复、多实例应用等场景。
内容的提问来源于stack exchange,提问作者John Doe
相关产品推荐
相关产品推荐

