EnumProcessModulesEx 和 CreateToolhelp32Snapshot 失败 - 无论是 32 位还是 64 位

2024-03-10

Edit:

这个问题的答案在这里:

https://stackoverflow.com/a/27317947/996540 https://stackoverflow.com/a/27317947/996540

在 msvc 中创建项目时,默认启用选项 /DYNAMICBASE 现在。由于ASLR(地址空间布局随机化,自Windows Vista起), 每次运行 exe 时,它​​的加载地址都是随机的。

我最近在做DLL注入工作,所以我对它做了一些研究 谷歌,并阅读了一些项目。获取一个的加载地址(基地址) exe很重要。

似乎有两个简单的 API 可以做到这一点:EnumProcessModulesEx 和 创建Toolhelp32Snapshot。但我从来没有成功过。

这是代码示例:

void TestEnumProcessModulesEx(const char* app)
{
    std::cout << "Begin TestEnumProcessModulesEx(" << mybit() << ")" << std::endl;

    STARTUPINFOA startupInfo = {0};
    startupInfo.cb = sizeof(startupInfo);
    PROCESS_INFORMATION processInformation = {0};

    if (CreateProcessA(app, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInformation))
    {
        std::vector<HMODULE> buf(128);
        DWORD needed = 0;
        for (;;) {
            if (EnumProcessModulesEx(processInformation.hProcess, &buf[0], DWORD(buf.size()*sizeof(HMODULE)), &needed, LIST_MODULES_ALL) == FALSE) {
                DWORD ec = GetLastError();
                std::cout << "GetLastError() = " << ec << std::endl;
                break;
            }
            else if (needed <= buf.size() * sizeof(HMODULE)) {
                break;
            }
            else {
                const size_t oldSize = buf.size();
                buf.resize(oldSize * 2);
            }
        }
        ResumeThread(processInformation.hThread);
        WaitForSingleObject(processInformation.hProcess, INFINITE);
    }

    std::cout << "End TestEnumProcessModulesEx(" << mybit() << ")" << std::endl;
}

为了减少这个问题的长度,完整的代码 - 包括 CreateToolhelp32Snapshot 的测试代码 - 此处未列出,但您可以获取它 从:

https://dl.dropboxusercontent.com/u/235920/enum_proc_mods_sample.7z https://dl.dropboxusercontent.com/u/235920/enum_proc_mods_sample.7z or https://www.mediafire.com/?cry3pnra8392099 https://www.mediafire.com/?cry3pnra8392099

“如果从 WOW64 上运行的 32 位应用程序调用此函数,它可以 仅枚举 32 位进程的模块。如果进程是 64 位 过程中,该函数失败,最后的错误代码为 ERROR_PARTIAL_COPY (299)。”- 来自 MSDN。

这是关于这个问题的博客文章:http://winprogger.com/getmodulefilenameex-enumprocessmodulesex-failures-in-wow64/ http://winprogger.com/getmodulefilenameex-enumprocessmodulesex-failures-in-wow64/

不幸的是,这没有意义,因为无论指定什么 进程是32位或64位,失败并显示299;无论调用者进程是什么 32 位或 64 位,失败并显示 299。

这是我的示例的输出:

Begin TestEnumProcessModulesEx(32bit)
GetLastError() = 299
hello world 32bit
End TestEnumProcessModulesEx(32bit)

Begin TestEnumProcessModulesEx(32bit)
GetLastError() = 299
hello world 64bit
End TestEnumProcessModulesEx(32bit)

Begin TestEnumProcessModulesEx(64bit)
GetLastError() = 299
hello world 32bit
End TestEnumProcessModulesEx(64bit)

Begin TestEnumProcessModulesEx(64bit)
GetLastError() = 299
hello world 64bit
End TestEnumProcessModulesEx(64bit)

如您所见,任何组合都会失败。

我的操作系统是Windows 7 64位专业版,我的编译器是VS2013。

那么,我能做什么呢?


我不知道 EnumProcessModulesEx 的不成功和 CreateToolhelp32Snapshot,这个问题就留给专家吧。

我的目标是获取子进程的加载地址(基地址),找到 入口点并对其进行修补 - 修补入口点的原因如下:https://opcode0x90.wordpress.com/2011/01/15/injecting-dll-into-process-on-load/ https://opcode0x90.wordpress.com/2011/01/15/injecting-dll-into-process-on-load/

由于DLL注入是我的主要目的,所以我必须重新考虑这一点 问题。我会使用“CreateRemoteThread 和 LoadLibrary 技术”http://www.codeproject.com/Articles/4610/Three-Ways-to-Inject-Your-Code-into-Another-Proces#section_2 http://www.codeproject.com/Articles/4610/Three-Ways-to-Inject-Your-Code-into-Another-Proces#section_2进行 DLL 注入(事实上 ASLR 并不是这项技术的障碍), 虽然DLLMain有这么多的限制http://msdn.microsoft.com/en-us/library/windows/desktop/dn633971%28v=vs.85%29.aspx http://msdn.microsoft.com/en-us/library/windows/desktop/dn633971%28v=vs.85%29.aspx,但是做一点工作就可以了:使用以下命令查找 exe 的基地址 GetModuleHandleA(NULL),将返回的HMODULE保存到共享内存中, 接下来,调用者进程读取共享内存并获取 HMODULE。 同步机制当然是必要的。

所以,答案是IPC。 (顺便说一句,并非所有 IPC 机制在 DL​​LMain 中都是安全的)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

EnumProcessModulesEx 和 CreateToolhelp32Snapshot 失败 - 无论是 32 位还是 64 位 的相关文章

随机推荐