Windows 8上的DLL LoadCount [英] DLL LoadCount on Windows 8

查看:77
本文介绍了Windows 8上的DLL LoadCount的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人知道Windows 8上LDR_MODULE.LoadCount在哪里吗?

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

以下代码始终打印6作为参考计数:S我用RemoteDLLTool和基地址检查了所有其他信息是否正确.但是,LoadCount始终是6,这是错误的.我读到,如果它是6,则意味着DLL是动态加载的;如果它是-1,则它是静态的.

The following code always prints 6 for the reference count :S I checked with a RemoteDLLTool and the baseaddress and all other information is correct. However, LoadCount is wrong as it is always 6. I read that if it is 6, it means the DLL is loaded dynamically and if it is -1, it is static.

还有没有一种方法可以让我迭代链接列表,而不必不断读取ReadProcessMemory?

Also is there a way I can just iterate the linked list without having to constantly ReadProcessMemory?

我需要以某种方式弄清楚引用计数..基本上,Windows 7上的以下代码将告诉我DLL被加载了多少次..也就是DLL的引用计数.

I need to figure out the reference count somehow.. Basically the code below on Windows 7 will tell me how many times a DLL is loaded.. aka the reference count to the DLL.

#include <winternl.h>

typedef struct _LDR_MODULE
{
    LIST_ENTRY              InLoadOrderModuleList;
    LIST_ENTRY              InMemoryOrderModuleList;
    LIST_ENTRY              InInitializationOrderModuleList;
    PVOID                   BaseAddress;
    PVOID                   EntryPoint;
    ULONG                   SizeOfImage;
    UNICODE_STRING          FullDllName;
    UNICODE_STRING          BaseDllName;
    ULONG                   Flags;
    SHORT                   LoadCount;
    SHORT                   TlsIndex;
    LIST_ENTRY              HashTableEntry;
    ULONG                   TimeDateStamp;
} LDR_MODULE, *PLDR_MODULE;

int GetModuleLoadCount()
{
    DWORD dwBytesRead = 0;
    PROCESS_BASIC_INFORMATION PBI = {0};
    HANDLE ProcessHandle = GetCurrentProcess();

    if (NT_SUCCESS(NtQueryInformationProcess(ProcessHandle, ProcessBasicInformation, &PBI, sizeof(PBI), &dwBytesRead)))
    {
        PEB_LDR_DATA LdrData;
        LDR_MODULE LdrModule;
        PPEB_LDR_DATA pLdrData = nullptr;
        PLDR_MODULE pLdrModule = nullptr;

        char* LdrDataOffset = reinterpret_cast<char*>(PBI.PebBaseAddress) + offsetof(PEB, Ldr);
        ReadProcessMemory(ProcessHandle, LdrDataOffset, &pLdrData, sizeof(pLdrData), &dwBytesRead);
        ReadProcessMemory(ProcessHandle, pLdrData, &LdrData, sizeof(LdrData), &dwBytesRead);

        LIST_ENTRY* Head = LdrData.InMemoryOrderModuleList.Flink;
        LIST_ENTRY* Next = Head;

        do
        {
            LDR_DATA_TABLE_ENTRY LdrEntry;
            LDR_DATA_TABLE_ENTRY* Base = CONTAINING_RECORD(Head, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);

            if (ReadProcessMemory(ProcessHandle, Base, &LdrEntry, sizeof(LdrEntry), &dwBytesRead))
            {
                char* pLdrModuleOffset = reinterpret_cast<char*>(Head) - sizeof(LIST_ENTRY);
                ReadProcessMemory(ProcessHandle, pLdrModuleOffset, &pLdrModule, sizeof(pLdrModule), &dwBytesRead);
                ReadProcessMemory(ProcessHandle, pLdrModule, &LdrModule, sizeof(LdrModule), &dwBytesRead);

                if (LdrEntry.DllBase)
                {
                    std::cout<<"BaseAddress:     "<< LdrModule.BaseAddress<<std::endl;
                    std::cout<<"Reference Count: "<< LdrModule.LoadCount<<std::endl;
                }

                Head = LdrEntry.InMemoryOrderLinks.Flink;
            }
        }
        while (Head != Next);
    }
    CloseHandle(ProcessHandle);
    return 0;
}

关于如何在Windows 8上执行相同操作的任何想法?

Any ideas on how to do the same on Windows 8?

推荐答案

在Windows 8.1上进行了测试.无法保证此功能将在较新的Windows上运行(例如,不过10个-根据文档,应该可以正常工作)

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

用于注入的.dll的用途:

Usage for injected .dll's:

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

FreeLibraryAndExitThread(dll, 0);

(2016年12月31日更新)但是请注意-建议从主线程使用此功能.主要问题是当您迭代dll时-DLL也可以释放,此后无限循环挂起"while-loop".

(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.

如果侧线程正在释放dll,那么也可能从主线程中发生这种令人惊讶的dll删除,但是这种情况很少发生.

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

这篇关于Windows 8上的DLL LoadCount的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆