这是可能的。
例如,您可以参考 tofucoder 的回答中的优秀示例。
另一个示例可以参考此链接。
关于它为什么有效,请查看此主题。
另一个示例可以在这里找到。
整个技巧就是调用64位版本的ReadProcessMemory函数。直观地说,从32位进程中调用它不是一个选项,但上面的链接解释了:x64版本的ntdll.dll
也作为Windows WOW64模拟器中32位进程的一部分加载。它有一个名为NtReadVirtualMemory
的函数,具有与ReadProcessMemory64
相同的原型:
__declspec(SPEC)BOOL __cdecl ReadProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead);
地址长度为64位,因此可以引用64位进程的整个虚拟地址空间。
您可能会想知道如何获取此函数的地址。这时ntdll.dll中的另一个函数
LdrGetProcedureAddress
就派上用场了。它的原型与
GetProcAddress
相同:
__declspec(SPEC)DWORD64 __cdecl GetProcAddress64(DWORD64 hModule, char* funcName);
我们需要检查x64
ntdll.dll
的导出目录,并手动找到该函数的入口。然后,我们可以获取任何其他函数的地址。
另一个问题尚未解决:如何获取x64
ntdll.dll
的起始地址?我们需要手动遍历我们进程的x64
PEB
结构并遍历已加载模块的列表 - 作为其中的一种变体。如何获取PEB地址?请参考上面的链接,不要在此帖子中过多详细信息。
所有这些都在第一个链接的示例中涵盖。
第二个和第三个链接提供了使用
NtReadVirtualMemory
和
NtWow64ReadVirtualMemory64
函数的替代方案(以及获取PEB地址的替代方法)。
总之,可以从x86进程与x64进程进行交互。可以通过直接调用x64版本的函数(从作为WOW64进程的一部分加载的x64
ntdll.dll
中)或调用特定的x86函数来完成与x64进程的工作(即
NtWow64ReadVirtualMemory64
)。
P.S.有人可能会说这是未记录的,更像是黑客行为 - 但它只是没有正式记录。例如,软件如
Unlocker
、
ProcessHacker
或
ProcessExplorer
利用了这些未记录的功能(以及许多其他功能),当然,由您决定。
LPCVOID
这样的指针最大为32位。无论您将目标64位地址存储在DWORD64
变量中,当强制转换为32位指针时,它都会被截断。因此,您无法使用32位版本的ReadProcessMemory()
从32位应用程序中读取超过0xFFFFFFFF的目标64位内存地址,因为它无法适合32位指针。 - Remy Lebeau