
SindriKit v2.0.0
Una biblioteca C fundamental para construir capacidades ofensivas operativamente creíbles.
SindriKit
El desarrollo ofensivo merece una mejor arquitectura.
Una biblioteca en C para construir capacidades ofensivas.
Concepto central
La mayoría de las utilidades ofensivas codifican de forma rígida sus mecánicas de ejecución dentro de la lógica de la técnica. Un cargador reflexivo no solo mapea una imagen; la mapea usando una cadena específica y codificada de llamadas a VirtualAlloc o a la NTAPI nativa. Cuando un EDR comienza a monitorear esa cadena específica, te ves obligado a reescribir toda la herramienta.
SindriKit resuelve esto imponiendo una separación de responsabilidades mediante tablas de abstracción de interfaces:
- La lógica de la técnica: (p. ej., cargadores, inyecciones, parcheadores) se ocupa del seguimiento de estado y la orquestación de datos. No tiene conocimiento de cómo se asigna la memoria ni de cómo se crean los hilos.
- Las mecánicas de ejecución: (p. ej., Win32 API, NTAPI nativa, syscalls directas) residen en tablas de API independientes y se inyectan en la técnica en tiempo de ejecución.
Al trasladar las mecánicas de ejecución a punteros a función en tiempo de ejecución, puedes cambiar toda tu estrategia de llamadas Win32 a syscalls directas en bruto con una sola línea de código, sin cambiar la lógica de ejecución de tu payload.
Arquitectura de diseño
- Perfiles de ejecución desacoplados: Intercambia las mecánicas de memoria, módulo, mapeo, proceso, hilo y archivo mediante tablas de punteros a función independientes (
snd_memory_api_t,snd_module_api_t,snd_process_api_t,snd_thread_api_t,snd_mapping_api_t,snd_file_api_t) sin tocar la lógica de la técnica. - Cobertura de técnicas: Carga reflexiva de PE (EXE/DLL) y COFF/BOF, inyección clásica y early-bird APC sobre shellcode/PE/COFF, además de FFI consciente de la arquitectura y Heaven's Gate, todo sobre los mismos perfiles componibles.
- Pipeline en cascada de syscalls: Resolvedores de SSN conectables (
snd_syscall_resolve_ssn_scan,snd_syscall_resolve_ssn_sort) con una cadena de prioridad, desacoplados de los invocadores: directo, indirecto (gadget de NTDLL) o suplantado (suplantación dinámica de pila de llamadas Fat-Frame). - Estado codificado por facility: Cada llamada que puede fallar devuelve
snd_status_t: un código de facility/local empaquetado más el error del SO capturado, con cadenas de contexto que se eliminan en la compilación en el nivel silencioso. - Ofuscación en tiempo de compilación: Los algoritmos de hashing de cadenas y API (DJB2, FNV1A) pueden intercambiarse globalmente mediante CMake. La compilación aleatoriza automáticamente la semilla global para alterar las firmas estáticas.
- Motor de mutación: Habilita polimorfismo profundo mediante
SND_MORPH. Genera firmas binarias únicas en cada compilación inyectando predicados opacos volátiles en el código C, matemáticas/NOPs funcionalmente equivalentes en los stubs de ensamblador, y alterando la disposición en memoria de las estructuras principales. - Compilaciones de release: Un nivel silencioso elimina todas las cadenas de diagnóstico, descriptores de archivo y marcos de seguimiento; las compilaciones
SND_CRTLESSvan más allá con/NODEFAULTLIB, sin cabecera del SDK, un frontend de PEB y solo backends nativos.
Inicio rápido
El repositorio incluye una única CLI unified que ejercita todos los perfiles:
build.bat pocs
build64\pocs\Release\unified.exe load pe -f payload.dll -e Run --sys
unified admite load pe|coff, inject classic|apc|hijack (shell, PE, COFF) y hg, cada uno sobre --win/--nt/--sys. Consulta Ejemplos y PoCs y Primeros pasos.
Integrar SindriKit
cmake_minimum_required(VERSION 3.16)
project(MyTool C ASM_MASM)
set(SND_BUILD_PAYLOADS OFF CACHE BOOL "")
set(SND_ENABLE_DEBUG OFF CACHE BOOL "")
set(SND_HASH_ALGO "DJB2" CACHE STRING "")
set(SND_RANDOMIZE_SEED ON CACHE BOOL "")
set(SND_MORPH ON CACHE BOOL "")
add_subdirectory(libs/SindriKit)
add_executable(my_tool src/main.c)
target_link_libraries(my_tool PRIVATE sindri::engine)
cmake -B build && cmake --build build --config Release
Solo dos líneas para que tu herramienta herede todas las capacidades de SindriKit: análisis de PE y COFF, carga reflexiva, syscalls en cascada y perfiles de inyección.
El motor
Capa de abstracción de API
┌────────────────────────────────────────────────────────────────────────────┐
│ CUALQUIER INTENCIÓN OFENSIVA │
│ Loader · Injector · Spoofer · Patcher · Bypasser · Harvester · ... │
├────────────────────────────────────────────────────────────────────────────┤
│ CAPA DE ABSTRACCIÓN DE API DE SINDRIKIT │
│ snd_memory_api_t -> alloc · free · protect │
│ snd_module_api_t -> load_library · get_proc_address · ... │
│ snd_process_api_t -> open · alloc_remote · write · protect · thread │
│ snd_mapping_api_t -> open · view · close (KnownDlls bootstrap) │
│ snd_thread_api_t -> queue_apc · resume · suspend │
│ snd_file_api_t -> load │
├──────────────────┬──────────────────────┬──────────────────────────────────┤
│ Perfil Win32 │ Perfil Nativo │ Trae tu propia mecánica │
│ VirtualAlloc │ NtAllocateVirtual │ Driver · ROP · Exótico │
│ LoadLibraryA │ PEB Walk + EAT │ Funciones definidas por el │
│ │ │ operador │
└──────────────────┴──────────────────────┴──────────────────────────────────┘
En la práctica, esto significa que cada dominio sigue el mismo contrato:
// Reflective loader
snd_ldr_pe_ctx_t ctx = {0};
ctx.raw_source = &payload;
ctx.mem_api = &snd_mem_win; // or snd_mem_nt / snd_mem_sys
ctx.mod_api = &snd_mod_win; // or snd_mod_nt
snd_ldr_pe_prepare_image(&ctx);
snd_ldr_pe_execute_image(&ctx);
// Classic injection
snd_inj_ctx_t inj = {0};
inj.target_pid = 1337;
inj.payload = &shellcode;
inj.proc_api = &snd_proc_sys; // or snd_proc_win / snd_proc_nt
snd_inj_classic_shell(&inj);
snd_inj_cleanup(&inj);
Pipeline en cascada de syscalls
SindriKit trata la resolución de syscalls como una mecánica inyectable, apilando estrategias en orden de prioridad. El motor va cayendo por la cadena hasta que una tiene éxito:
snd_ntdll_set_clean(clean_ntdll);
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 syscalls:
// snd_syscall_set_invoker(snd_syscall_indirect_invoke_asm);
// snd_syscall_set_gadget_finder(snd_syscall_find_gadget_scan);
// or for spoofed syscalls:
// snd_syscall_set_invoker(snd_syscall_spoofed_invoke_asm);
// snd_syscall_set_spoof_finder(snd_syscall_find_spoof_scan);