Skip to content

Instantly share code, notes, and snippets.

@v1stra
Created December 10, 2022 13:27
Show Gist options
  • Select an option

  • Save v1stra/bd0bc1617da1e3131bb2ed69e09cb01a to your computer and use it in GitHub Desktop.

Select an option

Save v1stra/bd0bc1617da1e3131bb2ed69e09cb01a to your computer and use it in GitHub Desktop.
#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