Windows平台下如何用C++列出进程使用的所有句柄?
用C++枚举Windows进程句柄的实现方案
要实现类似Sysinternals Handle.exe或Process Explorer的进程句柄枚举功能,核心是调用未公开的NtQuerySystemInformation API——这也是Sysinternals工具的底层实现方式。下面是具体的实现步骤和代码示例:
1. 必备的结构体与类型定义
NtQuerySystemInformation属于Windows内核未公开API,需要自行定义所需的结构体和枚举值:
#include <windows.h> #include <winternl.h> #include <psapi.h> #include <vector> #include <iostream> // 系统信息类枚举,此处用到SystemHandleInformation typedef enum _SYSTEM_INFORMATION_CLASS { SystemHandleInformation = 16 } SYSTEM_INFORMATION_CLASS; // 单个句柄的详细信息结构体 typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO { USHORT UniqueProcessId; USHORT CreatorBackTraceIndex; UCHAR ObjectTypeIndex; UCHAR HandleAttributes; USHORT HandleValue; PVOID Object; ULONG GrantedAccess; } SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO; // 系统句柄信息的顶层结构体 typedef struct _SYSTEM_HANDLE_INFORMATION { ULONG NumberOfHandles; SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1]; } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; // 声明NtQuerySystemInformation函数指针 typedef NTSTATUS(WINAPI* PNtQuerySystemInformation)( SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength );
2. 提升调试权限(关键步骤)
要枚举其他进程的句柄,必须启用SeDebugPrivilege权限:
BOOL EnableDebugPrivilege() { HANDLE hToken; TOKEN_PRIVILEGES tp; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { return FALSE; } LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid); tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL); CloseHandle(hToken); return (GetLastError() == ERROR_SUCCESS); }
3. 枚举句柄的核心逻辑
void EnumProcessHandles() { if (!EnableDebugPrivilege()) { std::cerr << "Failed to enable debug privilege" << std::endl; return; } // 加载ntdll.dll并获取NtQuerySystemInformation函数地址 HMODULE hNtdll = GetModuleHandle(L"ntdll.dll"); if (!hNtdll) { std::cerr << "Failed to load ntdll.dll" << std::endl; return; } PNtQuerySystemInformation NtQuerySystemInformation = reinterpret_cast<PNtQuerySystemInformation>(GetProcAddress(hNtdll, "NtQuerySystemInformation")); if (!NtQuerySystemInformation) { std::cerr << "Failed to get NtQuerySystemInformation address" << std::endl; return; } ULONG bufferSize = 0x10000; // 初始缓冲区大小 std::vector<BYTE> buffer(bufferSize); NTSTATUS status; // 第一次调用获取所需的缓冲区大小 status = NtQuerySystemInformation(SystemHandleInformation, buffer.data(), bufferSize, &bufferSize); if (status == STATUS_INFO_LENGTH_MISMATCH) { buffer.resize(bufferSize); status = NtQuerySystemInformation(SystemHandleInformation, buffer.data(), bufferSize, &bufferSize); } if (!NT_SUCCESS(status)) { std::cerr << "NtQuerySystemInformation failed with status: 0x" << std::hex << status << std::endl; return; } PSYSTEM_HANDLE_INFORMATION handleInfo = reinterpret_cast<PSYSTEM_HANDLE_INFORMATION>(buffer.data()); for (ULONG i = 0; i < handleInfo->NumberOfHandles; ++i) { SYSTEM_HANDLE_TABLE_ENTRY_INFO& handle = handleInfo->Handles[i]; // 可选:过滤当前进程的句柄 if (handle.UniqueProcessId == GetCurrentProcessId()) { continue; } // 打开目标进程,需要PROCESS_DUP_HANDLE权限 HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, handle.UniqueProcessId); if (!hProcess) { continue; } // 复制句柄到当前进程,以便查询对象详情 HANDLE hDupHandle; if (DuplicateHandle(hProcess, reinterpret_cast<HANDLE>(handle.HandleValue), GetCurrentProcess(), &hDupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) { // 示例:查询文件句柄对应的路径 WCHAR fileName[MAX_PATH] = {0}; if (GetFinalPathNameByHandle(hDupHandle, fileName, MAX_PATH, VOLUME_NAME_DOS)) { std::wcout << L"PID: " << handle.UniqueProcessId << L", Handle: 0x" << std::hex << handle.HandleValue << L", Path: " << fileName << std::endl; } CloseHandle(hDupHandle); } CloseHandle(hProcess); } }
4. 主函数调用示例
int main() { EnumProcessHandles(); return 0; }
关键说明
NtQuerySystemInformation返回的SYSTEM_HANDLE_INFORMATION包含系统中所有进程的句柄列表,遍历即可获取每个句柄的基本属性(所属PID、句柄值、权限等)。- 复制句柄是为了在当前进程中调用
GetFinalPathNameByHandle等API查询对象详情,若仅需句柄基础属性,可跳过复制步骤。 - 若未启用
SeDebugPrivilege,仅能枚举当前进程的句柄,无法访问其他进程的句柄。
内容的提问来源于stack exchange,提问作者anitarazafi
相关产品推荐
相关产品推荐

