Created
December 10, 2022 13:27
-
-
Save v1stra/bd0bc1617da1e3131bb2ed69e09cb01a to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| #include <stdio.h> | |
| #include <Windows.h> | |
| // pe_get_function_by_hash function: takes a pointer to a DLL mapped to memory, and a djb2 hash value of a function. | |
| // It then searches the DLL's export table, hashing the value of the strings in the table, and then returns | |
| // the address to that function. | |
| PVOID pe_get_function_by_hash(PVOID dll, ULONG hashValue) | |
| { | |
| // Pointers to DLL's DOS header, NT header, and data directory | |
| PIMAGE_DOS_HEADER dosHeader; | |
| PIMAGE_NT_HEADERS ntHeader; | |
| PIMAGE_DATA_DIRECTORY dataDirectory; | |
| // Pointers to DLL's export directory, address of functions, address of names, | |
| // and address of name ordinals | |
| PIMAGE_EXPORT_DIRECTORY exportDirectory; | |
| PDWORD addressOfFunctions; | |
| PDWORD addressOfNames; | |
| PUSHORT addressOfNameOrdinals; | |
| // Pointer to the current string in the export table, and counter for looping through the table | |
| PCHAR currentString; | |
| DWORD counter; | |
| // Hash value of the current string in the export table | |
| ULONG hashOfCurrentString; | |
| // Get pointers to DOS header, NT header, and data directory | |
| dosHeader = (PIMAGE_DOS_HEADER)dll; | |
| ntHeader = (PIMAGE_NT_HEADERS)(((DWORD_PTR)dosHeader) + dosHeader->e_lfanew); | |
| dataDirectory = (PIMAGE_DATA_DIRECTORY) & (ntHeader->OptionalHeader.DataDirectory[0]); | |
| // If the data directory has a valid virtual address, get pointers to the export directory, | |
| // address of functions, address of names, and address of name ordinals | |
| if (dataDirectory->VirtualAddress) { | |
| exportDirectory = (PIMAGE_EXPORT_DIRECTORY)(((DWORD_PTR)dosHeader) + dataDirectory->VirtualAddress); | |
| addressOfFunctions = (PDWORD)(((DWORD_PTR)dosHeader) + exportDirectory->AddressOfFunctions); | |
| addressOfNames = (PDWORD)(((DWORD_PTR)dosHeader) + exportDirectory->AddressOfNames); | |
| addressOfNameOrdinals = (PUSHORT)(((DWORD_PTR)dosHeader) + exportDirectory->AddressOfNameOrdinals); | |
| // Loop through the export table | |
| for (counter = 0; counter < exportDirectory->NumberOfNames; ++counter) { | |
| // Get a pointer to the current string in the table and its hash value | |
| currentString = (PCHAR)(((DWORD_PTR)dosHeader) + addressOfNames[counter]); | |
| hashOfCurrentString = hash_djb2(currentString); | |
| // If the hash value of the current string matches the given hash value, | |
| // return the address of the corresponding function | |
| if (hashOfCurrentString == hashValue) { | |
| return (PVOID)(((DWORD_PTR)dosHeader) + addressOfFunctions[addressOfNameOrdinals[counter]]); | |
| } | |
| } | |
| } | |
| // Return NULL if no matching function was found | |
| return NULL; | |
| } | |
| // Generate hash value for a string using the djb2 algorithm | |
| unsigned long hash_djb2(char* str) { | |
| unsigned long hash = 5381; | |
| int c; | |
| while ((c = *str++)) { | |
| hash = ((hash << 5) + hash) + c; | |
| } | |
| return hash; | |
| } | |
| int main() | |
| { | |
| HMODULE ntdll = GetModuleHandleA("ntdll"); | |
| unsigned long hash_NtAllocateVirtualMemory = hash_djb2("NtAllocateVirtualMemory"); | |
| PVOID pvAddress = pe_get_function_by_hash(ntdll, hash_NtAllocateVirtualMemory); | |
| printf("NTDLL->%p\nNtAllocateVirtualMemory->%p\n", ntdll, pvAddress); | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment