我一直在使用
NtQuerySystemInformation
中的winternl.h
函数来查找系统中的一些互斥体。我正在使用以下结构来通过该函数检索信息。
#pragma pack(1)
typedef struct __SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
DWORD UniqueProcessId;
UCHAR ObjectTypeIndex;
UCHAR HandleAttributes;
USHORT HandleValue;
PVOID Object;
ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
#pragma pack()
#pragma pack(1)
typedef struct __SYSTEM_HANDLE_INFORMATION
{
ULONG NumberOfHandles;
SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
#pragma pack()
这是检索和过滤互斥体的代码。
Comman::Comman()
{
PSYSTEM_HANDLE_INFORMATION pshi;
NTSTATUS ret;
ULONG ulRequired;
pshi = (PSYSTEM_HANDLE_INFORMATION)VirtualAlloc(NULL, SYSTEM_HANDLE_INFORMATION_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
ret = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)0x10, pshi, SYSTEM_HANDLE_INFORMATION_SIZE, &ulRequired);
if (pshi && !NT_SUCCESS(ret))
{
VirtualFree(pshi, 0, MEM_RELEASE);
pshi = (PSYSTEM_HANDLE_INFORMATION)VirtualAlloc(NULL, ulRequired + 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
ret = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)0x10, pshi, ulRequired + 4096, &ulRequired);
if (!NT_SUCCESS(ret))
throw ret;
}
InitializeMutexVector(pshi);
}
//...
void Comman::InitializeMutexVector(PSYSTEM_HANDLE_INFORMATION pshi)
{
int i;
PUBLIC_OBJECT_TYPE_INFORMATION oti;
PPUBLIC_OBJECT_TYPE_INFORMATION poti;
NTSTATUS ret;
ULONG required;
for (i = 0, required = 0, poti = NULL; i < pshi->NumberOfHandles; i++, required = 0, poti = NULL)
{
ret = NtQueryObject((PVOID)pshi->Handles[i].HandleValue, ObjectTypeInformation, &oti, sizeof(oti), &required);
if (ret == 0xC0000004)
{
poti = (PPUBLIC_OBJECT_TYPE_INFORMATION)VirtualAlloc(NULL, required + 1024, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
ret = NtQueryObject((PVOID)pshi->Handles[i].HandleValue, ObjectTypeInformation, poti, required + 1024, &required);
if (poti)
oti = *poti;
}
if (DEBUG && NT_SUCCESS(ret) && poti)
std::wcout << pshi->Handles[i].UniqueProcessId << ", " << oti.TypeName.Buffer << '\n';
if (NT_SUCCESS(ret) && poti && !wcscmp(L"Mutant", oti.TypeName.Buffer))
mutexes.push_back(pshi->Handles[i]);
if (poti)
VirtualFree(poti, 0, MEM_RELEASE);
}
}
我将结果打印为“PID,object_type_name”的格式,并制作了一个
.csv
文件,并用Microsoft Excel打开它。不幸的是,当我运行一个创建两个互斥体并故意导致死锁的测试程序时,NtQuerySystemInformation
函数没有从测试程序中获取任何资源。
我在下面附上了测试程序的代码,供可能需要的人使用。
#include <Windows.h>
#include <stdio.h>
HANDLE R1, R2, sync;
DWORD WINAPI ThreadProc(LPVOID param)
{
wprintf(L"[THRD] Acquiring R2.\n");
WaitForSingleObject(R2, INFINITE);
Sleep(2000);
wprintf(L"[THRD] Acquiring R1.\n");
WaitForSingleObject(R1, INFINITE);
}
int wmain(void)
{
HANDLE hThread;
DWORD dwThreadID;
wprintf(L"PID: %d\n", GetCurrentProcessId());
R1 = CreateMutexW(NULL, FALSE, L"name");
R2 = CreateMutexW(NULL, FALSE, L"name2");
if (!R1 || !R2)
{
wprintf(L"Mutex creation has failed.\n");
return -1;
}
hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, &dwThreadID);
if (!hThread)
{
wprintf(L"Thread creation has failed.\n");
return -1;
}
wprintf(L"[MAIN] Acquiring R1.\n");
WaitForSingleObject(R1, INFINITE);
Sleep(1000);
wprintf(L"[MAIN] Acquiring R2.\n");
WaitForSingleObject(R2, INFINITE);
wprintf(L"[MAIN] Releasing R1.\n");
ReleaseMutex(R1);
return 0;
}
提前感谢您,如果需要,我将非常乐意提供更多资源。
#pragma pack(1)
- 这不能出现在结构声明中。SystemExtendedHandleInformation
代替
SystemHandleInformation
STATUS_INFO_LENGTH_MISMATCH
HandleValue
是在另一个进程的上下文中,您首先需要
在查询之前将其复制到您的流程中void DumpMutexs()
{
if (HANDLE hMutant = CreateMutexExW(0, 0, 0, 0))
{
union {
PVOID buf;
PBYTE pb;
POBJECT_NAME_INFORMATION poni;
};
ULONG cb = 0x10000;
NTSTATUS status;
enum { cbNameInfo = 0x10000 };
do
{
status = STATUS_NO_MEMORY;
if (buf = LocalAlloc(LMEM_FIXED, cbNameInfo + (cb += 0x1000)))
{
SYSTEM_HANDLE_INFORMATION_EX* phei = (SYSTEM_HANDLE_INFORMATION_EX*)(pb + cbNameInfo);
if (0 <= (status = NtQuerySystemInformation(SystemExtendedHandleInformation, phei, cb, &cb)))
{
if (ULONG_PTR NumberOfHandles = phei->NumberOfHandles)
{
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles = phei->Handles;
ULONG dwProcessId = GetCurrentProcessId();
do
{
if (Handles->UniqueProcessId == dwProcessId &&
Handles->HandleValue == (ULONG_PTR)hMutant)
{
USHORT ObjectTypeIndex = Handles->ObjectTypeIndex;
NumberOfHandles = phei->NumberOfHandles;
Handles = phei->Handles;
HANDLE hProcess = 0;
ULONG_PTR UniqueProcessId = 0;
do
{
if (ObjectTypeIndex == Handles->ObjectTypeIndex)
{
if (Handles->UniqueProcessId != UniqueProcessId)
{
UniqueProcessId = Handles->UniqueProcessId;
if (hProcess)
{
NtClose(hProcess);
hProcess = 0;
}
hProcess = dwProcessId == UniqueProcessId ? 0 :
OpenProcess(PROCESS_DUP_HANDLE, FALSE, (ULONG)UniqueProcessId);
}
if (hProcess)
{
HANDLE hMutex;
if (DuplicateHandle(hProcess, (HANDLE)Handles->HandleValue,
NtCurrentProcess(), &hMutex, 0, 0, DUPLICATE_SAME_ACCESS))
{
if (0 <= NtQueryObject(hMutex, ObjectNameInformation, poni, cbNameInfo, &cb))
{
if (poni->Name.Length)
{
DbgPrint("%p:%p %wZ\n", UniqueProcessId, Handles->HandleValue, &poni->Name);
}
}
else
{
__nop();
}
NtClose(hMutex);
}
else
{
DbgPrint("dup(%p)=%x\n", Handles->HandleValue, RtlGetLastNtStatus());
}
}
}
} while (Handles++, --NumberOfHandles);
if (hProcess)
{
NtClose(hProcess);
hProcess = 0;
}
break;
}
} while (Handles++, --NumberOfHandles);
}
}
LocalFree(buf);
}
} while (STATUS_INFO_LENGTH_MISMATCH == status);
NtClose(hMutant);
}
}