
Header-only Windows x64 indirect syscall library. Zero CRT, zero IAT, VEH anti-BP, AMSI/ETW bypass, W^X memory, per-call dynamic stubs.
Librería de solo cabecera para Windows x64 que te permite invocar cualquier syscall de NT sin tocar los imports de ntdll, sin dejar cadenas en tu binario y sin las banderas rojas habituales que hacen que los EDR pierdan la cabeza.
Sin CRT. Sin STL. Sin IAT. Todo se compila hasta ~19KB con literalmente cero dependencias de DLL.
Diseñada para evitar los errores comunes de las librerías de syscall existentes: cadenas en texto plano, constantes hash conocidas, syscall directo desde memoria que no es de ntdll, imports IAT que gritan "estoy haciendo algo raro", IOC SEC_NO_CHANGE, inflado de CRT. Nada de eso aquí.
syscall; ret propio de ntdll, por lo que RIP siempre está dentro de ntdll cuando se ejecuta la instrucción syscall\KnownDlls\ntdll.dll (sin acceso al sistema de archivos, invisible para ProcMon)Anti-Breakpoint
Evasión
AmsiScanBuffer para que devuelva S_OKEtwEventWrite para que devuelva SUCCESSCalidad del Código
stealth/ en tu proyecto y listo
initialize() abre ntdll a través de la sección \KnownDlls, analiza los exports del PE y captura cada número de syscall.text de ntdll en busca de un gadget syscall; ret: desde aquí se ejecutará la instrucción syscall realsc::invoke():
emit_stub() construye un stub polimórfico único: instrucciones basura aleatorias antes/después, número de syscall ofuscado con XOR y clave por llamada, jmp indirecto al gadget de ntdllEn ningún momento existe memoria RWX. En ningún momento se ejecuta una instrucción syscall fuera de ntdll. En ningún momento los números de syscall se almacenan en texto plano.
Llamas a tramp::invoke() con la función objetivo. Si no hay breakpoint, la función simplemente se ejecuta normalmente con cero sobrecarga. Si un depurador colocó 0xCC:
La lista de breakpoints del depurador sigue mostrándolo como activo. El breakpoint simplemente nunca se dispara en nuestras llamadas.
cmake -B build -A x64
cmake --build build --config Release
Requiere MSVC (VS 2019+) y CMake 3.15+. La salida es de ~19KB con cero 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"
// funciona incluso si x64dbg tiene un BP en 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 — operaciones de memoria, spinlock, static_map, PRNG, salida de depuración
hash.hpp — hash personalizado en tiempo de compilación
xorstr.hpp — cifrado de cadenas XOR en tiempo de compilación
peb.hpp — recorrido de PEB, analizador de exports PE, detección de hooks
syscall.hpp — motor de syscalls indirectos, generador de stubs, W^X, anti-dump
trampoline.hpp — anti-breakpoint basado en VEH
bypass.hpp — parcheo de AMSI + ETW
MIT: haz lo que quieras con ello.