DLL LoadCount on Windows 8

前端 未结 1 1498
野性不改
野性不改 2021-01-03 06:20

Does anyone know where LDR_MODULE.LoadCount is on windows 8?

The following code always prints 6 for the reference count :S I checked with a RemoteDLLTool and the bas

相关标签:
1条回答
  • 2021-01-03 06:35

    Tested on Windows 8.1. Will not guarantee that this will work on newer windows (e.g. 10, however - according to documentation should be working)

    #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
    

    Usage for injected .dll's:

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

    (Update 3.12.2016) Please notice however - that it's recommended to use this function from main thread. The main problem is when you're iterating dll's - dll's can be freed as well, after which "while-loop" hungs infinitely.

    Such surprise dll removal can happen also from main thread as well, if side thread is freeing dll, but this happens more rarely.

    0 讨论(0)
提交回复
热议问题