You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 22:47:06