自用 x86 GetProcAddress + GetModuleHandle

hambaga發表於2021-01-01

寫專案時自己實現了這兩個函式,記錄下來以後方便複習。

// 從PEB的_PEB_LDR_DATA裡獲取已載入模組的控制程式碼
HMODULE GetLoadedModuleW(LPCWSTR lpModuleName)
{
	typedef struct _UNICODE_STRING {
		USHORT Length;
		USHORT MaximumLength;
		PWSTR  Buffer;
	} UNICODE_STRING, *PUNICODE_STRING;

	typedef struct _PEB_LDR_DATA
	{
		DWORD Length;
		bool Initialized;
		PVOID SsHandle;
		LIST_ENTRY InLoadOrderModuleList;
		LIST_ENTRY InMemoryOrderModuleList;
		LIST_ENTRY InInitializationOrderModuleList;
	} PEB_LDR_DATA, *PPEB_LDR_DATA;

	typedef struct _LDR_DATA_TABLE_ENTRY
	{
		LIST_ENTRY InLoadOrderLinks;
		LIST_ENTRY InMemoryOrderLinks;
		LIST_ENTRY InInitializationOrderLinks;
		PVOID DllBase;
		PVOID EntryPoint;
		UINT32 SizeOfImage;
		UNICODE_STRING FullDllName;
		UNICODE_STRING BaseDllName;
		UINT32 Flags;
		USHORT LoadCount;
		USHORT TlsIndex;
		LIST_ENTRY HashLinks;
		PVOID SectionPointer;
		UINT32 CheckSum;
		UINT32 TimeDateStamp;
		PVOID LoadedImports;
		PVOID EntryPointActivationContext;
		PVOID PatchInformation;
	} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

	PPEB_LDR_DATA pLDR = NULL;
	PLDR_DATA_TABLE_ENTRY pLdteHead;
	PLDR_DATA_TABLE_ENTRY pLdteCur;
	BOOL bEqual = FALSE;
	DWORD StringMinLen = 0;
	HMODULE hModule = NULL;

	//pLDR = (PPEB_LDR_DATA)(__readfsdword(0x30) + 0x0C);
	__asm
	{
		mov eax, fs: [0x30] ; // PEB
		mov eax, [eax + 0x0C]; // PEB->LDR
		mov pLDR, eax;
	}

	// 如果是NULL,直接返回主模組控制程式碼(第一個模組)
	if (lpModuleName == NULL)
	{
		__asm
		{
			mov eax, fs: [0x30] ;
			mov eax, [eax + 0x08];
			mov hModule, eax;
		}
		return hModule;
	}

	pLdteHead = (PLDR_DATA_TABLE_ENTRY)(&pLDR->InLoadOrderModuleList);
	pLdteCur = (PLDR_DATA_TABLE_ENTRY)(pLdteHead->InLoadOrderLinks.Flink);

	// 遍歷模組
	do
	{
		PLDR_DATA_TABLE_ENTRY pLdte = CONTAINING_RECORD(pLdteCur, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
		
		// 字串對比

		bEqual = TRUE;
		StringMinLen = min(wcslen(lpModuleName), pLdteCur->BaseDllName.Length);
		for (size_t i = 0; i < StringMinLen; i++)
		{
			if (towupper(lpModuleName[i]) != towupper(pLdteCur->BaseDllName.Buffer[i]))
			{
				bEqual = FALSE;
				break;
			}
		}		
		if (bEqual)
		{
			hModule = (HMODULE)pLdteCur->DllBase;			
			break;
		}
		pLdteCur = (PLDR_DATA_TABLE_ENTRY)pLdteCur->InLoadOrderLinks.Flink;
	} while (pLdteHead != pLdteCur);

	return hModule;
}

// 重寫的 GetProcAddress
LPVOID GetFunctionByName(LPVOID pDllImageBuffer, LPCSTR lpszFunc)
{
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pDllImageBuffer;
	PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
	PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)pDllImageBuffer +
		pNtHeader->OptionalHeader.DataDirectory[0].VirtualAddress);

	PDWORD AddressOfFunctions = (PDWORD)((PBYTE)pDllImageBuffer + pExport->AddressOfFunctions);
	PDWORD AddressOfNames = (PDWORD)((PBYTE)pDllImageBuffer + pExport->AddressOfNames);
	PUSHORT AddressOfNameOrdinals = (PUSHORT)((PBYTE)pDllImageBuffer + pExport->AddressOfNameOrdinals);
	for (size_t i = 0; i < pExport->NumberOfNames; i++)
	{
		if (0 == strcmp(lpszFunc, (char *)pDllImageBuffer + AddressOfNames[i]))
		{
			return AddressOfFunctions[AddressOfNameOrdinals[i]] + (PBYTE)pDllImageBuffer;
		}
	}

	return NULL;
}

相關文章