此代码在64位应用程序中运行。目标应用程序是32位。
每次运行此代码时,CreateToolhelp32Snapshot()
都会返回INVALID_HANDLE_VALUE
,然后GetLastError()
会返回ERROR_PARTIAL_COPY
。所以它跳过循环并返回false。
BOOL HookInjector::InjectIntoProcess(DWORD pID)
{
//Get Handle to Remote Process
HANDLE Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
....
//Check to see if 64-bit or 32-bit application
IsWow64Process(Proc, &isWow64);
size_t szCurProc = sizeof(void*); //returns 8
if (isWow64)
{
__debugbreak();
//Get list of all Modules associated with the Process
HANDLE hProc32Module;
do {
hProc32Module = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE32, pID);
}
while ((hProc32Module == INVALID_HANDLE_VALUE) && (GetLastError() == ERROR_BAD_LENGTH));
if (hProc32Module == INVALID_HANDLE_VALUE) {
__debugbreak();
DWORD err = GetLastError(); //just to see the error code which is 0x12b
return false;
}
//Find the module for Kernel.dll and get the base address of it
MODULEENTRY32 entryModule;
entryModule.dwSize = sizeof(MODULEENTRY32);
BOOL isGetModuleSuccess = Module32First(hProc32Module, &entryModule);
DWORD errEndofList = GetLastError();
BOOL isSuccessful = false;
while (errEndofList != ERROR_NO_MORE_FILES && isGetModuleSuccess)
{
if (_tcscmp(entryModule.szModule, KERNEL32_DLL)){
isSuccessful = true;
break;
}
isGetModuleSuccess = Module32Next(hProc32Module, &entryModule);
errEndofList = GetLastError();
}
if (!isSuccessful)
{
__debugbreak();
CloseHandle(hProc32Module);
return false;
}
//Get handle for Kernel.dll module
hKernel32 = entryModule.hModule;
CloseHandle(hProc32Module);
}
else
{
....
答案 0 :(得分:1)
根据documentation,当{32}进程尝试访问64位进程调用CreateToolhelp32Snapshot()
时,ERROR_PARTIAL_COPY
仅在CreateToolhelp32Snapshot()
时失败:
如果指定的进程是64位进程且调用方是32位进程,则此函数将失败,最后一个错误代码为ERROR_PARTIAL_COPY(299)。
确保您的应用程序真正编译为64位开头。只有在64位进程中调用TH32CS_SNAPMODULE32
时才使用CreateToolhelp32Snapshot()
:
TH32CS_SNAPMODULE32
0x00000010
包括从64位进程调用时快照中th32ProcessID中指定的进程的所有32位模块。
除非另有说明,否则您也没有考虑{API}仅在API函数失败时更新GetLastError()
。你的循环假设每次API调用后都会更新GetLastError()
,这根本不是真的。
尝试更像这样的东西:
BOOL HookInjector::InjectIntoProcess(DWORD pID)
{
//Get Handle to Remote Process
HANDLE Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
....
DWORD dwFlag;
#ifdef _WIN64
//Check if Remote Process is a 32-bit application
BOOL isWow64 = FALSE;
IsWow64Process(Proc, &isWow64);
if (!isWow64) return false;
// TH32CS_SNAPMODULE32 includes 32bit modules when used by a 64bit process...
dwFlag = TH32CS_SNAPMODULE32;
#else
// TH32CS_SNAPMODULE includes 32bit modules when used by a 32bit process...
dwFlag = TH32CS_SNAPMODULE;
#endif
__debugbreak();
//Get list of all Modules associated with the Process
HANDLE hProc32Module;
do {
hProc32Module = CreateToolhelp32Snapshot(dwFlag, pID);
}
while ((hProc32Module == INVALID_HANDLE_VALUE) && (GetLastError() == ERROR_BAD_LENGTH));
if (hProc32Module == INVALID_HANDLE_VALUE) {
__debugbreak();
return false;
}
//Find the module for Kernel.dll and get the base address of it
hKernel32 = NULL;
MODULEENTRY32 entryModule = {0};
entryModule.dwSize = sizeof(MODULEENTRY32);
BOOL isGetModuleSuccess = Module32First(hProc32Module, &entryModule);
while (isGetModuleSuccess) {
if (_tcscmp(entryModule.szModule, KERNEL32_DLL)) {
hKernel32 = entryModule.hModule;
break;
}
isGetModuleSuccess = Module32Next(hProc32Module, &entryModule);
}
if (!hKernel32) {
__debugbreak();
CloseHandle(hProc32Module);
return false;
}
CloseHandle(hProc32Module);
....
}
答案 1 :(得分:0)
根据文档,当试图访问64位进程的32位进程调用CreateToolhelp32Snapshot()时,CreateToolhelp32Snapshot()仅 失败,并出现ERROR_PARTIAL_COPY:
如果指定的进程是64位进程,而调用者是32位进程,则此函数将失败,并且最后一个错误代码是ERROR_PARTIAL_COPY(299)。
这是很明显的错误,因为您可以从发布的摘录中推论得出。它在哪里说只有32位呼叫者尝试访问64位时,它仅以ERROR_PARTIAL_COPY (299)
失败?没有。
如果文档不是完整的文档,那么您可以正确地假设所陈述的行为是生成ERROR_PARTIAL_COPY
错误代码的唯一方法。很遗憾,文档不完整。
例如,如果使用CREATE_SUSPENDED
标志启动进程,则无论主机或目标应用程序的位数如何,在查询模块时,CreateToolhelp32Snapshot
API都会将错误代码设置为ERROR_PARTIAL_COPY
。我怀疑这是因为PebLdr
中的PEB
指针是NULL
。
基本上,任何阻止读取进程存储器(PEB
中的地址丢失,未映射的段等)都可能导致ERROR_PARTIAL_COPY
作为其描述状态:
ERROR_PARTIAL_COPY 299 (0x12B)
Only part of a ReadProcessMemory or WriteProcessMemory request was completed.