0

在此处输入图像描述如何在 Windows x64 中按名称(在另一个进程中)查找模块基地址?

ProcessModuleCollection 仅找到:ntdll.dll wow64.dll wow64win.dll wow64cpu.dll

在哪里可以找到按名称搜索模块基本地址的函数示例(适用于 x32 和 x64 Windows 版本)?

4

2 回答 2

3

调用返回的ProcessModuleCollection实例Process.Modules有你需要的信息。前提是两个进程具有相同的位数。因此,如果目标进程是 32 位进程,请确保您的进程也是 32 位进程。如果目标进程是 64 位进程,那么请确保您的进程是 64 位进程。

从您在问题中包含的输出中,很明显产生该输出的场景是:

  1. 一个 64 位操作系统。
  2. 您的代码在 64 位进程中执行。
  3. 目标进程是 32 位进程。

您只列举这少数几个模块的原因是(大概)它们是包含在 WOW64 模拟器下运行的 32 位进程中的 64 位模块,以及可执行模块。

您可能会想,您可以使用 Windows API 来枚举进程中具有不同位数的模块。但你不能。尝试使用CreateToolhelp32SnapshotModule32FirstModule32Next产生与使用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 位模块。

于 2013-07-01T20:40:46.643 回答
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 位平台上),此代码将获得进程模块的基地址就好了。

您必须记住的是,无论何时 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;
    }
}
于 2013-07-01T20:37:12.683 回答