枚举进程句柄,奇怪的问题
Enumerating process handles, weird issue
我扫描打开的进程句柄,并在控制台中打印它们。
- 我开始我的流程
- 我连接作弊引擎
- 我运行已打开句柄的枚举
- 我看到哪个流程可以处理我的流程
此时的奇怪问题如下,请检查代码:
array<Accessor^>^ AntiCheat::ScanHandles()
{
List<Accessor^>^ accessorList = gcnew List<Accessor^>();
if (!EnableDebugPrivilege(true))
printf("EnableDebugPrivilege failed: %dn", 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 usn");
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个打开的进程句柄(作弊引擎)。如果它被注释(运行得更快),则没有打开的句柄。但是我不知道为什么这会影响我的代码。我很惊讶,有人知道为什么会发生这种事吗?或者如何在没有printf(".")的情况下找到句柄;线
另一个问题是:每次调用函数时,分配的字节数都会重复。我不知道为什么。
我发现您的代码存在逻辑问题。
您并没有忽略handle.dwProcessId
等于currentProcessId
的数组项,因此您最终打开了自己进程的句柄。由于您只对查找其他进程感兴趣,因此应该忽略handle.dwProcessId
等于currentProcessId
的项。
您没有检查OpenProcess()
是否因ERROR_ACCESS_DENIED
以外的任何原因而失败。除非OpenProcess()
实际首先返回NULL,否则不要调用GetLastError()
。
如果DuplicateHandle()
失败,则不会关闭打开的句柄。为什么复制每个源句柄只是为了调用它上的GetProcessId()
?您已经从数组中获得了它们的进程ID,因此整个DuplicateHandle()
+GetProcessId()
是完全不必要的。
不管怎样,你的做法是错误的。看看这个讨论:
枚举引用对象的进程
在SystemInformationClass设置为SystemHandleInformation的情况下使用NtQuerySystemInformation。这将填充SYSTEM_HANDLE_INFORMATION结构的数组,这些结构定义为:
typedef struct _SYSTEM_HANDLE_INFORMATION { ULONG ProcessId; UCHAR ObjectTypeNumber; UCHAR Flags; USHORT Handle; PVOID Object; ACCESS_MASK GrantedAccess; } SYSTEM_HANDLE_INFORMATION;
搜索与ProcessID等于GetCurrentProcessId()的句柄对应的条目,然后查找具有相同Object指针的所有条目
尽管讨论显示SYSTEM_HANDLE_INFORMATION
的声明错误。下面的文章显示了正确的一个:
HOWTO:枚举处理
#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: %dn", 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 usn");
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] = ' ';
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();
}
- 枚举进程模块在有效句柄上返回无效句柄
- 获取特定进程的句柄数
- 获取现有进程句柄
- 获取进程内存信息失败,错误 6 句柄无效
- 在张量流中创建新操作时指定形状句柄的形状(输出张量的秩问题)
- 是否可以注入一个进程并获取给定的句柄,然后使用它们注入另一个进程
- 将窗口句柄从一个进程使用到另一个进程(插件 vst 音频)
- 为什么使用 ReadProcessMemory() 和当前进程的句柄
- 获取可停靠窗格C++的句柄时遇到问题
- 如何通过其 HWND 句柄在另一个进程中更改 TDateTimePicker 控件中的当前选定日期
- C++:通过进程id、进程句柄和标题名称从进程中获取唯一窗口的窗口句柄的最佳方法
- 获取进程句柄的详细信息
- JNI 问题:DLL 中的文件句柄出现符号查找错误C++
- 如何在Windows中获取当前进程的所有子进程的句柄
- 获取进程句柄名称
- 具有进程的句柄 如何注册以监视其关闭/重新启动/复制事件
- 如何在C/C++中创建一个新进程,并在WinXp中获得这个新进程句柄
- 获取已创建进程的进程句柄
- 枚举进程句柄,奇怪的问题
- 从进程句柄获取进程信息