R3下枚舉進程DLL的幾種方法

一、Module32FirstModule32Next

void Enum1()
{
	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
	if (hSnapshot == INVALID_HANDLE_VALUE)
		return;

	MODULEENTRY32W module{ 0 };
	module.dwSize = sizeof(module);
	BOOL bFound = Module32FirstW(hSnapshot, &module);
	while (bFound)
	{
		std::wcout << module.szExePath << std::endl;
		bFound = Module32Next(hSnapshot, &module);
	}

	CloseHandle(hSnapshot);
}

函數底層是通過搜索PEB.Ldr.InLoadOrderModuleList鏈來找到模塊信息的。

二、EnumProcessModules

void Enum2()
{
	HANDLE hProcess = GetCurrentProcess();
	HMODULE hModules[1024];
	DWORD cbNeeded = 0;
	if (EnumProcessModules(hProcess, hModules, sizeof(hModules), &cbNeeded))
	{
		for (auto i = 0u; i < (cbNeeded / sizeof(HMODULE)); i++)
		{
			WCHAR szFileName[MAX_PATH];
			if (GetModuleFileNameExW(hProcess, hModules[i], szFileName, _countof(szFileName)))
			{
				std::wcout << szFileName << std::endl;
			}
		}
	}
}

函數底層是通過搜索PEB.Ldr.InMemoryOrderModuleList鏈來找到模塊信息的。

三、VirtualQuery

void Enum3()
{
	SYSTEM_INFO SystemInfo;
	GetSystemInfo(&SystemInfo);
	ULONG_PTR ulStart = (ULONG_PTR)SystemInfo.lpMinimumApplicationAddress;
	ULONG_PTR ulEnd = (ULONG_PTR)SystemInfo.lpMaximumApplicationAddress;

	ULONG_PTR ulBaseAddress = ulStart;
	MEMORY_BASIC_INFORMATION info{ 0 };
	while (ulBaseAddress <= ulEnd)
	{
		if (VirtualQuery((PVOID)ulBaseAddress, &info, sizeof(info)) == sizeof(info))
		{
			if ((info.Type == MEM_IMAGE) && (info.AllocationBase == info.BaseAddress))
			{
				WCHAR szFileName[MAX_PATH];
				if (GetModuleFileNameW((HMODULE)info.BaseAddress, szFileName, _countof(szFileName)) > 0)
				{
					std::wcout << szFileName << std::endl;
				}
			}
		}
		ulBaseAddress += 0x10000;
	}
}

這個就是使用暴力搜索內存頁的方法來定位模塊信息,不依賴LDR鏈,VirtualQuery內部又會調用NtQueryVirtualMemory來取得內存頁信息。這個方法效率低下,特別是在64位進程中,由於內存地址範圍太大,需要很長時間去遍歷完整個內存,所以一般情況下不使用這個方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章