公開された非公開関数NtQuerySystemInformation
と非公開の定数SystemExtendedHandleInformation (0x40)
を使うとカーネルオブジェクトハンドルの一覧を取得できます。固定長構造体のみなので前回投稿と比べれば遥かに扱いが楽です。なお、NtQuerySystemInformation
とSystemExtendedHandleInformation
は非後方互換性が明記された関数と非公開定数の組み合わせです。今後のWindowsアップデート次第では使えなくなる可能性があります。
追記∶C++では一見正常に動作しましたが、C#へ移植したところ範囲外アクセスエラーが発生しました。NtQuerySystemInformation
の2〜3回目の呼び出しの間にカーネルオブジェクトが増加したことが要因と思われます。適当なマージンを加えつつ、戻り値がメモリ不足情報(STATUS_INFO_LENGTH_MISMATCH
)の場合は処理を繰り返しても良いかもしれません。
#include <bit> #include <vector> #include <ranges> #include <format> #include <iostream> #define STRICT #define NOMINMAX #include <Windows.h> #include <winternl.h> #pragma comment(lib, "ntdll.lib") // 参考 // https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/query.htm static const auto SystemExtendedHandleInformation = (SYSTEM_INFORMATION_CLASS)0x40; // 参考 // https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/handle_table_entry_ex.htm?tx=60&ts=0,313 typedef struct SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX { PVOID Object; ULONG_PTR UniqueProcessId; ULONG_PTR HandleValue; ULONG GrantedAccess; USHORT CreatorBackTraceIndex; USHORT ObjectTypeIndex; ULONG HandleAttributes; ULONG Reserved; } *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX; // 参考 // https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/handle_ex.htm?tx=60 typedef struct SYSTEM_HANDLE_INFORMATION_EX { ULONG_PTR NumberOfHandles; ULONG_PTR Reserved; SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1]; } *PSYSTEM_HANDLE_INFORMATION_EX; static std::vector<SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX> GetSystemHandleTableEntryInfosEx() { // NtQuerySystemInformationはnullptrと0を渡すと56(64ビット環境)、 // サイズ56のバッファーを渡すと実際に必要なサイズを返す。 DWORD required; ::NtQuerySystemInformation(SystemExtendedHandleInformation, nullptr, 0, &required); std::vector<BYTE> buffer(required); ::NtQuerySystemInformation(SystemExtendedHandleInformation, buffer.data(), required, &required); buffer.resize(required); if (!NT_SUCCESS(::NtQuerySystemInformation(SystemExtendedHandleInformation, buffer.data(), required, nullptr))) throw std::exception(); auto pinfos = std::bit_cast<PSYSTEM_HANDLE_INFORMATION_EX>(buffer.data()); return std::vector(pinfos->Handles, pinfos->Handles + pinfos->NumberOfHandles); } int wmain() { auto entries = GetSystemHandleTableEntryInfosEx(); for (const auto& [i, entry] : entries | std::views::take(1000) | std::views::enumerate) { std::wcout << std::format(L"{}: {} ({})\n", i, entry.Object, entry.ObjectTypeIndex); } if (entries.size() > 1000) std::wcout << L"...\n"; return 0; }
参考