123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523 |
- #ifndef UNICODE
- #define UNICODE
- #endif
- #include <windows.h>
- #include <stdio.h>
- #include <map>
- #define NT_SUCCESS(x) ((x) >= 0)
- #define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
- #define SystemHandleInformation 16
- #define ObjectBasicInformation 0f
- #define ObjectNameInformation 1
- #define ObjectTypeInformation 2
- typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)(
- ULONG SystemInformationClass,
- PVOID SystemInformation,
- ULONG SystemInformationLength,
- PULONG ReturnLength
- );
- typedef NTSTATUS (NTAPI *_NtDuplicateObject)(
- HANDLE SourceProcessHandle,
- HANDLE SourceHandle,
- HANDLE TargetProcessHandle,
- PHANDLE TargetHandle,
- ACCESS_MASK DesiredAccess,
- ULONG Attributes,
- ULONG Options
- );
- typedef NTSTATUS (NTAPI *_NtQueryObject)(
- HANDLE ObjectHandle,
- ULONG ObjectInformationClass,
- PVOID ObjectInformation,
- ULONG ObjectInformationLength,
- PULONG ReturnLength
- );
- typedef struct _UNICODE_STRING
- {
- USHORT Length;
- USHORT MaximumLength;
- PWSTR Buffer;
- } UNICODE_STRING, *PUNICODE_STRING;
- typedef struct _SYSTEM_HANDLE
- {
- ULONG ProcessId;
- BYTE ObjectTypeNumber;
- BYTE Flags;
- USHORT Handle;
- PVOID Object;
- ACCESS_MASK GrantedAccess;
- } SYSTEM_HANDLE, *PSYSTEM_HANDLE;
- typedef struct _SYSTEM_HANDLE_INFORMATION
- {
- ULONG HandleCount;
- SYSTEM_HANDLE Handles[1];
- } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
- typedef enum _POOL_TYPE
- {
- NonPagedPool,
- PagedPool,
- NonPagedPoolMustSucceed,
- DontUseThisType,
- NonPagedPoolCacheAligned,
- PagedPoolCacheAligned,
- NonPagedPoolCacheAlignedMustS
- } POOL_TYPE, *PPOOL_TYPE;
- typedef struct _OBJECT_TYPE_INFORMATION
- {
- UNICODE_STRING Name;
- ULONG TotalNumberOfObjects;
- ULONG TotalNumberOfHandles;
- ULONG TotalPagedPoolUsage;
- ULONG TotalNonPagedPoolUsage;
- ULONG TotalNamePoolUsage;
- ULONG TotalHandleTableUsage;
- ULONG HighWaterNumberOfObjects;
- ULONG HighWaterNumberOfHandles;
- ULONG HighWaterPagedPoolUsage;
- ULONG HighWaterNonPagedPoolUsage;
- ULONG HighWaterNamePoolUsage;
- ULONG HighWaterHandleTableUsage;
- ULONG InvalidAttributes;
- GENERIC_MAPPING GenericMapping;
- ULONG ValidAccess;
- BOOLEAN SecurityRequired;
- BOOLEAN MaintainHandleCount;
- USHORT MaintainTypeList;
- POOL_TYPE PoolType;
- ULONG PagedPoolUsage;
- ULONG NonPagedPoolUsage;
- } OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
- void* GetLibraryProcAddress(const char* LibraryName, const char* procName)
- {
- return (void*)GetProcAddress(GetModuleHandleA(LibraryName), procName);
- }
- #include "HandleDbg.h"
- #include "BeefySysLib/util/CritSect.h"
- USING_NS_BF;
- struct HandleEntry
- {
- std::string mTraceStr;
- SYSTEM_HANDLE mHandle;
- };
- typedef std::map<USHORT, HandleEntry> HandleMap;
- static _NtQuerySystemInformation gNtQuerySystemInformation;
- static _NtDuplicateObject gNtDuplicateObject;
- static _NtQueryObject gNtQueryObject;
- static bool gHDInitialized = false;
- static HandleMap gHDHandleMap;
- static CritSect gHDCritSect;
- static void CheckInit()
- {
- if (gHDInitialized)
- return;
- gNtQuerySystemInformation = (_NtQuerySystemInformation) GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation");
- gNtDuplicateObject = (_NtDuplicateObject) GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject");
- gNtQueryObject = (_NtQueryObject) GetLibraryProcAddress("ntdll.dll", "NtQueryObject");
- gHDInitialized = true;
- }
- void HDCheckHandles(const std::string& traceStr)
- {
- AutoCrit autoCrit(gHDCritSect);
- CheckInit();
- /*if (!(processHandle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid)))
- {
- printf("Could not open PID %d! (Don't try to open a system process.)\n", pid);
- return 1;
- }*/
- PSYSTEM_HANDLE_INFORMATION handleInfo;
- ULONG handleInfoSize = 0x100000;
- handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize);
- NTSTATUS status;
- /* NtQuerySystemInformation won't give us the correct buffer size,
- so we guess by doubling the buffer size. */
- while ((status = gNtQuerySystemInformation(
- SystemHandleInformation,
- handleInfo,
- handleInfoSize,
- NULL
- )) == STATUS_INFO_LENGTH_MISMATCH)
- handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2);
- /* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */
- if (!NT_SUCCESS(status))
- {
- //printf("NtQuerySystemInformation failed!\n");
- return;
- }
- HandleMap oldHandleMap = gHDHandleMap;
- gHDHandleMap.clear();
- for (int i = 0; i < (int)handleInfo->HandleCount; i++)
- {
- SYSTEM_HANDLE& handle = handleInfo->Handles[i];
- /*HANDLE dupHandle = NULL;
- POBJECT_TYPE_INFORMATION objectTypeInfo;
- PVOID objectNameInfo;
- UNICODE_STRING objectName;
- ULONG returnLength;*/
- /* Check if this handle belongs to the PID the user specified. */
- if (handle.ProcessId != GetCurrentProcessId())
- continue;
- auto itr = oldHandleMap.find(handle.Handle);
- if (itr != oldHandleMap.end())
- gHDHandleMap.insert(*itr);
- else
- {
- HandleEntry handleEntry;
- handleEntry.mTraceStr = traceStr;
- handleEntry.mHandle = handle;
- gHDHandleMap.insert(HandleMap::value_type(handle.Handle, handleEntry));
- }
- }
- free(handleInfo);
- }
- void HDStart()
- {
- AutoCrit autoCrit(gHDCritSect);
- gHDHandleMap.clear();
- HDCheckHandles("");
- }
- void HDDump()
- {
- AutoCrit autoCrit(gHDCritSect);
- HANDLE processHandle = GetCurrentProcess();
- for (auto pair : gHDHandleMap)
- {
- USHORT handle = pair.first;
- HandleEntry handleEntry = pair.second;
- if (!handleEntry.mTraceStr.empty())
- {
- OutputDebugStrF("New Handle: %X %s\n", handle, handleEntry.mTraceStr.c_str());
- SYSTEM_HANDLE handle = handleEntry.mHandle;
- HANDLE dupHandle = NULL;
- POBJECT_TYPE_INFORMATION objectTypeInfo;
- PVOID objectNameInfo;
- UNICODE_STRING objectName;
- ULONG returnLength;
- /* Check if this handle belongs to the PID the user specified. */
- /*if (handle.ProcessId != pid)
- continue;*/
- /* Duplicate the handle so we can query it. */
- if (!NT_SUCCESS(gNtDuplicateObject(
- processHandle,
- (HANDLE)handle.Handle,
- GetCurrentProcess(),
- &dupHandle,
- 0,
- 0,
- 0
- )))
- {
- OutputDebugStrF("[%#x] Error!\n", handle.Handle);
- continue;
- }
- /* Query the object type. */
- objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000);
- if (!NT_SUCCESS(gNtQueryObject(
- dupHandle,
- ObjectTypeInformation,
- objectTypeInfo,
- 0x1000,
- NULL
- )))
- {
- OutputDebugStrF("[%#x] Error!\n", handle.Handle);
- CloseHandle(dupHandle);
- continue;
- }
- /* Query the object name (unless it has an access of
- 0x0012019f, on which NtQueryObject could hang. */
- if (handle.GrantedAccess == 0x0012019f)
- {
- /* We have the type, so display that. */
- OutputDebugStrF(
- "[%#x] %.*S: (did not get name)\n",
- handle.Handle,
- objectTypeInfo->Name.Length / 2,
- objectTypeInfo->Name.Buffer
- );
- free(objectTypeInfo);
- CloseHandle(dupHandle);
- continue;
- }
- objectNameInfo = malloc(0x1000);
- if (!NT_SUCCESS(gNtQueryObject(
- dupHandle,
- ObjectNameInformation,
- objectNameInfo,
- 0x1000,
- &returnLength
- )))
- {
- /* Reallocate the buffer and try again. */
- objectNameInfo = realloc(objectNameInfo, returnLength);
- if (!NT_SUCCESS(gNtQueryObject(
- dupHandle,
- ObjectNameInformation,
- objectNameInfo,
- returnLength,
- NULL
- )))
- {
- /* We have the type name, so just display that. */
- OutputDebugStrF(
- "[%#x] %.*S: (could not get name)\n",
- handle.Handle,
- objectTypeInfo->Name.Length / 2,
- objectTypeInfo->Name.Buffer
- );
- free(objectTypeInfo);
- free(objectNameInfo);
- CloseHandle(dupHandle);
- continue;
- }
- }
- /* Cast our buffer into an UNICODE_STRING. */
- objectName = *(PUNICODE_STRING)objectNameInfo;
- /* Print the information! */
- if (objectName.Length)
- {
- /* The object has a name. */
- OutputDebugStrF(
- "[%#x] %.*S: %.*S\n",
- handle.Handle,
- objectTypeInfo->Name.Length / 2,
- objectTypeInfo->Name.Buffer,
- objectName.Length / 2,
- objectName.Buffer
- );
- }
- else
- {
- /* Print something else. */
- OutputDebugStrF(
- "[%#x] %.*S: (unnamed)\n",
- handle.Handle,
- objectTypeInfo->Name.Length / 2,
- objectTypeInfo->Name.Buffer
- );
- }
- free(objectTypeInfo);
- free(objectNameInfo);
- CloseHandle(dupHandle);
- }
- }
- }
- int ZZwmain(int argc, WCHAR *argv[])
- {
- _NtQuerySystemInformation NtQuerySystemInformation = (_NtQuerySystemInformation)
- GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation");
- _NtDuplicateObject NtDuplicateObject = (_NtDuplicateObject)
- GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject");
- _NtQueryObject NtQueryObject = (_NtQueryObject)
- GetLibraryProcAddress("ntdll.dll", "NtQueryObject");
- NTSTATUS status;
- PSYSTEM_HANDLE_INFORMATION handleInfo;
- ULONG handleInfoSize = 0x10000;
- ULONG pid;
- HANDLE processHandle;
- ULONG i;
- if (argc < 2)
- {
- printf("Usage: handles [pid]\n");
- return 1;
- }
- pid = _wtoi(argv[1]);
- if (!(processHandle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid)))
- {
- printf("Could not open PID %d! (Don't try to open a system process.)\n", pid);
- return 1;
- }
- handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize);
- /* NtQuerySystemInformation won't give us the correct buffer size,
- so we guess by doubling the buffer size. */
- while ((status = NtQuerySystemInformation(
- SystemHandleInformation,
- handleInfo,
- handleInfoSize,
- NULL
- )) == STATUS_INFO_LENGTH_MISMATCH)
- handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2);
- /* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */
- if (!NT_SUCCESS(status))
- {
- printf("NtQuerySystemInformation failed!\n");
- return 1;
- }
- for (i = 0; i < handleInfo->HandleCount; i++)
- {
- SYSTEM_HANDLE handle = handleInfo->Handles[i];
- HANDLE dupHandle = NULL;
- POBJECT_TYPE_INFORMATION objectTypeInfo;
- PVOID objectNameInfo;
- UNICODE_STRING objectName;
- ULONG returnLength;
- /* Check if this handle belongs to the PID the user specified. */
- if (handle.ProcessId != pid)
- continue;
- /* Duplicate the handle so we can query it. */
- if (!NT_SUCCESS(NtDuplicateObject(
- processHandle,
- (HANDLE)(uintptr)handle.Handle,
- GetCurrentProcess(),
- &dupHandle,
- 0,
- 0,
- 0
- )))
- {
- printf("[%#x] Error!\n", handle.Handle);
- continue;
- }
- /* Query the object type. */
- objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000);
- if (!NT_SUCCESS(NtQueryObject(
- dupHandle,
- ObjectTypeInformation,
- objectTypeInfo,
- 0x1000,
- NULL
- )))
- {
- printf("[%#x] Error!\n", handle.Handle);
- CloseHandle(dupHandle);
- continue;
- }
- /* Query the object name (unless it has an access of
- 0x0012019f, on which NtQueryObject could hang. */
- if (handle.GrantedAccess == 0x0012019f)
- {
- /* We have the type, so display that. */
- printf(
- "[%#x] %.*S: (did not get name)\n",
- handle.Handle,
- objectTypeInfo->Name.Length / 2,
- objectTypeInfo->Name.Buffer
- );
- free(objectTypeInfo);
- CloseHandle(dupHandle);
- continue;
- }
- objectNameInfo = malloc(0x1000);
- if (!NT_SUCCESS(NtQueryObject(
- dupHandle,
- ObjectNameInformation,
- objectNameInfo,
- 0x1000,
- &returnLength
- )))
- {
- /* Reallocate the buffer and try again. */
- objectNameInfo = realloc(objectNameInfo, returnLength);
- if (!NT_SUCCESS(NtQueryObject(
- dupHandle,
- ObjectNameInformation,
- objectNameInfo,
- returnLength,
- NULL
- )))
- {
- /* We have the type name, so just display that. */
- printf(
- "[%#x] %.*S: (could not get name)\n",
- handle.Handle,
- objectTypeInfo->Name.Length / 2,
- objectTypeInfo->Name.Buffer
- );
- free(objectTypeInfo);
- free(objectNameInfo);
- CloseHandle(dupHandle);
- continue;
- }
- }
- /* Cast our buffer into an UNICODE_STRING. */
- objectName = *(PUNICODE_STRING)objectNameInfo;
- /* Print the information! */
- if (objectName.Length)
- {
- /* The object has a name. */
- printf(
- "[%#x] %.*S: %.*S\n",
- handle.Handle,
- objectTypeInfo->Name.Length / 2,
- objectTypeInfo->Name.Buffer,
- objectName.Length / 2,
- objectName.Buffer
- );
- }
- else
- {
- /* Print something else. */
- printf(
- "[%#x] %.*S: (unnamed)\n",
- handle.Handle,
- objectTypeInfo->Name.Length / 2,
- objectTypeInfo->Name.Buffer
- );
- }
- free(objectTypeInfo);
- free(objectNameInfo);
- CloseHandle(dupHandle);
- }
- free(handleInfo);
- CloseHandle(processHandle);
- return 0;
- }
|