- Implemented fully decoupled direct and indirect syscall invocation - Added dynamic PEB-based gadget scanning (syscall; ret / sysenter) - Added x86 & x64 inline MASM stubs with proper stack frame alignment - Introduced SND_USE_DEFAULTS compile-time OpSec macro for lean payload compilation - Extensive documentation across all primitives and examples
3.5 KiB
Process Techniques
The process subdomain defines how SindriKit interacts with a remote target process. The injection engine never calls OpenProcess or WriteProcessMemory directly; it routes all cross-process operations through ctx->proc_api.
Paradigm 1: Win32 Process Operations (snd_proc_win)
The snd_proc_win implementation backs the process interface with standard Win32 APIs:
- Open:
OpenProcess - Remote alloc:
VirtualAllocEx - Remote write:
WriteProcessMemory - Remote protect:
VirtualProtectEx - Remote thread:
CreateRemoteThread - Close:
CloseHandle
OpSec Implications
Every operation generates high-visibility telemetry through kernel32.dll and hooked ntdll.dll stubs. Intended for diagnostics (pocs/inject_shell/main.c uses this profile) or environments without EDR.
Paradigm 2: NT API (snd_proc_nt)
The snd_proc_nt implementation resolves NT functions from ntdll.dll via PEB walking and hash-based EAT parsing:
- Open:
NtOpenProcess - Remote alloc:
NtAllocateVirtualMemory - Remote write:
NtWriteVirtualMemory - Remote protect:
NtProtectVirtualMemory - Remote thread:
NtCreateThreadEx(withTHREAD_ALL_ACCESS/0x1FFFFF) - Close:
NtClose
OpSec Implications
Bypasses kernel32.dll and avoids plaintext API strings. Calls still execute through in-process ntdll.dll stubs where inline EDR hooks may fire.
Paradigm 3: Direct Syscalls (snd_proc_sys)
The snd_proc_sys implementation invokes the same NT operations through the syscall resolution pipeline and ASM stubs:
- Open / Alloc / Write / Protect / Thread / Close: Direct syscalls resolved by compile-time function hashes
Remote thread creation uses NtCreateThreadEx with the same access mask (0x1FFFFF) as the NT backend.
OpSec Implications
Direct syscalls bypass userland EDR hooks on ntdll.dll stubs. This is the preferred backend for stealth injection profiles.
Warning
snd_proc_sysrequires a bootstrapped syscall pipeline (snd_syscall_set_ntdll,snd_syscall_set_resolver,snd_syscall_set_invoker) before any_sysprocess call. See the Syscall Primitives documentation.
Injection Integration
The classic injection chain injects a process backend into snd_inj_ctx_t:
snd_inj_ctx_t inj_ctx = {0};
inj_ctx.target_pid = target_pid;
inj_ctx.proc_api = &snd_proc_sys;
snd_status_t status = snd_inj_classic_pe(&ldr_ctx, &inj_ctx);
snd_inj_cleanup(&inj_ctx);
The injection engine progresses through discrete stages (SND_INJ_STAGE_*), calling proc_api callbacks at each step:
open_process— acquire a handle totarget_pidalloc_remote— reserve/commit memory in the remote processwrite_remote— copy the prepared payloadprotect_remote— set final page protections (e.g.PAGE_EXECUTE_READ)create_remote_thread— execute the entry pointclose_handle— release process and thread handles viasnd_inj_cleanup
A typical full-stealth profile (pocs/inject_pe/main.c):
- Map clean
ntdll.dllfrom KnownDlls (snd_om_knowndll_map+snd_map_nt) - Bootstrap syscalls with the mapped base
- Load payload locally with
snd_mem_sys+snd_mod_nt - Inject remotely with
snd_proc_sys
Mixing Backends
Process backends are independent of memory and module backends. The local loader can use snd_mem_sys while injection uses snd_proc_win, or any other combination — each snd_*_api_t table is injected separately.