9.7 KiB
PE Parser: API Reference
This page documents the full public API surface of the parsers subsystem. Headers live under include/sindri/parsers/pe/.
Core Parser (sindri/parsers/pe/pe_parser.h)
snd_pe_parse
Validates and parses a raw or mapped PE buffer into a snd_pe_parser_t context. Checks the DOS signature (MZ), the NT signature (PE\0\0), and the Optional Header magic (0x10B for PE32, 0x20B for PE32+). Populates all fields of the output structure on success.
| Parameter | Type | Description |
|---|---|---|
buf |
const snd_buffer_t* |
Buffer descriptor containing the PE data (pointer + size) |
is_mapped |
BOOL |
FALSE for a raw file, TRUE for a memory-mapped image |
parser |
snd_pe_parser_t* |
Output context to populate |
Returns: snd_status_t — SND_OK on success, or a parse error (SND_STATUS_INVALID_DOS_SIGNATURE, SND_STATUS_INVALID_NT_SIGNATURE, SND_STATUS_UNSUPPORTED_OPTIONAL_HEADER_MAGIC, etc.).
SND_PE_GET_NT_FIELD(parser, field)
Macro for reading a field from the NT Optional Header without branching on is_64bit at every call site. Selects nt.nt64->field or nt.nt32->field based on parser->is_64bit.
DWORD size_of_image = SND_PE_GET_NT_FIELD(&ctx.pe, OptionalHeader.SizeOfImage);
SND_SYS_DLL_SIZE_DEFAULT
Value: 0x1000 (4096 bytes)
Bootstrap bound used when parsing the headers of an in-memory system DLL before SizeOfImage is known. After snd_pe_parse succeeds, the caller must update parser->source.size to SizeOfImage before calling any directory resolution function.
snd_pe_parser_t
| Field | Type | Description |
|---|---|---|
source |
snd_buffer_t |
Buffer descriptor (base pointer + tracked size) |
dos |
PIMAGE_DOS_HEADER |
Pointer to the DOS header |
nt.nt32 |
PIMAGE_NT_HEADERS32 |
NT headers pointer for 32-bit images (valid when is_64bit == FALSE) |
nt.nt64 |
PIMAGE_NT_HEADERS64 |
NT headers pointer for 64-bit images (valid when is_64bit == TRUE) |
section_head |
PIMAGE_SECTION_HEADER |
Pointer to the first section header entry |
string_table |
BYTE* |
COFF string table pointer (used for long section names) |
is_64bit |
BOOL |
TRUE for PE32+ (64-bit image) |
is_dll |
BOOL |
TRUE if IMAGE_FILE_DLL is set in FileHeader.Characteristics |
is_mapped |
BOOL |
TRUE if the source buffer is a loaded image, FALSE if raw file |
sections_count |
DWORD |
Number of section header entries |
imports_rva |
DWORD |
Cached RVA of the import data directory |
import_size |
DWORD |
Cached size of the import data directory |
SND_PE_MIN_FILE_ALIGNMENT
Value: 512
The minimum valid file alignment factor allowed for a PE image. Used to sanity-check PE structures against malformed headers.
Utilities (sindri/parsers/pe/pe_utils.h)
snd_pe_compatibility_check
Validates that a payload's bitness matches the host process architecture. This validation should occur before allocating memory or mapping sections.
| Parameter | Type | Description |
|---|---|---|
is_64bit |
BOOL |
TRUE if the payload is 64-bit |
Returns: BOOL — TRUE if compatible, FALSE on mismatch.
snd_pe_get_entry_point
Computes the absolute entry point address from OptionalHeader.AddressOfEntryPoint relative to the parser's source base.
| Parameter | Type | Description |
|---|---|---|
parser |
const snd_pe_parser_t* |
Parsed PE context |
Returns: void* — absolute entry point address, or NULL if the RVA is zero or invalid.
snd_pe_get_tls_callbacks
Retrieves the TLS callback array pointer from the TLS data directory. Returns NULL if no TLS directory is present.
| Parameter | Type | Description |
|---|---|---|
base_address |
PVOID |
Base address of the mapped image |
parser |
const snd_pe_parser_t* |
Parsed PE context |
Returns: PVOID — pointer to the null-terminated PIMAGE_TLS_CALLBACK array, or NULL.
snd_pe_execute_tls_callbacks
Iterates the TLS callback array and calls each entry with the specified reason.
| Parameter | Type | Description |
|---|---|---|
virtual_base |
PVOID |
Base address of the mapped image |
parser |
const snd_pe_parser_t* |
Parsed PE context |
reason |
DWORD |
Callback reason (e.g., DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH) |
Returns: snd_status_t — SND_OK on success (including when no TLS directory exists).
snd_pe_rva_to_ptr
Translates an RVA to an absolute pointer within the parser's tracked buffer. Performs a bounds check on (rva, size) before returning. For raw files (is_mapped = FALSE), performs section-table-based translation. For mapped images (is_mapped = TRUE), returns source.base + rva directly.
| Parameter | Type | Description |
|---|---|---|
parser |
const snd_pe_parser_t* |
Parsed PE context |
rva |
DWORD |
Relative Virtual Address to translate |
size |
SIZE_T |
Expected data size at the target address (used for bounds checking) |
Returns: PVOID — pointer to the data, or NULL if out-of-bounds or the RVA is invalid.
snd_pe_get_directory
Safely retrieves a data directory entry by index from the Optional Header's DataDirectory array.
| Parameter | Type | Description |
|---|---|---|
parser |
const snd_pe_parser_t* |
Parsed PE context |
index |
DWORD |
Directory index (e.g., IMAGE_DIRECTORY_ENTRY_IMPORT, IMAGE_DIRECTORY_ENTRY_EXPORT) |
dir_out |
IMAGE_DATA_DIRECTORY* |
Output structure populated with VirtualAddress and Size |
Returns: snd_status_t — SND_OK on success, SND_STATUS_DIRECTORY_NOT_FOUND if the directory index is out of range or the directory's VirtualAddress is zero.
Export Resolution (sindri/parsers/pe/pe_exports.h)
snd_pe_get_export_address
Resolves an exported symbol by name from a mapped PE image. Handles export forwarders recursively via the resolver callback.
| Parameter | Type | Description |
|---|---|---|
base_address |
PVOID |
Base address of the mapped PE image |
size |
SIZE_T |
Size of the mapped PE image (for bounds checking) |
func_name |
const char* |
Null-terminated export name to resolve |
func_addr_out |
FARPROC* |
Receives the resolved function address |
resolver |
snd_module_resolver_cb |
Callback to resolve external module bases for forwarders; pass NULL to fail on forwarders |
Returns: snd_status_t — SND_OK on success, SND_STATUS_EXPORT_NOT_FOUND if the name is not in the export table, SND_STATUS_EXPORT_FORWARDER_UNSUPPORTED if a forwarder is encountered and resolver is NULL.
snd_pe_get_export_address_by_hash
Hash-based variant of export resolution. Eliminates plaintext function name strings from the binary entirely.
| Parameter | Type | Description |
|---|---|---|
base_address |
PVOID |
Base address of the mapped PE image |
size |
SIZE_T |
Size of the mapped PE image |
func_hash |
DWORD |
Pre-computed hash of the target export name |
func_addr_out |
FARPROC* |
Receives the resolved function address |
resolver |
snd_module_resolver_hash_cb |
Hash-based resolver callback for forwarder modules |
Returns: snd_status_t — SND_OK on success, or an export resolution error.
SND_FWD_MAX_DEPTH
Value: 4
Maximum recursion depth for export forwarder resolution. Prevents infinite loops from cyclically forwarded exports.
Import Resolution (sindri/parsers/pe/pe_imports.h)
snd_pe_resolve_imports
Walks the Import Descriptor table of a mapped PE and patches the IAT. For each descriptor: loads the dependency module via mod_api->load_library, then iterates the thunk array resolving by ordinal or name via mod_api->get_proc_address.
| Parameter | Type | Description |
|---|---|---|
base_address |
PVOID |
Base address of the mapped PE image |
mod_api |
const snd_module_api_t* |
Module API used for all loading and symbol resolution |
parser |
const snd_pe_parser_t* |
Parsed PE context |
Returns: snd_status_t — SND_OK on success, or an import resolution error (SND_STATUS_IMPORT_DLL_LOAD_FAILED, SND_STATUS_IMPORT_SYMBOL_RESOLVE_FAILED, etc.).
Ordinal Detection Macros
| Macro | Description |
|---|---|
SND_PE_SNAP_BY_ORDINAL32(ordinal) |
TRUE if the high bit of a 32-bit thunk value is set (ordinal-based import) |
SND_PE_SNAP_BY_ORDINAL64(ordinal) |
TRUE if the high bit of a 64-bit thunk value is set |
SND_PE_ORDINAL(ordinal) |
Extracts the 16-bit ordinal value from a thunk entry |
Base Relocations (sindri/parsers/pe/pe_relocations.h)
snd_pe_apply_relocations
Iterates the Base Relocation Table (.reloc section) and patches all hardcoded absolute addresses to align with the actual runtime base address. Each entry is bounds-checked before the write is applied.
The function computes delta = actual_base - preferred_base. If delta is zero (the image landed at its preferred ImageBase), the function returns immediately with SND_OK.
Note
The memory at
base_addressmust have at leastPAGE_READWRITEpermissions before calling this function, as it physically overwrites pointer-sized values inside.textand.datasections.
| Parameter | Type | Description |
|---|---|---|
base_address |
PVOID |
Actual runtime base address where the PE image is mapped |
delta_offset |
LONG_PTR |
Difference between actual base and preferred ImageBase; zero triggers early exit |
parser |
const snd_pe_parser_t* |
Validated PE parser context |
Returns: snd_status_t — SND_OK on success, or SND_STATUS_RELOCS_STRIPPED if IMAGE_FILE_RELOCS_STRIPPED is set in the PE characteristics.