-
-
Save gavz/ab137a314aaecd4d47808017d1e3ad91 to your computer and use it in GitHub Desktop.
Customized GetProcAddress and GetModuleHandle and handle redirected function with API hashing
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
UINT32 HashStringJenkinsOneAtATime32BitA(_In_ PCHAR String) | |
{ | |
SIZE_T Index = 0; | |
UINT32 Hash = 0; | |
SIZE_T Length = lstrlenA(String); | |
while (Index != Length) | |
{ | |
Hash += String[Index++]; | |
Hash += Hash << INITIAL_SEED; | |
Hash ^= Hash >> 6; | |
} | |
Hash += Hash << 3; | |
Hash ^= Hash >> 11; | |
Hash += Hash << 15; | |
return Hash; | |
} | |
UINT32 HashStringJenkinsOneAtATime32BitW(_In_ PWCHAR String) | |
{ | |
SIZE_T Index = 0; | |
UINT32 Hash = 0; | |
SIZE_T Length = lstrlenW(String); | |
while (Index != Length) | |
{ | |
Hash += String[Index++]; | |
Hash += Hash << INITIAL_SEED; | |
Hash ^= Hash >> 6; | |
} | |
Hash += Hash << 3; | |
Hash ^= Hash >> 11; | |
Hash += Hash << 15; | |
return Hash; | |
} | |
FARPROC GetProcAddressH(HMODULE hModule, DWORD dwApiNameHash) { | |
if (hModule == NULL || dwApiNameHash == NULL) | |
return NULL; | |
PBYTE pBase = (PBYTE)hModule; | |
PIMAGE_DOS_HEADER pImgDosHdr = (PIMAGE_DOS_HEADER)pBase; | |
if (pImgDosHdr->e_magic != IMAGE_DOS_SIGNATURE) | |
return NULL; | |
PIMAGE_NT_HEADERS pImgNtHdr = (PIMAGE_NT_HEADERS)(pBase + pImgDosHdr->e_lfanew); | |
if (pImgNtHdr->Signature != IMAGE_NT_SIGNATURE) | |
return NULL; | |
IMAGE_OPTIONAL_HEADER ImgOptHdr = pImgNtHdr->OptionalHeader; | |
PIMAGE_EXPORT_DIRECTORY pImgExportDir = (PIMAGE_EXPORT_DIRECTORY)(pBase + ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); | |
PDWORD FunctionNameArray = (PDWORD)(pBase + pImgExportDir->AddressOfNames); | |
PDWORD FunctionAddressArray = (PDWORD)(pBase + pImgExportDir->AddressOfFunctions); | |
PWORD FunctionOrdinalArray = (PWORD)(pBase + pImgExportDir->AddressOfNameOrdinals); | |
DWORD dwImgExportDirSize = ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; | |
for (DWORD i = 0; i < pImgExportDir->NumberOfFunctions; i++) { | |
CHAR* pFunctionName = (CHAR*)(pBase + FunctionNameArray[i]); | |
PVOID pFunctionAddress = (PVOID)(pBase + FunctionAddressArray[FunctionOrdinalArray[i]]); | |
DWORD DotOffSet = 0; | |
CHAR ForwardedName[MAX_PATH * 2] = { 0 }; | |
PCHAR FunctionMod = NULL; | |
PCHAR FunctionName = NULL; | |
//Hashing function | |
if (dwApiNameHash == HashStringJenkinsOneAtATime32BitA(pFunctionName)) { | |
// Check if it's a redirected function | |
if ((ULONG_PTR)pFunctionAddress >= (ULONG_PTR)(pImgExportDir) && | |
(ULONG_PTR)pFunctionAddress < (ULONG_PTR)(pImgExportDir) + dwImgExportDirSize) { | |
memcpy(ForwardedName, pFunctionAddress, strlen((PCHAR)pFunctionAddress)); | |
for (int i = 0; i < strlen((PCHAR)ForwardedName); i++) { | |
if ((PCHAR)ForwardedName[i] == '.') { | |
ForwardedName[i] = NULL; | |
DotOffSet = i; | |
break; | |
} | |
} | |
FunctionName = ForwardedName + DotOffSet + 1; | |
FunctionMod = ForwardedName; | |
// Calling GetProcCustom with Forwarded function | |
return GetProcAddressH(LoadLibraryA(FunctionMod), HashStringJenkinsOneAtATime32BitA(FunctionName)); | |
} | |
return (FARPROC)pFunctionAddress; | |
} | |
} | |
return NULL; | |
} | |
HMODULE GetModuleHandleH(DWORD dwModuleNameHash) { | |
if (dwModuleNameHash == NULL) | |
return NULL; | |
#ifdef _WIN64 | |
PPEB pPeb = (PEB*)(__readgsqword(0x60)); | |
#elif _WIN32 | |
PPEB pPeb = (PEB*)(__readfsdword(0x30)); | |
#endif | |
PPEB_LDR_DATA pLdr = (PPEB_LDR_DATA)(pPeb->Ldr); | |
PLDR_DATA_TABLE_ENTRY pDte = (PLDR_DATA_TABLE_ENTRY)(pLdr->InMemoryOrderModuleList.Flink); | |
while (pDte) { | |
if (pDte->FullDllName.Length != NULL && pDte->FullDllName.Length < MAX_PATH) { | |
//Converting `FullDllName.Buffer to uppercase | |
CHAR UpperCaseDllName[MAX_PATH]; | |
DWORD i = 0; | |
while (pDte->FullDllName.Buffer[i]) { | |
UpperCaseDllName[i] = (CHAR)toupper(pDte->FullDllName.Buffer[i]); | |
i++; | |
} | |
UpperCaseDllName[i] = '\0'; | |
//Hash module name then compare | |
if (HashStringJenkinsOneAtATime32BitA(UpperCaseDllName) == dwModuleNameHash) | |
return (HMODULE)(pDte->InInitializationOrderLinks.Flink); | |
} | |
else { | |
break; | |
} | |
// Move to next element | |
pDte = *(PLDR_DATA_TABLE_ENTRY*)(pDte); | |
} | |
return NULL; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment