LoadCount DLL for Windows 8

Does anyone know where LDR_MODULE.LoadCount is located on Windows 8?

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

There is also a way that I can simply iterate over a linked list without having a constant ReadProcessMemory?

I need to somehow calculate the reference count. Basically, the code below in Windows 7 will tell me how many times a DLL loads. aka link refers to a 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 in Windows 8?

+4
source share
1 answer

Tested on Windows 8.1. It does not guarantee that this will work on newer windows (for example, 10, however - according to the documentation it should work)

 #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 

Uses for injection .dll:

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

(Update 12/03/2016) . Please note that it is recommended to use this function from the main thread. The main problem is that you iterate the dll - the dll can also be freed, after which the "while-loop" hangs endlessly.

This unexpected deletion of the dll can also occur from the main thread if the side thread releases the dll, but this is less common.

+2
source

All Articles