NtQuerySystemInformation无法捕获测试进程Mutex问题求助
排查NtQuerySystemInformation无法捕获测试进程Mutex的问题
核心问题分析
你的代码存在三个关键错误,导致无法正确枚举目标进程的Mutex:
1. 跨进程句柄误用
SYSTEM_HANDLE_TABLE_ENTRY_INFO中的HandleValue是目标进程的句柄值,而非当前进程的句柄。直接用该值调用NtQueryObject会失败,因为当前进程的句柄表中不存在这个值,必须先通过DuplicateHandle将目标进程的句柄复制到当前进程空间。
2. PUBLIC_OBJECT_TYPE_INFORMATION结构体拷贝错误
当动态分配poti后,直接执行oti = *poti会导致oti.TypeName.Buffer指向poti的堆内存,后续VirtualFree(poti)会使该指针变为野指针,同时栈上的oti缓冲区大小固定,首次调用NtQueryObject几乎必然因缓冲区不足失败。
3. 过滤逻辑遗漏场景
当前代码仅在poti不为空时处理句柄,但如果首次NtQueryObject调用成功(缓冲区足够),poti为NULL,这部分句柄会被直接忽略,导致漏检。
修复后的代码示例
修正InitializeMutexVector函数
void Comman::InitializeMutexVector(PSYSTEM_HANDLE_INFORMATION pshi) { for (ULONG i = 0; i < pshi->NumberOfHandles; ++i) { const auto& handleEntry = pshi->Handles[i]; HANDLE hTargetProcess = OpenProcess(PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, FALSE, handleEntry.UniqueProcessId); if (!hTargetProcess) continue; HANDLE hDuplicatedHandle = NULL; // 复制目标进程的句柄到当前进程 if (!DuplicateHandle(hTargetProcess, (HANDLE)handleEntry.HandleValue, GetCurrentProcess(), &hDuplicatedHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) { CloseHandle(hTargetProcess); continue; } NTSTATUS ret; ULONG required = 0; PPUBLIC_OBJECT_TYPE_INFORMATION poti = NULL; // 先查询所需缓冲区大小 ret = NtQueryObject(hDuplicatedHandle, ObjectTypeInformation, NULL, 0, &required); if (ret == STATUS_INFO_LENGTH_MISMATCH && required > 0) { poti = (PPUBLIC_OBJECT_TYPE_INFORMATION)VirtualAlloc(NULL, required, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (poti) { ret = NtQueryObject(hDuplicatedHandle, ObjectTypeInformation, poti, required, &required); if (NT_SUCCESS(ret)) { if (DEBUG) std::wcout << handleEntry.UniqueProcessId << ", " << poti->TypeName.Buffer << '\n'; if (!wcscmp(L"Mutant", poti->TypeName.Buffer)) mutexes.push_back(handleEntry); } } } // 清理资源 if (poti) VirtualFree(poti, 0, MEM_RELEASE); CloseHandle(hDuplicatedHandle); CloseHandle(hTargetProcess); } }
修正构造函数中的魔法数字
建议用定义好的枚举值代替魔法数字0x10,避免系统版本兼容问题:
// 替换原代码中的(SYSTEM_INFORMATION_CLASS)0x10 ret = NtQuerySystemInformation(SystemHandleInformation, pshi, SYSTEM_HANDLE_INFORMATION_SIZE, &ulRequired);
注:需要确保winternl.h已正确包含,或自行定义:
typedef enum _SYSTEM_INFORMATION_CLASS { SystemHandleInformation = 0x10 } SYSTEM_INFORMATION_CLASS;
额外注意事项
- 确保工具进程以足够权限运行(如管理员权限),否则无法打开某些进程或复制句柄。
- 测试进程死锁时,进程处于等待状态,句柄依然存在,修复后的代码应能正确捕获其Mutex。
内容的提问来源于stack exchange,提问作者Nascity
相关产品推荐
相关产品推荐

