Files
sibouzitoun aea2eb6cfb Release v1.1.0: Process Injection & Architecture Hardening
- Implement complete cross-process injection engine via snd_inj_ctx_t
- Track explicit remote_entry_point for safe thread hijacking and PE execution
- Refactor standalone syscall resolvers into a unified pipeline (scan/sort)
- Perfect status code system by purging generic fallbacks in favor of highly-specific, domain-aware error codes
- Fix minor pointer validation and parsing bugs in the reflective loader
2026-06-28 14:14:54 +01:00

6.2 KiB

Loaders: API Reference

Public loader API for the Reflective PE technique under include/sindri/loaders/reflective/. Include sindri/loaders.h or sindri/loaders/reflective.h.

KnownDlls mapping is documented under mapping/object-manager — not part of this API surface.


Reflective Chain (sindri/loaders/reflective/chain.h)

Primary entry points for end-to-end reflective loading.

snd_ldr_pe_prepare_image

Runs the full local preparation pipeline:

  1. snd_pe_parse(ctx->raw_source, FALSE, &ctx->pe)
  2. snd_ldr_pe_compatibility_check
  3. snd_ldr_pe_allocate_and_copy_image
  4. snd_ldr_pe_apply_relocations
  5. snd_ldr_pe_resolve_imports
  6. snd_ldr_pe_apply_memory_protections

Leaves context at SND_STAGE_READY_FOR_EXECUTION. Does not run TLS or invoke the entry point.

snd_status_t snd_ldr_pe_prepare_image(snd_ldr_pe_ctx_t *ctx);

Returns: SND_OK or first failing stage status

Source: src/loaders/reflective/chain.c


snd_ldr_pe_execute_image

Executes a prepared image locally. Requires SND_STAGE_READY_FOR_EXECUTION and local_base == execution_base.

  1. Resolves entry point
  2. Runs TLS callbacks (DLL_PROCESS_ATTACH)
  3. Invokes DllMain (DLL) or jumps to EXE entry
snd_status_t snd_ldr_pe_execute_image(snd_ldr_pe_ctx_t *ctx);

Returns: SND_OK, SND_STATUS_DLL_INITIALIZATION_FAILED, SND_STATUS_ENTRY_POINT_NOT_FOUND, SND_STATUS_UNSUPPORTED (remote-prepared image)


snd_ldr_pe_detach_image

Tears down a locally executed image. Requires SND_STAGE_EXECUTED and matching local/execution bases. Runs DLL detach + TLS detach, then frees mapped memory.

void snd_ldr_pe_detach_image(snd_ldr_pe_ctx_t *ctx);

No-op if preconditions fail (including remote-prepared images).


Reflective Engine (sindri/loaders/reflective/engine.h)

snd_ldr_pe_ctx_t

Central context for reflective PE operations.

Field Type Description
raw_source const snd_buffer_t * Raw on-disk PE bytes
pe snd_pe_parser_t Parsed PE context (raw then re-parsed mapped)
target snd_pe_target_t Allocation, delta, entry point state
stage snd_ldr_pe_stage_t Current pipeline stage
mem_api const snd_memory_api_t * Injected memory primitives
mod_api const snd_module_api_t * Injected module primitives

snd_pe_target_t

Field Type Description
local_base LPVOID Local virtual mapping base
execution_base LPVOID Base for relocation delta (remote base when baking for injection)
delta_offset LONG_PTR execution_base - ImageBase
entry_point LPVOID Resolved entry (after get_entry_point)
allocated_size SIZE_T SizeOfImage allocation size

snd_ldr_pe_stage_t

Constant Value
SND_STAGE_UNINITIALIZED 0
SND_STAGE_PARSED 1
SND_STAGE_MEM_ALLOCATED 2
SND_STAGE_SECTIONS_MAPPED 3
SND_STAGE_RELOCATED 4
SND_STAGE_IMPORTS_RESOLVED 5
SND_STAGE_READY_FOR_EXECUTION 6
SND_STAGE_EXECUTED 7

Engine functions

Function Required stage Description
snd_ldr_pe_compatibility_check (after parse) Host vs payload bitness
snd_ldr_pe_allocate_and_copy_image PARSED Alloc + section copy + re-parse mapped
snd_ldr_pe_apply_relocations SECTIONS_MAPPED Base relocation fixups
snd_ldr_pe_resolve_imports RELOCATED IAT patching via mod_api
snd_ldr_pe_apply_memory_protections IMPORTS_RESOLVED Per-page section protections
snd_ldr_pe_get_entry_point >= READY_FOR_EXECUTION Populates target.entry_point
snd_ldr_pe_execute_tls_callbacks >= READY_FOR_EXECUTION Invokes TLS callback array
snd_ldr_pe_get_proc_address >= READY_FOR_EXECUTION Export resolve via snd_pe_get_export_address
snd_ldr_pe_free_mapped_image (any with local_base) Frees mapping, resets toward PARSED

Source: src/loaders/reflective/engine.c


snd_ldr_pe_get_proc_address

Resolves an export from the loaded image using the PE export parser. Forwarders use mod_api->get_module_base as resolver.

snd_status_t snd_ldr_pe_get_proc_address(snd_ldr_pe_ctx_t *ctx, const char *func_name, FARPROC *func_addr_out);

Export call macros

SND_CALL_EXPORT

Resolves and calls an export; discards return value.

SND_CALL_EXPORT(ctx, name, signature, status_out, ...)

SND_CALL_EXPORT_RET

Resolves and calls an export; captures return value in ret_out.

SND_CALL_EXPORT_RET(ctx, name, signature, status_out, ret_out, ...)

Both macros set status_out from snd_ldr_pe_get_proc_address and only invoke the function when resolution succeeds (SND_SUCCEEDED(status_out)).


Stage validation errors

Engine functions return SND_STATUS_INVALID_STAGE_SEQUENCE with context naming expected vs actual stage. Allocation failure during section copy rolls back to SND_STAGE_PARSED and frees local_base.

snd_ldr_pe_free_mapped_image vs snd_ldr_pe_detach_image

Function When to use
snd_ldr_pe_free_mapped_image Release virtual memory after prepare-only or failed load
snd_ldr_pe_detach_image Full teardown after local execute: DllMain detach, TLS detach, then free

detach_image is a no-op when local_base != execution_base (remote-prepared images from snd_inj_classic_pe).


Usage Example (local reflective load)

snd_ldr_pe_ctx_t ctx = {0};
ctx.raw_source = &file_buf;
ctx.mem_api    = &snd_mem_win;
ctx.mod_api    = &snd_mod_win;

snd_status_t status = snd_ldr_pe_prepare_image(&ctx);
if (SND_FAILED(status)) goto cleanup;

status = snd_ldr_pe_execute_image(&ctx);
if (SND_FAILED(status)) goto cleanup;

snd_ldr_pe_detach_image(&ctx);
cleanup:
    snd_ldr_pe_free_mapped_image(&ctx);