Files

128 lines
4.1 KiB
C
Raw Permalink Normal View History

2026-08-27 11:03:10 -06:00
#include <windows.h>
#include <winternl.h>
#include <stdio.h>
#include <stdint.h>
typedef struct _S_LDR_DATA_TABLE_ENTRY {
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
LPVOID DllBase;
LPVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
} S_LDR_DATA_TABLE_ENTRY;
typedef struct _S_PEB_LDR_DATA {
DWORD Length;
DWORD Initialized;
LPVOID SsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
} S_PEB_LDR_DATA;
typedef struct _S_PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2;
#ifdef _WIN64
BYTE Reserved3[4];
#endif
LPVOID Reserved4[1];
LPVOID ImageBaseAddress;
S_PEB_LDR_DATA *Ldr;
} S_PEB;
static inline S_PEB *GetPeb(void) {
#ifdef _WIN64
return (S_PEB *)__readgsqword(0x60);
#else
return (S_PEB *)__readfsdword(0x30);
#endif
}
static DWORD StubHash(const char *str) {
DWORD h = 0x4E67C6A7;
while (*str) {
h = ((h << 5) + h) ^ (unsigned char)*str++;
}
return h;
}
static DWORD StubHashW(const WCHAR *str, USHORT lenBytes) {
DWORD h = 0x4E67C6A7;
const char *raw = (const char *)str;
for (USHORT i = 0; i < lenBytes; i++) {
char c = raw[i];
if (c >= 'a' && c <= 'z') c -= 0x20;
h = ((h << 5) + h) ^ (unsigned char)c;
}
return h;
}
int main(void) {
printf("=== PEB Module Walk ===\n");
S_PEB_LDR_DATA *ldr = GetPeb()->Ldr;
S_LDR_DATA_TABLE_ENTRY *first = (S_LDR_DATA_TABLE_ENTRY *)ldr->InMemoryOrderModuleList.Flink;
S_LDR_DATA_TABLE_ENTRY *entry = first;
do {
if (entry->BaseDllName.Buffer) {
DWORD h = StubHashW(entry->BaseDllName.Buffer, entry->BaseDllName.Length);
printf(" Module: %.*S hash=0x%08X base=%p\n",
entry->BaseDllName.Length / 2, entry->BaseDllName.Buffer,
h, entry->DllBase);
}
entry = (S_LDR_DATA_TABLE_ENTRY *)entry->InMemoryOrderModuleList.Flink;
} while (entry != first);
printf("\n=== Expected Hashes ===\n");
printf(" FH_KERNEL32 = 0x52B1CB57\n");
printf(" FH_NTDLL = 0x1EBCC013\n");
/* Try to resolve a function */
LPVOID k32 = NULL;
LPVOID ntdll = NULL;
entry = first;
do {
if (entry->BaseDllName.Buffer) {
DWORD h = StubHashW(entry->BaseDllName.Buffer, entry->BaseDllName.Length);
if (h == 0x52B1CB57) k32 = entry->DllBase;
if (h == 0x1EBCC013) ntdll = entry->DllBase;
}
entry = (S_LDR_DATA_TABLE_ENTRY *)entry->InMemoryOrderModuleList.Flink;
} while (entry != first);
printf("\n=== Resolution ===\n");
printf(" kernel32 base: %p %s\n", k32, k32 ? "FOUND" : "NOT FOUND!");
printf(" ntdll base: %p %s\n", ntdll, ntdll ? "FOUND" : "NOT FOUND!");
if (k32) {
/* Try resolving LoadLibraryA by hash */
LPBYTE base = (LPBYTE)k32;
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)base;
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)(base + dos->e_lfanew);
PIMAGE_EXPORT_DIRECTORY exp = (PIMAGE_EXPORT_DIRECTORY)(
base + nt->OptionalHeader.DataDirectory[0].VirtualAddress);
LPDWORD names = (LPDWORD)(base + exp->AddressOfNames);
int found = 0;
for (DWORD i = 0; i < exp->NumberOfNames && i < 5; i++) {
const char *name = (const char *)(base + names[i]);
DWORD h = StubHash(name);
if (i < 3) printf(" Export[%d]: %-30s hash=0x%08X\n", i, name, h);
}
/* Find LoadLibraryA specifically */
for (DWORD i = 0; i < exp->NumberOfNames; i++) {
const char *name = (const char *)(base + names[i]);
DWORD h = StubHash(name);
if (h == 0x32B72ABF) {
printf(" LoadLibraryA: FOUND (hash 0x32B72ABF matched \"%s\")\n", name);
found = 1;
break;
}
}
if (!found) printf(" LoadLibraryA: NOT FOUND!\n");
}
return 0;
}