PSYSTEM_HANDLE_INFORMATION HandleInfo = NULL;
ULONG HandleInfoLength = 0;
...
result = NTQSI((SYSTEM_INFORMATION_CLASS)0x10, NULL, 0, &HandleInfoLength);
if (result != 0xC0000004) {
printf("OmmeSearchProcessHandle - NTQSI output is unexpected! Expexted : 0xC0000004 Result : 0x%x\n", result);
return NULL;
}
printf("system handle info length : %i\n", HandleInfoLength);
SIZE_T HandleInfoRegionSize = HandleInfoLength;
result = NTAVM((HANDLE)(-1), (PVOID*)&HandleInfo, 0, &HandleInfoRegionSize, MEM_COMMIT, PAGE_READWRITE);
if (!NT_SUCCESS(result)) {
printf("OmmeSearchProcessHandle - NTAVM failed with result : %x\n", result);
return NULL;
}
result = NTQSI((SYSTEM_INFORMATION_CLASS)0x10, (PVOID)HandleInfo, HandleInfoLength, &HandleInfoLength);
if (!NT_SUCCESS(result)) {
printf("OmmeSearchProcessHandle - NTQSI failed with result : %x\n", result);
printf("system handle info length : %i\n", HandleInfoLength);
return NULL;
}
The code above produces this. Somehow the first NtQuerySystemInformation call doesnt give the correct return size, anyone have any idea about this? And then, i stubled upon this on Github, NtQuerySystemInformation won't give us the correct buffer size
, is this a common knowledge that NTQSI SystemHandleInformation wont give the correct return size?
CodePudding user response:
the handle count in system is very volatile. so between 2 calls to NtQuerySystemInformation handle count in system can incremented and require more size. you need call NtQuerySystemInformation in loop. and need use SystemExtendedHandleInformation
instead SystemHandleInformation
NTSTATUS TestHandles()
{
NTSTATUS status;
ULONG cb = 0x400000;
do
{
union {
PVOID buf;
PSYSTEM_HANDLE_INFORMATION_EX pshie;
};
status = STATUS_NO_MEMORY;
if (buf = LocalAlloc(0, cb = 0x1000))
{
if (0 <= (status = NtQuerySystemInformation(SystemExtendedHandleInformation, buf, cb, &cb)))
{
if (ULONG_PTR NumberOfHandles = pshie->NumberOfHandles)
{
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Entry = pshie->Handles;
do
{
} while (Entry , --NumberOfHandles);
}
}
LocalFree(buf);
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
return status;
}
CodePudding user response:
The ReturnLength
value returned by a call to NtQuerySystemInformation
with SystemHandleInformation
does not necessarily represent the required buffer size to hold the entire system handle information - or more precisely, it depends on the input buffer size if it does or not (refer to this). Calling the function twice like in your example is not a good practice even if it returned the expected buffer size, because the required size could change in between your first and second call. A working example could look like this:
void GetHandleInfo()
{
PSYSTEM_HANDLE_INFORMATION handleInfo = NULL;
DWORD size = 0, required = 0;
NTSTATUS handleInfoStatus;
do
{
if (handleInfo)
{
fpExFreePool(handleInfo);
handleInfo = NULL;
}
size = required PAGE_SIZE;
if(!(handleInfo = fpExAllocatePool(NonPagedPool, size)))
goto Done;
} while ((handleInfoStatus = fpZwQuerySystemInformation(0x10, handleInfo, size, &required)) == STATUS_INFO_LENGTH_MISMATCH);
if (!NT_SUCCESS(handleInfoStatus))
goto Done;
//The handle info is available here
Done:
if (handleInfo)
fpExFreePool(handleInfo);
return;
}