Created
November 27, 2023 22:51
-
-
Save OtterHacker/8abaf54694ef27b9e3d38dfe57f13bd3 to your computer and use it in GitHub Desktop.
Custom GetProcAddress and GetModuleHandle parsing forwarded export
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
unsigned long hash_string(void* buffer, unsigned long size, char* extension){ | |
unsigned char current = 0; | |
unsigned long hash = 0; | |
unsigned char* currentChar = NULL; | |
hash = 1337; | |
currentChar = (void*)buffer; | |
hash++; | |
while(1){ | |
current = *currentChar; | |
if (!size) { | |
if (!*currentChar) {break;} | |
} | |
else { | |
if ((ULONG)(currentChar - (PUCHAR)buffer) >= size) { break; } | |
if (!*currentChar) { ++currentChar; continue; } | |
} | |
if (current >= 'a'){current -= 0x20;} | |
hash = ((hash << 5) + hash) + current; | |
++currentChar; | |
}; | |
if(extension) { | |
currentChar = (void *)extension; | |
while (1) { | |
current = *currentChar; | |
if (!*currentChar) { break; } | |
if (current >= 'a') { current -= 0x20; } | |
hash = ((hash << 5) + hash) + current; | |
++currentChar; | |
}; | |
} | |
return hash; | |
}; | |
HMODULE get_module_handle(unsigned long module_hash, unsigned long* image_size) { | |
PPEB peb = (PPEB)__readgsqword(0x60); | |
PLIST_ENTRY hdr = NULL; | |
PLIST_ENTRY ent = NULL; | |
PLDR_DATA_TABLE_ENTRY ldr = NULL; | |
hdr = &(peb->Ldr->InLoadOrderModuleList); | |
ent = hdr->Flink; | |
for (; hdr != ent; ent = ent->Flink){ | |
ldr = (void*)ent; | |
if (hash_string(ldr->BaseDllName.Buffer, ldr->BaseDllName.Length, NULL) == module_hash){ | |
if (image_size != NULL) { *image_size = ldr->SizeOfImage; } | |
return ldr->DllBase; | |
} | |
} | |
return NULL; | |
} | |
PVOID get_proc_address(HMODULE moduleHandle, unsigned long hash) { | |
PIMAGE_DOS_HEADER dosHeaders = (PVOID)moduleHandle; | |
PIMAGE_NT_HEADERS ntHeaders = (PVOID)((ULONG_PTR)dosHeaders + dosHeaders->e_lfanew); | |
PIMAGE_DATA_DIRECTORY dataDirectory = &ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; | |
ULONG Idx = 0; | |
if (dataDirectory->VirtualAddress){ | |
PIMAGE_EXPORT_DIRECTORY exportsDirectory = (PVOID)((ULONG_PTR)dosHeaders + dataDirectory->VirtualAddress); | |
PUINT32 addressOfNames = (PVOID)((ULONG_PTR)dosHeaders + exportsDirectory->AddressOfNames); | |
PUINT32 addressOfFunctions = (PVOID)((ULONG_PTR)dosHeaders + exportsDirectory->AddressOfFunctions); | |
PUINT16 addressOfOrdinals = (PVOID)((ULONG_PTR)dosHeaders + exportsDirectory->AddressOfNameOrdinals); | |
for (Idx = 0; Idx < exportsDirectory->NumberOfNames; ++Idx){ | |
if (hash_string((PVOID)((ULONG_PTR)dosHeaders + addressOfNames[Idx]), 0, NULL) == hash){ | |
// Forwarded export | |
if((addressOfFunctions[addressOfOrdinals[Idx]] >=dataDirectory->VirtualAddress) && (addressOfFunctions[addressOfOrdinals[Idx]] < dataDirectory->VirtualAddress + dataDirectory->Size)){ | |
// Get the name of the forwarder : DLL.FUNCTION | |
char* forwarded_dll = (char*)((ULONG_PTR)dosHeaders + addressOfFunctions[addressOfOrdinals[Idx]]); | |
// Retrieve the function name with a simple split on '.' | |
char* export_name = forwarded_dll; | |
while(*export_name != '.'){ | |
if(*export_name == '\0'){ | |
return NULL; | |
} | |
export_name++; | |
} | |
size_t dll_name_length = export_name - forwarded_dll; | |
export_name++; | |
// Compute the hashed name of the DLL | |
ULONG dll_hash = hash_string(forwarded_dll, dll_name_length, (char[]){'.','d','l','l','\0'}); | |
ULONG export_hash = hash_string(export_name, 0, NULL); | |
// Get the module handle | |
HMODULE export_dll_module = get_module_handle(dll_hash, NULL); | |
// Resolve the forwarder and return the value | |
return get_proc_address(export_dll_module, export_hash); | |
} | |
return (PVOID)((ULONG_PTR)dosHeaders + addressOfFunctions[addressOfOrdinals[Idx]]); | |
} | |
} | |
} | |
return NULL; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment