如何在 Windows x64 中按名称(在另一个进程中)查找模块基地址?
ProcessModuleCollection 仅找到:ntdll.dll wow64.dll wow64win.dll wow64cpu.dll
在哪里可以找到按名称搜索模块基本地址的函数示例(适用于 x32 和 x64 Windows 版本)?
如何在 Windows x64 中按名称(在另一个进程中)查找模块基地址?
ProcessModuleCollection 仅找到:ntdll.dll wow64.dll wow64win.dll wow64cpu.dll
在哪里可以找到按名称搜索模块基本地址的函数示例(适用于 x32 和 x64 Windows 版本)?
调用返回的ProcessModuleCollection
实例Process.Modules
有你需要的信息。前提是两个进程具有相同的位数。因此,如果目标进程是 32 位进程,请确保您的进程也是 32 位进程。如果目标进程是 64 位进程,那么请确保您的进程是 64 位进程。
从您在问题中包含的输出中,很明显产生该输出的场景是:
您只列举这少数几个模块的原因是(大概)它们是包含在 WOW64 模拟器下运行的 32 位进程中的 64 位模块,以及可执行模块。
您可能会想,您可以使用 Windows API 来枚举进程中具有不同位数的模块。但你不能。尝试使用CreateToolhelp32Snapshot
,Module32First
并Module32Next
产生与使用Process.Modules
. 这一点也不奇怪。在 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 位模块。
如果您只打算使用此代码针对 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 位平台上),此代码将获得进程模块的基地址就好了。
您必须记住的是,无论何时 enumerate 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;
}
}