从32位应用程序中读取64位进程的进程内存是否可能?

10
在 Windows 64 位系统上,我有一个 32 位进程读取其他 32 位进程的内存,并希望能够读取 64 位进程的内存。
使用 ReadProcessMemory 来读取内存,但它有 32 位限制。有没有办法在 64 位进程上执行类似于 ReadProcessMemory 的操作?
我知道我可以编写一个 64 位进程并从我的 32 位进程中启动它来完成工作,但我想知道是否还有其他选项,以避免编写 64 位进程。
谢谢。
5个回答

15

这是可能的。

例如,您可以参考 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地址?请参考上面的链接,不要在此帖子中过多详细信息。
所有这些都在第一个链接的示例中涵盖。 第二个和第三个链接提供了使用NtReadVirtualMemoryNtWow64ReadVirtualMemory64函数的替代方案(以及获取PEB地址的替代方法)。
总之,可以从x86进程与x64进程进行交互。可以通过直接调用x64版本的函数(从作为WOW64进程的一部分加载的x64 ntdll.dll中)或调用特定的x86函数来完成与x64进程的工作(即NtWow64ReadVirtualMemory64)。
P.S.有人可能会说这是未记录的,更像是黑客行为 - 但它只是没有正式记录。例如,软件如UnlockerProcessHackerProcessExplorer利用了这些未记录的功能(以及许多其他功能),当然,由您决定。

3
图书馆wow64ext似乎已经解决了这个问题,并提供了一个名为ReadProcessMemory64的函数。Visual Studio扩展VSDebugTool似乎使用了这个库,并且对于我来说可以使用64位进程。

无论如何,这不应该是不可能的,因为(32位)Visual Studio调试器非常好地处理64位调试对象。



-4

ReadProcessMemory函数可以读取任何大小的内存,包括从x86进程读取x64进程。

在x86程序中,您可以毫不费力地执行以下操作:

DWORD64 test = 0;
ReadProcessMemory(hProcess, (LPCVOID)lpBaseAddress, &test, sizeof(DWORD64), NULL);

这将允许您从x86进程中取消引用x64指针。


nSize指定要从目标进程中读取的字节数,而不是指针的大小,请参阅https://msdn.microsoft.com/en-us/library/windows/desktop/ms680553(v=vs.85).aspx。 - hillu
@hillu 我从来没有说过那样的话。我经常在x86和x64进程之间进行读写,并且从未遇到问题。 - Pierre Ciholas
2
在32位应用程序中,像LPCVOID这样的指针最大为32位。无论您将目标64位地址存储在DWORD64变量中,当强制转换为32位指针时,它都会被截断。因此,您无法使用32位版本的ReadProcessMemory()从32位应用程序中读取超过0xFFFFFFFF的目标64位内存地址,因为它无法适合32位指针。 - Remy Lebeau

-5

这是无法避免的。一种解决方案是停止使用WOW64模拟器并编写64位进程。另一种解决方案是使用IPC而不是直接内存读取。


你可以编写一个驱动程序来实现它,但考虑到其他选择,这是过度设计了。只需编写一个64位的辅助进程即可。 - Luke
实际上,可以使用WOW64系统的一种方法。 https://github.com/rwfpl/rewolf-wow64ext - Mecanik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接