Windows 是否可以从32位应用程序读取64位进程的进程内存?
在windows 64位上,我有一个32位进程可以读取其他32位进程的内存,我希望它也能够读取64位进程 ReadProcessMemory用于读取内存,但有32位限制。有没有办法在64位进程上实现ReadProcessMemory的等效功能 我知道我可以写一个64位进程,然后从我的32位进程启动它来完成这项工作,但我想知道是否还有其他选择,这样我就不需要写一个64位进程了Windows 是否可以从32位应用程序读取64位进程的进程内存?,windows,32bit-64bit,Windows,32bit 64bit,在windows 64位上,我有一个32位进程可以读取其他32位进程的内存,我希望它也能够读取64位进程 ReadProcessMemory用于读取内存,但有32位限制。有没有办法在64位进程上实现ReadProcessMemory的等效功能 我知道我可以写一个64位进程,然后从我的32位进程启动它来完成这项工作,但我想知道是否还有其他选择,这样我就不需要写一个64位进程了 谢谢。这是无法回避的。一种解决方案是停止使用WOW64仿真器并编写一个64位进程。另一种解决方案是使用IPC而不是直接读取
谢谢。这是无法回避的。一种解决方案是停止使用WOW64仿真器并编写一个64位进程。另一种解决方案是使用IPC而不是直接读取内存。否:该库似乎已经解决了这个问题,并提供了一个函数
ReadProcessMemory64
Visual Studio扩展似乎使用了该库,并为我提供了64位进程
无论如何,这不应该是不可能的,因为(32位)Visual Studio调试器可以很好地处理64位调试对象。这是可能的
例如,您可以参考tofucoder答案中的优秀样本。
有关更多示例,请参考
请解释一下为什么它真的有效
可能会找到另一个样本
整个技巧是调用64位版本的ReadProcessMemory函数。直观地说,它不是32位进程的选项,但是上面的链接解释了:x64版本的ntdll.dll
也作为32位进程的一部分加载到Windows WOW64 emulator中。它有一个名为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);
我们将检查x64ntdll.dll的导出目录,并手动找到此函数的条目。然后我们可以获得任何其他函数的地址
到目前为止还没有发现另一个问题:如何获取x64ntdll.dll的起始地址?我们需要手动遍历流程的x64PEB
结构,并遍历加载的模块列表——作为变体之一。如何获得PEB地址?请参考上面的链接,不要用太多的细节来淹没这篇文章
所有这些都包含在第一个链接的示例中。
第二和第三个链接中提供了使用NtReadVirtualMemory
和NTWOW64READVirtualMemory 64
功能的替代变体(以及获取PEB地址的替代方法)
概要:可以从x86 one与x64进程交互。可以通过直接调用x64版本的函数(从作为WOW64进程一部分加载的x64ntdll.dll
)或调用特定的x86函数(即NtWow64ReadVirtualMemory64
)来完成
另外,有人可能会说这是没有文件记录的,更像是黑客——但它只是没有正式的文件记录。例如,像Unlocker
、ProcessHacker
或ProcessExplorer
这样的软件利用了这些未记录的功能(以及更多),当然,这取决于您的决定。ReadProcessMemory可以读取任何大小的内存,包括从x86进程读取x64进程
在x86程序中,您可以毫无问题地执行以下操作:
DWORD64 test = 0;
ReadProcessMemory(hProcess, (LPCVOID)lpBaseAddress, &test, sizeof(DWORD64), NULL);
这将允许您从x86进程中取消对x64指针的引用。您可以编写执行此操作的驱动程序,但考虑到其他替代方案,这样做有些过头了。只需编写一个64位助手进程。实际上,有一种方法是使用WOW64系统。nSize指定要从目标进程读取的字节数,而不是指针的大小,参见@hillu I从未说过这一点。在32位应用程序中,像LPCVOID
这样的指针的最大大小为32位。如果将目标64位地址存储在DWORD64
变量中并不重要,当类型转换为32位指针时,它将被截断。因此,您无法使用32位版本的ReadProcessMemory()
,从32位应用程序中读取高于0xFFFFFFFF的64位目标内存地址,因为它不适合32位指针。