
Header-only Windows x64 indirect syscall library. Zero CRT, zero IAT, VEH anti-BP, AMSI/ETW bypass, W^X memory, per-call dynamic stubs.
Header-only library for Windows x64 that lets you invoke any NT syscall without touching ntdll imports, without leaving strings in your binary, and without the usual red flags that make EDRs lose their minds.
No CRT. No STL. No IAT. The whole thing compiles down to ~19KB with literally zero DLL dependencies.
Built to avoid the common pitfalls of existing syscall libraries — plaintext strings, known hash constants, direct syscall from non-ntdll memory, IAT imports that scream "I'm doing something weird", SEC_NO_CHANGE IOC, CRT bloat. None of that here.
Syscall Engine
syscall; ret gadget, so RIP is always inside ntdll when the syscall instruction fires\KnownDlls\ntdll.dll section mapping (no filesystem access, invisible to ProcMon)Anti-Breakpoint
Evasion
AmsiScanBuffer to return S_OKEtwEventWrite to return SUCCESSCode Quality
stealth/ folder into your project and go
initialize() opens ntdll through \KnownDlls section, parses PE exports, grabs every syscall number.text for a syscall; ret gadget — this is where the actual syscall instruction will execute fromsc::invoke():
emit_stub() builds a unique polymorphic stub — random junk instructions before/after, XOR-obfuscated syscall number with a per-call key, indirect jmp to the ntdll gadgetAt no point does RWX memory exist. At no point does a syscall instruction execute outside of ntdll. At no point are syscall numbers stored in plaintext.
You call tramp::invoke() with the target function. If there's no breakpoint — the function just runs normally with zero overhead. If a debugger placed 0xCC:
The debugger's breakpoint list still shows it as active. The breakpoint just never triggers on our calls.
cmake -B build -A x64
cmake --build build --config Release
Needs MSVC (VS 2019+) and CMake 3.15+. Output is ~19KB with zero imports.
#include "stealth/syscall.hpp"
stealth::sc::initialize();
PVOID base = nullptr;
SIZE_T size = 0x1000;
NTSTATUS status = stealth::sc::invoke<NTSTATUS>(
HASH("NtAllocateVirtualMemory"),
NtCurrentProcess(), &base, (ULONG_PTR)0, &size,
(ULONG)(MEM_COMMIT | MEM_RESERVE), (ULONG)PAGE_READWRITE
);
#include "stealth/trampoline.hpp"
// works even if x64dbg has a BP on MessageBoxA
int ret = stealth::tramp::invoke<int>(
HASH_CI("user32.dll"), HASH("MessageBoxA"),
(HWND)nullptr, (LPCSTR)"hello", (LPCSTR)"title", (UINT)MB_OK
);
#include "stealth/bypass.hpp"
stealth::bypass::patch_etw();
stealth::bypass::patch_amsi();
stealth::tramp::shutdown();
stealth::sc::shutdown();
stealth/
common.hpp — memory ops, spinlock, static_map, PRNG, debug output
hash.hpp — compile-time custom hash
xorstr.hpp — compile-time XOR string encryption
peb.hpp — PEB walk, PE export parser, hook detection
syscall.hpp — indirect syscall engine, stub generator, W^X, anti-dump
trampoline.hpp — VEH-based anti-breakpoint
bypass.hpp — AMSI + ETW patching
MIT — do whatever you want with it.