DLL LoadCount on Windows 8

匿名 (未验证) 提交于 2019-12-03 02:20:02

问题:

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

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

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; } 

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

回答1:

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.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!