内核模式移除PROCESS_SUSPEND_RESUME致进程永久挂起求助
问题:移除notepad.exe句柄权限后进程永久挂起的解决方法
问题背景
- 内核与C++开发新手,正在测试句柄创建预操作例程,目标是移除notepad.exe句柄的
PROCESS_TERMINATE(0x0001)和PROCESS_SUSPEND_RESUME(0x0800)权限,实现进程正常运行的同时阻止被终止或挂起。 - 当前代码可成功移除权限,但notepad.exe启动后会永久挂起。
- 开发环境:宿主Visual Studio 2019,宿主与目标物理机均运行Windows 10 1909。
当前代码:
if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE) { OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~0x0001; OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~0x0800; KdPrint(("[OperationInformation->Operation]: OB_OPERATION_HANDLE_CREATE\r\n")); }
原因分析与解决方法
1. 未过滤进程自身的句柄创建操作
你的代码会修改所有进程的句柄创建权限,包括notepad.exe自身创建的句柄。进程启动过程中,自身需要PROCESS_SUSPEND_RESUME权限完成线程初始化(比如启动时的线程挂起/恢复逻辑),如果自身句柄被移除该权限,会导致初始化失败,进程挂起。
修正代码:
添加进程判断,仅修改外部进程对notepad.exe创建的句柄权限,跳过notepad.exe自身的句柄操作:
#include <ntddk.h> VOID PreHandleCreateCallback(PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OperationInformation) { if (OperationInformation->Operation == OB_OPERATION_HANDLE_CREATE) { // 获取目标进程对象 PEPROCESS targetProcess = (PEPROCESS)OperationInformation->Object; UNICODE_STRING targetProcessName; RtlInitUnicodeString(&targetProcessName, L"notepad.exe"); // 获取当前操作对应的进程名 UNICODE_STRING currentObjName; NTSTATUS status = PsGetProcessImageFileName(targetProcess, ¤tObjName); if (!NT_SUCCESS(status)) { KdPrint(("[Failed to get process image name: 0x%X]\r\n", status)); return; } // 仅当目标是notepad.exe,且操作发起者不是notepad自身时修改权限 if (RtlCompareUnicodeString(¤tObjName, &targetProcessName, TRUE) == 0) { PEPROCESS currentProcess = PsGetCurrentProcess(); if (currentProcess != targetProcess) { // 移除指定权限 OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE; OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_SUSPEND_RESUME; KdPrint(("[Modified external handle access for notepad.exe]\r\n")); } else { // 允许自身保留权限,保证初始化正常 KdPrint(("[Skipped notepad.exe self-handle creation]\r\n")); } } // 释放字符串内存 RtlFreeUnicodeString(¤tObjName); } }
2. 区分进程创建时的初始句柄
进程启动时,系统或父进程会创建一个初始句柄(带有OB_OPERATION_HANDLE_CREATE_FROM_CREATE_PROCESS标志),这类句柄的权限修改可能直接影响进程启动流程。可以通过OperationFlags判断并跳过:
在上述代码的权限修改判断中添加:
// 跳过进程创建时的初始句柄 if (OperationInformation->OperationFlags & OB_OPERATION_HANDLE_CREATE_FROM_CREATE_PROCESS) { KdPrint(("[Skipped initial process creation handle]\r\n")); return; }
3. 调试定位挂起原因
使用WinDbg附加到目标物理机,查看notepad.exe的挂起状态:
- 执行
!process 0 0 notepad.exe获取进程的EPROCESS地址 - 执行
!process <EPROCESS地址> 7查看线程调用栈,确认挂起的系统调用位置,是否因权限不足导致
内容的提问来源于stack exchange,提问作者David Figueras Tamame
相关产品推荐
相关产品推荐

