C++ Windows 8上的DLL加载计数
有人知道windows 8上LDR_MODULE.LoadCount的位置吗 以下代码始终为引用计数打印6:S 我用RemoteDLL工具检查了一下,基本地址和所有其他信息都是正确的。然而,LoadCount是错误的,因为它总是6。我读到,如果它是6,这意味着动态加载DLL,如果它是-1,它是静态的 还有没有一种方法可以在不必不断读取ProcessMemory的情况下迭代链表 我得想办法算出参考人数。。基本上,下面Windows 7上的代码会告诉我DLL加载了多少次。。aka指向DLL的引用计数C++ Windows 8上的DLL加载计数,c++,winapi,C++,Winapi,有人知道windows 8上LDR_MODULE.LoadCount的位置吗 以下代码始终为引用计数打印6:S 我用RemoteDLL工具检查了一下,基本地址和所有其他信息都是正确的。然而,LoadCount是错误的,因为它总是6。我读到,如果它是6,这意味着动态加载DLL,如果它是-1,它是静态的 还有没有一种方法可以在不必不断读取ProcessMemory的情况下迭代链表 我得想办法算出参考人数。。基本上,下面Windows 7上的代码会告诉我DLL加载了多少次。。aka指向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;
}
#包括
类型定义结构(LDR)模块
{
LoadOrderModuleList中的列表项;
在MemoryDermoduleList中列出条目;
InitializationOrderModuleList中的列表项;
PVOID基址;
PVOID入口点;
乌龙西泽图像;
UNICODE_字符串完整名称;
UNICODE_基于字符串的名称;
乌龙旗;
短负载计数;
短TlsIndex;
列表项HashTableEntry;
乌龙时间戳;
}LDR_模块,*PLDR_模块;
int GetModuleLoadCount()
{
DWORD-dwBytesRead=0;
进程基本信息PBI={0};
HANDLE ProcessHandle=GetCurrentProcess();
if(NT_SUCCESS(NtQueryInformationProcess(ProcessHandle、ProcessBasicInformation和PBI、sizeof(PBI)和dwBytesRead)))
{
产品环境足迹数据;
LDR_模块LDR模块;
PPEB_LDR_DATA pLdrData=nullptr;
PLDR_模块pLdrModule=nullptr;
char*LdrDataOffset=reinterpret_cast(PBI.PebBaseAddress)+offset(PEB,Ldr);
ReadProcessMemory(ProcessHandle、LdrDataOffset和pLdrData、sizeof(pLdrData)和DWByteRead);
ReadProcessMemory(ProcessHandle、pLdrData和LdrData、sizeof(LdrData)和DWByteRead);
LIST_ENTRY*Head=LdrData.InMemoryOrderModuleList.Flink;
列表\条目*下一步=标题;
做
{
LDR\u数据\u表格\u条目LdrEntry;
LDR_数据_表_条目*Base=包含_记录(Head、LDR_数据_表_条目、InMemoryOrderLinks);
if(ReadProcessMemory(ProcessHandle、Base和LdrEntry、sizeof(LdrEntry)和dwBytesRead))
{
char*pLdrModuleOffset=重新解释铸件(头部)-sizeof(列表项);
ReadProcessMemory(进程句柄、pLdrModuleOffset和pLdrModule、sizeof(pLdrModule)和DWByteRead);
ReadProcessMemory(ProcessHandle、pLdrModule和LdrModule、sizeof(LdrModule)和DWByteRead);
if(LdrEntry.DllBase)
{
std::cout在Windows 8.1上测试。不能保证这在较新的Windows上工作(例如,10,但是-根据文档,应该工作)
(更新3.12.2016)但是请注意-建议从主线程使用此函数。主要问题是当您迭代dll时-dll也可以被释放,之后“while loop”将无限长
如果副线程正在释放dll,这种意外的dll删除也可能发生在主线程中,但这种情况很少发生。如果您认为读取dll加载计数是解决方案,那么您遇到的问题是什么?哦,我只是想检查一个进程中加载了多少次dll..我正在进行注入,我希望能够调用LdrUnloadDll以卸载具有高计数的DLL。嗯,释放未加载的DLL不是最好的工程设计。您可能会考虑挂接LoadLibraryW/a(EX)调用,如果您试图检测进程何时加载库的次数过多。感谢您提供的代码,它在Windows 7上运行良好。我现在需要它来调试库的错误引用计数。在我看来,这既不能回答问题,也不能回答其他问题。它现在看起来更好了吗?
#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
// Someone reserved us, let's force us to shutdown.
while( GetModuleLoadCount( dll ) > 1 )
FreeLibrary(dll);
FreeLibraryAndExitThread(dll, 0);