2013-03-17 121 views
4

有誰知道LDR_MODULE.LoadCount在Windows 8上的位置?Windows 8上的DLL LoadCount 8

以下代碼始終打印6個引用計數:S 我使用RemoteDLLTool檢查了基本地址和所有其他信息是否正確。然而,LoadCount是錯誤的,因爲它總是6.我讀到,如果它是6,這意味着動態加載DLL,如果它是-1,它是靜態的。

也有一種方法,我可以迭代鏈表而無需不斷ReadProcessMemory?

我需要找出引用計數以某種方式..基本上下面的Windows 7上的代碼將告訴我多少次DLL加載..又稱爲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上執行相同操作的任何想法?

+0

如果您認爲閱讀DLL負載計數是您的解決方案,那麼您遇到的問題是什麼? – 2013-03-17 19:29:42

+0

哦,我只是想檢查一個DLL在一個進程中加載​​了多少次..我在做注入,我希望能夠調用LdrUnloadDll來卸載DLL的高計數。 – Brandon 2013-03-17 19:39:29

+2

嗯,釋放一個你沒有加載的DLL並不是最好的工程設計。 – 2013-03-17 22:37:09

回答

2

在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); 

(更新2016年12月3日)但請注意 - 建議在主線程中使用此功能。主要的問題是當你迭代dll的時候 - dll的也可以被釋放,然後在「while-loop」之後無限地釋放。

這樣的驚喜dll刪除也可以從主線程發生,如果側線程正在釋放dll,但是這種情況更少發生。

+1

從我的角度來看,這不是對問題的回答,也不是對其他問題的回答。 – user2120666 2016-11-24 19:33:15

+0

它現在看起來更好嗎? – TarmoPikaro 2016-11-24 22:00:07

+0

upvote怎麼樣? :-) – TarmoPikaro 2016-11-25 12:40:41