c++ - 如何检测使用 LoadLibraryEx 加载的模块

标签 c++ .net process clr

我需要使用类似 GetModuleHandle 的 Windows 函数或 GetModuleFileName查明是否在执行我的代码的同一进程中加载​​了特定的 dll。

我正在寻找的一个模块是 System.Windows.Forms.dll,但即使它在进程中加载​​... ProcessEx showing WindowsForms dll (在这里您可以使用 Process Explorer 查看它)

GetModuleHandle 仍然找不到它!

    HMODULE modHandle = GetModuleHandle(L"System.Windows.Forms.dll");

GetModuleHandle fails

GetLastError() 返回 ERROR_MOD_NOT_FOUND

If the function succeeds, the return value is a handle to the specified module. If the function fails, the return value is NULL.

我认为这可能与 CLR 加载这些 dll 的方式有关。我在 LoadLibraryEx 上看到一条注释如果使用 LOAD_LIBRARY_AS_DATAFILE 标志,则:

If this value is used, the system maps the file into the calling process's virtual address space as if it were a data file. Nothing is done to execute or prepare to execute the mapped file. Therefore, you cannot call functions like GetModuleFileName, GetModuleHandle or GetProcAddress with this DLL.

也许这是我的问题,但无论原因如何 - 有谁知道使用 native /c++ 代码在进程中查找托管 DotNet dll 的方法吗?

谢谢!

编辑: 根据 Castorix 在评论中的建议,我尝试使用 EnumProcessModules:

    HMODULE modules[100];
    void* hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, GetCurrentProcessId());
    if (hProcess)
    {
        DWORD bytesNeeded;
        BOOL rc = EnumProcessModules(hProcess, modules, sizeof(modules), &bytesNeeded);
        if (rc)
        {
            int count = (int)(bytesNeeded / sizeof(HMODULE));
            for (int i = 0; i < count; i++)
            {
                wchar_t moduleName[260];
                GetModuleFileName(modules[i], moduleName, 260);
            }
        }
    }
    CloseHandle(hProcess);

这段代码找到了很多模块,但没有找到 System.Windows.Forms.dll enter image description here

最佳答案

好的,这是对答案的尝试(或者真的只是一个太长的评论,抱歉)。

就个人而言,我从未在 Process Explorer Pane 中看到托管的 .NET DLL,但可能没有认真/经常地查看。但是,我能(而且总是能)看到的是 NGENed 图像 (*.ni.dll)。

enter image description here

另请注意此处存在 System.Data.dll,它不是 NGENed,而是混合模式程序集,包含 native 代码和托管代码。

因此可以得出结论,您在这里只能看到 NGENed 和混合模式“程序集”,因为它们仍然由 LoadLibraryLoadLibraryEx 加载。

另请注意我的评论,我将其复制在这里以便于访问:

I think the CLR does not use LoadLibrary, which would explain why you cannot "see" them using the APIs you described. In fact, CLR 4 Does Not Use LoadLibrary to Load Assemblies is a blog entry that is relevant. You could always check the sources (CoreCLR, but shouldn't matter), about how it is done in particular. I have no really good place, but you could start here and then go from it. Use the ICorDebug interface instead.

以下是上面链接的博客条目中的一些相关引述:

You may be asking yourself: …who cares? Well, first of all it’s good to know. I haven’t noticed a public service announcement to the above. It is an implementation detail, however—CLR assemblies are not even guaranteed to be implemented using files, not to mention DLL files in a specific format that are loaded using the LoadLibrary Win32 API.

However, there are several tools and scenarios which have come to rely on the fact the CLR loads assemblies using LoadLibrary. For example, up to CLR 4, if you wanted to know which .NET assemblies were loaded in your process, a fairly reliable heuristic would be to fire up Sysinternals Process Explorer and look at the DLLs view of a given process. This doesn’t work for CLR 4, as you can see here:

坦率地说,我不知道 Process Explorer 如何设法在您的案例中显示程序集(不是 NGENed 也不是混合模式)- appart from you are watching CLR2 process。但是,请注意,PE 不仅使用 Win32 API。它还使用 WMI,并且可能还直接使用 CLR 来获取更多信息。例如,“Process Properties/.NET Assemblies”和“Process Properties/.NET Performance”选项卡最有可能分别使用 ICorDebug/ICorProfile 和性能计数器/ETW。

您可能还需要使用这些接口(interface)中的一个,或者来自 unmanaged Debugging API 的其他接口(interface)或 unmanaged API一般而言。

无论是什么,出于上述原因,我认为 EnumProcessModules 等不会让您到达那里。

关于c++ - 如何检测使用 LoadLibraryEx 加载的模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56906157/

相关文章:

c++ - 带有 do while 函数的无限循环

sql - SQL Server 中的having 上的列名无效

java - 如何使用 ProcessBuilder 设置工作目录

windows - python : How to pass non-ASCII file names to Popen on Windows?

c - 确定进程是否已死 - 通过 PID

c++ - 多态指针的typeid?

c++ - 二进制快速排序起始位位置

c# - 接收 json 作为字符串始终为 null

c# - 反序列化动态 JSON 对象

c++ - 表达式必须是使用模板类可修改的左值