I'm trying to implement a custom version of GetModuleHandle that takes a hash of the module name and returns the base address of the loaded module.
Here is the code:
PVOID GetModuleHandleH(DWORD dwModuleNameHash) {
if (dwModuleNameHash == NULL)
return NULL;
#ifdef _WIN64
PPEB pPeb = (PPEB)(__readgsqword(0x60));
#elif _WIN32
PPEB pPeb = (PPEB)(__readfsdword(0x30));
#endif
PPEB_LDR_DATA pLdr = (PPEB_LDR_DATA)(pPeb->LoaderData);
PLDR_DATA_TABLE_ENTRY pDte = (PLDR_DATA_TABLE_ENTRY)(pLdr->InMemoryOrderModuleList.Flink);
while (pDte) {
if (pDte->FullDllName.Length != NULL && pDte->FullDllName.Length < MAX_PATH) {
CHAR UpperCaseDllName[MAX_PATH];
DWORD i = 0;
while (pDte->FullDllName.Buffer[i]) {
UpperCaseDllName[i] = (CHAR)toupper(pDte->FullDllName.Buffer[i]);
i++;
}
UpperCaseDllName[i] = '\0';
if (HASHA(UpperCaseDllName) == dwModuleNameHash)
return (HMODULE)(pDte->InInitializationOrderLinks.Flink); // <--- Problem?
} else {
break;
}
pDte = *(PLDR_DATA_TABLE_ENTRY*)(pDte);
}
return NULL;
}
When I call this function like:
DWORD hashUser32 = HASHA("USER32.DLL");
PVOID hUser32 = GetModuleHandleH(hashUser32);
I get a truncated 32-bit value on x64: something like 0x53190000 instead of the full 64-bit address 0x00007FFE53190000.
My debugging shows: UpperCaseDllName is "USER32.DLL"
dwModuleNameHash is 882733799 (matches the DLL)
The return value is not the actual base address of the module.
Why is my function returning a truncated address on x64, and how can I fix it to get the correct module base address?
I RESOLVED WITH HMODULE GetModuleHandle(DWORD dwModuleNameHash);
dwModuleNameHash
isn't a pointer so don't doif (dwModuleNameHash == NULL)
. Compare with0
instead.