1.7 KiB
PEB Walking
The modules subdomain provides mechanisms for interacting with the loaded DLLs of a process. The primary challenge in offensive tooling is resolving module base addresses and exported functions without relying on highly monitored APIs like GetModuleHandle or GetProcAddress.
Traversing the PEB
The Process Environment Block (PEB) is a userland structure containing extensive process information, including the lists of all currently loaded DLLs. It is accessible without invoking any Win32 or NT API calls.
- x64: Accessed via the
gssegment register at offset0x60 - x86: Accessed via the
fssegment register at offset0x30
The Loaded Module Lists
Within the PEB, PEB->Ldr points to a PEB_LDR_DATA structure. This structure contains three doubly-linked lists of LDR_DATA_TABLE_ENTRY nodes:
InLoadOrderModuleListInMemoryOrderModuleListInInitializationOrderModuleList
SindriKit traverses the InMemoryOrderModuleList. By iterating through these nodes, the framework inspects the BaseDllName field of each loaded module.
Resolution Methods
String Comparison
The framework provides snd_peb_get_module_base to perform a case-insensitive, wide-string comparison against the BaseDllName (e.g., matching L"ntdll.dll").
Hash Comparison
For superior OpSec, snd_peb_get_module_base_by_hash computes a runtime hash of each module's name and compares it against a compile-time hash. This completely eliminates plaintext module strings (like ntdll.dll or kernel32.dll) from the implant's .rdata section.
Reference: Finding kernel32 base and function addresses in shellcode