如何检查dll的引用计数?如何知道dll的加载位置?

时间:2010-08-24 02:48:42

标签: c++ windows

如您所知,如果对LoadLibrary的调用指定DLL模块已映射到调用进程的地址空间,则该函数只返回DLL的句柄并递增模块的引用计数。

某处,我需要获取一个dll的引用计数。如何获取dll的引用计数?如何知道dll的加载位置?感谢。

7 个答案:

答案 0 :(得分:5)

我用Google搜索,发现这个article声称提供了答案。 对不起,我无能为力:

答案 1 :(得分:4)

如果它是非编程方式(感谢C.Johnson给出了这个观点),WinDBG可能会有所帮助

http://windbg.info/doc/1-common-cmds.html#10_modules

看看!dlls和它的变种。

  

!dll - 所有加载的模块都有加载   计数

编辑2:

如果您想知道从进程中加载​​所有DLL的位置,有两种方法:

一个。看一下命令

  

“bu kernel32!LoadLibraryExW”;作为/ mu   $ {/ v:MyAlias} poi(@ esp + 4); .if(   $ spat(\“$ {MyAlias} \”,\“ MYDLL \”)   != 0){kn; } .else {g}“”

在上面的网址

湾在WinDBG下运行该过程。 Debug-> Even Filter并选择“Load Module”并在“Execution”下将其设置为“Enabled”。在“继续”下,将其设置为“未处理”。

其中一个应该对你有所帮助。

答案 2 :(得分:1)

我不确定你是否完全理解LoadLibrary/FreeLibrary的工作方式。完成后调用FreeLibrary并减少加载时递增的引用计数。如果您的流程的其他部分仍在使用它,那可能不是您的担忧。

引用计数可能会告诉您已经“加载”了多少次,但无法确定是谁加载了它。

答案 3 :(得分:0)

此信息无法通过公共API afaik获得。你的情景是什么?运行AppVerifier将捕获您使用模块(或任何其他)句柄所犯的任何错误。

答案 4 :(得分:0)

您可以使用Module32First() / Module32Next()枚举已加载的模块,然后使用MODULEENTRY32.GlblcntUsage检查其引用计数。我不确定这是多么可靠。

答案 5 :(得分:0)

请在下面显示代码。 注意:我在Visual Studio 2010中编写了以下代码。

ng-app

For more info go to below url

答案 6 :(得分:0)

在Windows 8.1上测试。不保证这将适用于较新的窗口(例如10,但是 - 根据文档应该正常工作)

#include <winternl.h>                   //PROCESS_BASIC_INFORMATION


// warning C4996: 'GetVersionExW': was declared deprecated
#pragma warning (disable : 4996)
bool IsWindows8OrGreater()
{
    OSVERSIONINFO ovi = { 0 };
    ovi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );

    GetVersionEx(&ovi);
    if( (ovi.dwMajorVersion == 6 && ovi.dwMinorVersion >= 2) || ovi.dwMajorVersion > 6 )
        return true;

    return false;
} //IsWindows8OrGreater
#pragma warning (default : 4996)



bool ReadMem( void* addr, void* buf, int size )
{
    BOOL b = ReadProcessMemory( GetCurrentProcess(), addr, buf, size, nullptr );
    return b != FALSE;
}

#ifdef _WIN64
    #define BITNESS 1
#else
    #define BITNESS 0
#endif

typedef NTSTATUS (NTAPI *pfuncNtQueryInformationProcess)(HANDLE,PROCESSINFOCLASS,PVOID,ULONG,PULONG);

//
//  Queries for .dll module load count, returns 0 if fails.
//
int GetModuleLoadCount( HMODULE hDll )
{
    // Not supported by earlier versions of windows.
    if( !IsWindows8OrGreater() )
        return 0;

    PROCESS_BASIC_INFORMATION pbi = { 0 };

    HMODULE hNtDll = LoadLibraryA("ntdll.dll");
    if( !hNtDll )
        return 0;

    pfuncNtQueryInformationProcess pNtQueryInformationProcess = (pfuncNtQueryInformationProcess)GetProcAddress( hNtDll, "NtQueryInformationProcess");
    bool b = pNtQueryInformationProcess != nullptr;
    if( b ) b = NT_SUCCESS(pNtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof( pbi ), nullptr ));
    FreeLibrary(hNtDll);

    if( !b )
        return 0;

    char* LdrDataOffset = (char*)(pbi.PebBaseAddress) + offsetof(PEB,Ldr);
    char* addr;
    PEB_LDR_DATA LdrData;

    if( !ReadMem( LdrDataOffset, &addr, sizeof( void* ) ) || !ReadMem( addr, &LdrData, sizeof( LdrData ) ) ) 
        return 0;

    LIST_ENTRY* head = LdrData.InMemoryOrderModuleList.Flink;
    LIST_ENTRY* next = head;

    do {
        LDR_DATA_TABLE_ENTRY LdrEntry;
        LDR_DATA_TABLE_ENTRY* pLdrEntry = CONTAINING_RECORD( head, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks );

        if( !ReadMem( pLdrEntry , &LdrEntry, sizeof(LdrEntry) ) )
            return 0;

        if( LdrEntry.DllBase == (void*)hDll )
        {
            //  
            //  http://www.geoffchappell.com/studies/windows/win32/ntdll/structs/ldr_data_table_entry.htm
            //
            int offDdagNode = (0x14 - BITNESS) * sizeof(void*);   // See offset on LDR_DDAG_NODE *DdagNode;

            ULONG count = 0;
            char* addrDdagNode = ((char*)pLdrEntry) + offDdagNode;

            //
            //  http://www.geoffchappell.com/studies/windows/win32/ntdll/structs/ldr_ddag_node.htm
            //  See offset on ULONG LoadCount;
            //
            if( !ReadMem(addrDdagNode, &addr, sizeof(void*) ) || !ReadMem( addr + 3 * sizeof(void*), &count, sizeof(count) ) )
                return 0;

            return (int)count;
        } //if

        head = LdrEntry.InMemoryOrderLinks.Flink;
    }while( head != next );

    return 0;
} //GetModuleLoadCount

注入.dll的用法:

// Someone reserved us, let's force us to shutdown.
while( GetModuleLoadCount( dll ) > 1 )
    FreeLibrary(dll);

FreeLibraryAndExitThread(dll, 0);