如何在Windows x64中按名称(在另一个进程中)查找模块基址?
ProcessModuleCollection仅查找:ntdll.dll wow64.dll wow64win.dll wow64cpu.dll
哪里可以找到按名称搜索模块库地址的功能示例(适用于x32和x64 Windows版本)?
答案 0 :(得分:3)
通过调用ProcessModuleCollection
返回的Process.Modules
实例包含您需要的信息。只要两个进程具有相同的位数。因此,如果目标进程是32位进程,请确保您的进程也是32位进程。如果目标进程是64位进程,那么请确保您的进程是64位进程。
从您在问题中包含的输出中可以清楚地看出,产生该输出的方案是:
你只列举那些少数模块的原因(大概)是它们是WOW64仿真器下运行的32位进程中包含的64位模块,以及可执行模块。
您可能会想到您可以使用Windows API枚举具有不同位数的进程中的模块。但你不能。尝试使用CreateToolhelp32Snapshot
,Module32First
和Module32Next
会产生与使用Process.Modules
的C#代码相同的结果。这真的不奇怪。在Win32中实现的.net将调用为此任务设计的本机Win32 API,这是完全合理的。
您的解决方案是确保对Process.Modules
的调用来自32位进程。如果需要能够同时针对32位和64位进程,则需要使用一些不同位的辅助进程。
<强>更新强>
Ben Voigt将我从Debug Help API指向EnumerateLoadedModules64。我承认没有意识到这一点。但是,它似乎与工具帮助API具有相同的位数限制。
最后,还有EnumProcessModulesEx可以枚举64位进程的32位模块。如果你传递LIST_MODULES_32BIT
,那么你确实可以从一个64位的调用进程中提取加载到外部32位进程的32位模块。
答案 1 :(得分:2)
如果您只是使用此代码定位32位进程,以下内容应该可以正常使用:
/// <summary>
/// Gets the base address of a process' module with the specified name.
/// </summary>
/// <param name="moduleName">Name of the module.</param>
/// <returns>The module BaseAddress if successful; otherwise, IntPtr.Zero.</returns>
public IntPtr GetModuleBaseAddress(string moduleName)
{
var module = Memory.Process.Modules.Cast<ProcessModule>().FirstOrDefault(m => m.ModuleName == moduleName);
return module != null ? module.BaseAddress : IntPtr.Zero;
}
其中Memory.Process只是一个System.Diagnostics.Process
对象。我不确定它是否适用于实际的x64进程,但只要你的目标是32位进程(即使在64位平台上),这段代码就可以获得进程模块的基本地址。
您必须记住的是,无论何时枚举ProcessModules
,您都只能获得被调用者体系结构中的模型(x86或x64)。如果您正在运行x86进程并且在另一个进程上调用Process.Modules
,那么您将只看到该进程的x86模块。这同样适用于x64。您可能需要找到解决方法或为x86和x64编译项目,并为每个应用程序使用正确的项目。
编辑:我在GameDeception上找到了以下可能对您有用的原生代码:
unsigned long ProcessDevice::getModuleAddress(DWORD proc, const char *modname)
{
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, proc);
if( snapshot == INVALID_HANDLE_VALUE )
{
return 0;
}
MODULEENTRY32 mod;
mod.dwSize = sizeof(MODULEENTRY32);
if( Module32First(snapshot, &mod) )
{
if( strcmp(mod.szModule, modname) == 0 )
return (unsigned long)mod.modBaseAddr;
while( Module32Next(snapshot, &mod) )
{
if( strcmp(mod.szModule, modname) == 0 )
return (unsigned long)mod.modBaseAddr;
}
/* Failed to find the module */
return 0;
}
else
{
/* Failed to read any module info */
return 0;
}
}