Files
youssefnoob003-SindriKit/docs/domains/primitives/syscalls/README.md
T
sibouzitoun b7d3cf717c Release v1.2.0: Indirect Syscalls & Pipeline Decoupling
- 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
2026-06-29 19:31:15 +01:00

3.8 KiB

Syscall Primitives

Direct and indirect syscall invocation bypasses hooked ntdll.dll stubs by resolving System Service Numbers (SSNs) and executing the syscall instruction from custom ASM stubs — either inline (direct) or by jumping to a legitimate NTDLL gadget (indirect).

Header: include/sindri/primitives/syscalls.h
Implementation: src/primitives/execution/syscalls/

Warning

Bootstrap required: Call snd_syscall_set_ntdll(), configure at least one strategy via snd_syscall_set_resolver(), and configure the invoker via snd_syscall_set_invoker() before snd_syscall_resolve(). For indirect invocation, also set a gadget finder via snd_syscall_set_gadget_finder(). With SND_USE_DEFAULTS=ON, only snd_syscall_set_ntdll() is required — the resolver, invoker, and gadget finder are pre-configured at compile time. _sys memory/process/mapping backends depend on this pipeline.

How _sys primitives use syscalls

snd_mem_sys / snd_proc_sys / snd_map_sys
        │
        ▼
  snd_syscall_resolve(func_hash)       <- cascading strategy chain
        │
        ▼
  (gadget finder, if indirect)         <- locates syscall/sysenter gadget in NTDLL
        │
        ▼
  g_syscall_invoker(&args)             <- dispatches to configured ASM stub
        │
    ┌───┴───────────────────┐
    ▼                       ▼
  snd_syscall_direct_     snd_syscall_indirect_
  invoke_asm              invoke_asm

Function hashes come from sindri_hashes.h (build-generated, e.g. SND_HASH_NTALLOCATEVIRTUALMEMORY).

Resolution strategies

Function Source Approach
snd_syscall_resolve_ssn_scan syscalls_scan.c Read SSN from stub bytes; neighbor scan if hooked
snd_syscall_resolve_ssn_sort syscalls_sort.c Build sorted Zw* export table; index = SSN

Typical registration:

snd_syscall_set_resolver(snd_syscall_resolve_ssn_scan);
snd_syscall_add_resolver(snd_syscall_resolve_ssn_sort);
snd_syscall_set_invoker(snd_syscall_direct_invoke_asm);
// or for indirect:
// snd_syscall_set_invoker(snd_syscall_indirect_invoke_asm);
// snd_syscall_set_gadget_finder(snd_syscall_find_gadget_scan);

Custom resolvers matching snd_syscall_resolver_t can be added to the chain (max 4 strategies).

Invocation modes

Function File Description
snd_syscall_direct_invoke_asm invoke_direct_x64.asm / invoke_direct_x86.asm Executes syscall/sysenter inline
snd_syscall_indirect_invoke_asm invoke_indirect_x64.asm / invoke_indirect_x86.asm Jumps to a legitimate NTDLL gadget

Note

Build with SND_USE_DEFAULTS=ON to pre-configure the invoker (snd_syscall_direct_invoke_asm), gadget finder (snd_syscall_find_gadget_scan), and primary resolver (snd_syscall_resolve_ssn_scan) at compile time. Only snd_syscall_set_ntdll() is then needed at runtime.

Invocation modes

Function File Description
snd_syscall_direct_invoke_asm invoke_direct_x64.asm / invoke_direct_x86.asm Executes syscall/sysenter inline
snd_syscall_indirect_invoke_asm invoke_indirect_x64.asm / invoke_indirect_x86.asm Jumps to a legitimate NTDLL gadget

Note on SND_USE_DEFAULTS: When enabled, the framework pre-configures the invoker (indirect), gadget finder, and primary resolver automatically.

Table of Contents