gpt4 book ai didi

c++ - 枚举进程句柄,奇怪的问题

转载 作者:行者123 更新时间:2023-11-28 06:12:23 25 4
gpt4 key购买 nike

我扫描打开的进程句柄并在控制台中打印它们。

  1. 我开始我的过程
  2. 我附加 Cheat Engine
  3. 我运行已打开句柄的枚举
  4. 我查看哪个进程拥有我的进程的句柄

此时奇怪的问题如下,查看代码:

array<Accessor^>^ AntiCheat::ScanHandles()
{
List<Accessor^>^ accessorList = gcnew List<Accessor^>();

if (!EnableDebugPrivilege(true))
printf("EnableDebugPrivilege failed: %d\n", GetLastError());

tNtQuerySystemInformation oNtQuerySystemInformation = (tNtQuerySystemInformation)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation");

PSYSTEM_HANDLE_INFORMATION handleInfo = new SYSTEM_HANDLE_INFORMATION;
SYSTEM_INFORMATION_CLASS infoClass = (SYSTEM_INFORMATION_CLASS)16; // SystemHandleInformation
DWORD size = sizeof(SYSTEM_HANDLE_INFORMATION);
DWORD needed = 0;
NTSTATUS status = oNtQuerySystemInformation(infoClass, handleInfo, size, &needed);
while (!NT_SUCCESS(status))
{
if (needed == 0)
return nullptr;
// The previously supplied buffer wasn't enough.
delete handleInfo;
size = needed + 1024;
handleInfo = (PSYSTEM_HANDLE_INFORMATION)new BYTE[size];
status = oNtQuerySystemInformation(infoClass, handleInfo, size, &needed);
}

HANDLE currentProcess = GetCurrentProcess();
DWORD currentProcessId = GetProcessId(currentProcess);
for (DWORD i = 0; i < handleInfo->dwCount; i++)
{
//printf(".");
SYSTEM_HANDLE handle = handleInfo->Handles[i];

HANDLE procHandle = OpenProcess(PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, handle.dwProcessId);
if (GetLastError() == ERROR_ACCESS_DENIED)
continue;

HANDLE dupl = 0;
if (!DuplicateHandle(procHandle, (HANDLE)handle.wValue, currentProcess, &dupl, 0, false, DUPLICATE_SAME_ACCESS))
continue;

DWORD procId = GetProcessId(dupl);
if (procId == currentProcessId)
{
printf("accessing us\n");
char processName[MAX_PATH];
GetModuleFileNameEx((HMODULE)procHandle, NULL, processName, MAX_PATH);
accessorList->Add(gcnew Accessor(gcnew String(processName), handle.GrantedAccess));
}

CloseHandle(dupl);
}

return accessorList->ToArray();
}

如果我用 printf("."); 取消注释该行,我会看到 3 个打开的进程句柄 (cheatengine)。如果它被注释(运行得更快),则没有打开的句柄。但是我不知道为什么这会影响我的代码。我很惊讶,有谁知道为什么会这样?或者如何在没有我的 printf("."); 的情况下找出句柄。行?

另一个问题是:每次调用该函数时,分配的字节数都会重复。我也不知道为什么。

最佳答案

我发现你的代码存在逻辑问题。

您没有忽略 handle.dwProcessId 等于 currentProcessId 的数组项,因此您最终打开了您自己进程的句柄。由于您只对查找其他进程感兴趣,因此您应该忽略 handle.dwProcessId 等于 currentProcessId 的项。

您不会检查 OpenProcess() 是否因 ERROR_ACCESS_DENIED 以外的任何原因而失败。不要调用 GetLastError(),除非 OpenProcess() 实际上首先返回 NULL。

如果 DuplicateHandle() 失败,您并没有关闭打开的句柄。为什么要复制每个源句柄只是为了调用 GetProcessId()?您已经从数组中获得了它们的进程 ID,因此整个 DuplicateHandle()+GetProcessId() 完全没有必要。

无论如何,你采取的方法是错误的。看看这个讨论:

Enumerating the processes referencing an object

Use NtQuerySystemInformation with SystemInformationClass set to SystemHandleInformation. This fills in an array of SYSTEM_HANDLE_INFORMATION structures, which are defined as:

typedef struct _SYSTEM_HANDLE_INFORMATION {
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE_INFORMATION;

Search for the entry corresponding to the handle you opened with ProcessID equal to GetCurrentProcessId(), then find all entries with the same Object pointer.

尽管讨论显示了 SYSTEM_HANDLE_INFORMATION 的错误声明。以下文章显示了正确的文章:

HOWTO: Enumerate handles

#define SystemHandleInformation 16

typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);

/* The following structure is actually called SYSTEM_HANDLE_TABLE_ENTRY_INFO, but SYSTEM_HANDLE is shorter. */
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; /* Or NumberOfHandles if you prefer. */
SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;

话虽如此,尝试更像这样的事情:

array<Accessor^>^ AntiCheat::ScanHandles()
{
List<Accessor^>^ accessorList = gcnew List<Accessor^>();

if (!EnableDebugPrivilege(true))
printf("EnableDebugPrivilege failed: %d\n", GetLastError());

tNtQuerySystemInformation oNtQuerySystemInformation = (tNtQuerySystemInformation) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation");

DWORD currentProcessId = GetCurrentProcessId();
HANDLE currentProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, currentProcessId);
PVOID currentProcessAddr = nullptr;

DWORD size = sizeof(SYSTEM_HANDLE_INFORMATION);
DWORD needed = 0;
PSYSTEM_HANDLE_INFORMATION handleInfo = (PSYSTEM_HANDLE_INFORMATION) new BYTE[size];
SYSTEM_INFORMATION_CLASS infoClass = (SYSTEM_INFORMATION_CLASS) 16; // SystemHandleInformation
NTSTATUS status = oNtQuerySystemInformation(infoClass, handleInfo, size, &needed);
while (status == STATUS_INFO_LENGTH_MISMATCH)
{
// The previously supplied buffer wasn't enough.
delete[] handleInfo;
size += 1024;
handleInfo = (PSYSTEM_HANDLE_INFORMATION) new BYTE[size];
status = oNtQuerySystemInformation(infoClass, handleInfo, size, &needed);
}
if (status != 0)
{
delete[] handleInfo;
return nullptr;
}


for (DWORD i = 0; i < handleInfo->dwCount; i++)
{
SYSTEM_HANDLE &handle = handleInfo->Handles[i];

if ((handle.dwProcessId == currentProcessId) &&
(currentProcess == (HANDLE)handle.wValue))
{
currentProcessAddr = handle.pAddress;
break;
}
}

for (DWORD i = 0; i < handleInfo->dwCount; i++)
{
SYSTEM_HANDLE &handle = handleInfo->Handles[i];

if ((handle.dwProcessId != currentProcessId) &&
(handle.pAddress == currentProcessAddr))
{
printf("accessing us\n");

HANDLE procHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, handle.dwProcessId);
if (procHandle != 0)
{
char processName[MAX_PATH+1];
DWORD len = GetModuleFileNameEx((HMODULE)procHandle, NULL, processName, MAX_PATH);
CloseHandle(procHandle);
processName[len] = '\0';
accessorList->Add(gcnew Accessor(gcnew String(processName), handle.GrantedAccess));
}
else
accessorList->Add(gcnew Accessor(gcnew String("unknown"), handle.GrantedAccess));
}
}

CloseHandle(currentProcess);

delete[] handleInfo;
return accessorList->ToArray();
}

关于c++ - 枚举进程句柄,奇怪的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30991025/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com