从外部进程在Windows x64中查找模块句柄

时间:2013-07-01 19:51:00

标签: c# 32bit-64bit

enter image description here如何在Windows x64中按名称(在另一个进程中)查找模块基址?

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

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

2 个答案:

答案 0 :(得分:3)

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

从您在问题中包含的输出中可以清楚地看出,产生该输出的方案是:

  1. 64位操作系统。
  2. 您的代码以64位进程执行。
  3. 目标进程是一个32位进程。
  4. 你只列举那些少数模块的原因(大概)是它们是WOW64仿真器下运行的32位进程中包含的64位模块,以及可执行模块。

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