在 Windows 64 位上,我有一个 32 位进程可以读取其他 32 位进程的内存,并且我希望它也能够读取 64 位进程。
ReadProcessMemory 用于读取内存,但它有 32 位限制。有什么方法可以在 64 位进程上执行相当于 ReadProcessMemory 的操作吗?
我知道我可以编写一个 64 位进程并从 32 位进程启动它来完成工作,但我想知道是否有其他选项,这样我就不需要编写 64 位进程。
谢谢。
这是可能的。
例如,您可以参考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
)或调用旨在与 x64 进程配合使用的特定 x86 函数(即 NtWow64ReadVirtualMemory64
)来完成).
附注有人可能会说它没有记录,更像是黑客攻击 - 但它只是没有正式记录。例如,像
Unlocker
、ProcessHacker
或 ProcessExplorer
这样的软件会利用这些未记录的功能(以及更多),当然,这取决于您的决定。
库 wow64ext 似乎已经解决了这个问题并提供了一个功能
ReadProcessMemory64
Visual Studio 扩展 VSDebugTool 似乎使用这个库并适用于我的 64 位进程。
无论如何,这不应该是不可能的,因为(32 位)Visual Studio 调试器可以很好地处理 64 位调试器。
ReadProcessMemory 可以读取任何大小的内存,包括从 x86 进程读取 x64 进程。
您可以毫无问题地在 x86 程序中执行以下操作:
DWORD64 test = 0;
ReadProcessMemory(hProcess, (LPCVOID)lpBaseAddress, &test, sizeof(DWORD64), NULL);
这将允许您从 x86 进程取消引用 x64 指针。
没有办法解决这个问题。 一种解决方案是停止使用 WOW64 模拟器并编写 64 位进程。 另一种解决方案是使用 IPC 而不是直接内存读取。