
SindriKit v1.6.0
Una biblioteca C fundamental para construir capacidades ofensivas operativamente creíbles.
SindriKit
El desarrollo ofensivo merece una mejor arquitectura.
Una librería en C para construir capacidades ofensivas.
Concepto central
La mayoría de las utilidades ofensivas incrustan sus mecánicas de ejecución dentro de la lógica de la técnica. Un cargador reflectivo no solo mapea una imagen; la mapea usando una cadena específica y fija de llamadas a VirtualAlloc o NTAPI nativas. Cuando un EDR comienza a monitorear esa cadena específica, te ves obligado a reescribir toda la herramienta.
SindriKit resuelve esto aplicando 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.
- Los mecanismos de ejecución: (p. ej., API Win32, NTAPI nativa, syscalls directas) se encuentran dentro de tablas de API independientes y se inyectan en la técnica en tiempo de ejecución.
Al trasladar los mecanismos de ejecución a punteros de función en tiempo de ejecución, puedes cambiar toda tu estrategia de llamadas Win32 a syscalls directas con una sola línea de código—sin cambiar tu lógica de ejecución de payloads.
Arquitectura de diseño
- Perfiles de ejecución desacoplados: Intercambia los comportamientos subyacentes de manipulación de memoria, módulos y hilos mediante tablas de punteros a función sin romper la técnica invocadora.
- Fallos de syscall en cascada: Resolvedores de SSN enchufables (
snd_syscall_resolve_ssn_scan,snd_syscall_resolve_ssn_sort) con una cadena de prioridad: intercambia o extiende estrategias sin tocar el código de dominio. - Ofuscación en tiempo de compilación: Los algoritmos de hash de cadenas y API (DJB2, FNV1A) se pueden intercambiar globalmente vía CMake. Compilar aleatoriza automáticamente la semilla global para alterar las firmas estáticas.
- Motor de mutación: Habilita polimorfismo profundo vía
SND_MORPH. Genera firmas binarias únicas en cada compilación inyectando predicados opacos volátiles en el código C, NOPs matemáticamente equivalentes en los stubs de ensamblador y reordenando el diseño de memoria de las estructuras centrales. - Compilaciones Release: Un nivel silencioso elimina todas las cadenas de diagnóstico, descriptores de archivo y marcos de seguimiento del binario final, reduciendo tu huella estática a primitivas desnudas.
Integrando 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, resolución de syscalls, carga reflectiva...
El motor
Capa de abstracción de API
┌────────────────────────────────────────────────────────────────────────────┐
│ ANY OFFENSIVE INTENT │
│ Loader · Injector · Spoofer · Patcher · Bypasser · Harvester · ... │
├────────────────────────────────────────────────────────────────────────────┤
│ SINDRIKIT API ABSTRACTION LAYER │
│ 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 │
│ [ future tables ] -> thread · object · ... │
├──────────────────┬──────────────────────┬──────────────────────────────────┤
│ Win32 Profile │ Native Profile │ Bring Your Own Mechanic │
│ VirtualAlloc │ NtAllocateVirtual │ Driver · ROP · Exotic │
│ LoadLibraryA │ PEB Walk + EAT │ Operator-defined functions │
└──────────────────┴──────────────────────┴──────────────────────────────────┘
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 de syscalls en cascada
SindriKit trata la resolución de syscalls como un mecanismo inyectable, apilando estrategias en orden de prioridad. El motor va probando hasta que una tenga éxito:
snd_syscall_set_ntdll(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);
El invocador está desacoplado de la resolución de SSN: cambia entre syscalls directas e indirectas sin modificar el código de dominio. La invocación indirecta salta a un gadget legítimo de NTDLL, manteniendo la dirección de retorno de la syscall dentro de ntdll.dll.
Agilidad de algoritmos en tiempo de compilación
Cada nombre de API y cadena de módulo se elimina del binario final en tiempo de compilación mediante una sola variable de CMake:
set(SND_HASH_ALGO "FNV1A") # or DJB2 recomputes everything automatically
set(SND_RANDOMIZE_SEED ON) # generates a fresh 32-bit seed on next configure
Cada hash se calcula con una semilla generada aleatoriamente (si SND_RANDOMIZE_SEED=ON). La huella estática cambia por completo entre compilaciones sin tocar una línea de C.
FFI dinámico consciente de la arquitectura
Un puente de ensamblado MASM personalizado para la invocación arbitraria de funciones en tiempo de ejecución. Las compilaciones x64 siguen la convención de llamada de Microsoft x64 con precisión (espacio de sombra, colocación de argumentos en registros, alineación de pila). Las compilaciones x86 empujan los argumentos en orden inverso con soporte para destinos cdecl y stdcall.
Analizador de PE con verificación de límites
Un analizador PE32/PE32+ unificado con un indicador is_mapped que maneja correctamente tanto imágenes crudas en disco como vistas mapeadas en memoria. Cada acceso al directorio de datos se valida contra los límites del búfer rastreado antes de desreferenciar. La resolución de exportaciones admite cadenas de reenviadores (forwarders) de hasta profundidad 4 con búsqueda basada en hash.
Probado contra:
- Más de 40 combinaciones de pruebas principales dirigidas a EXEs y DLLs con casos límite, argumentos inválidos, exportaciones faltantes y callbacks TLS en x86 y x64.
- Más de 100 mutaciones dinámicas de PE generadas por el módulo
pe_mutator: nombres de sección en cero, desbordamientos de enteros, límites inválidos dee_lfanew, importaciones alteradas. - Corpus completo de Corkami: carga limpiamente muestras válidas y rechaza limpiamente las malformadas sin fallar en el 99% de las muestras.
Contextos de dominio con seguimiento de estado
Cada operación ofensiva se gestiona mediante una estructura de contexto discreta con enumeración de etapas. Las operaciones se pueden pausar entre etapas para ofuscación de suspensión o despliegue por etapas, reanudarse limpiamente e inspeccionarse para conocer el punto de fallo exacto hasta el subsistema y el motivo.
La filosofía de diseño de la API
Inicializa el pipeline de syscalls una vez (patrón típico):
PVOID clean_ntdll = NULL;
snd_om_knowndll_map(&snd_map_nt, L"ntdll.dll", &clean_ntdll);
snd_syscall_set_ntdll(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);
El invocador está desacoplado de la resolución de SSN: cambia entre syscalls directas e indirectas sin modificar el código de dominio. La invocación indirecta salta a un gadget legítimo de NTDLL, manteniendo la dirección de retorno de la syscall dentro de ntdll.dll.
Intercambia el perfil de ejecución con una sola asignación:
ctx.mem_api = &snd_mem_win; // diagnostic
ctx.mem_api = &snd_mem_nt; // NT stubs via PEB + EAT
ctx.mem_api = &snd_mem_sys; // direct syscalls (pipeline required)
La resolución de módulos sigue el mismo patrón (snd_mod_win vs snd_mod_nt). No existe un backend de módulos respaldado por syscalls: las importaciones usan PEB walk + EAT incluso en perfiles _sys completos.
Niveles de compilación
Nivel de depuración — SND_ENABLE_DEBUG=ON
Para desarrollo local. snd_status_t se expande para incluir file, line y un búfer de contexto context de 128 bytes. SND_ERR_CTX y SND_DEBUG_PRINT emiten transiciones de la máquina de estados, valores de campos PE analizados y resultados de resolución de syscalls. Usa SND_USE_PRINTF=ON para enviar la salida a stdout en lugar de a la consola de depuración.
Nivel silencioso — SND_ENABLE_DEBUG=OFF
La configuración de despliegue estándar para binarios operacionales. Cada cadena de diagnóstico, referencia de archivo y número de línea se elimina por completo en la compilación. snd_status_t se reduce a dos enteros. Nada más.
set(SND_ENABLE_DEBUG OFF CACHE BOOL "")
set(SND_BUILD_PAYLOADS OFF CACHE BOOL "")
set(SND_RANDOMIZE_SEED ON CACHE BOOL "")
set(SND_USE_DEFAULTS ON CACHE BOOL "")
set(SND_HASH_ALGO "DJB2" CACHE STRING "")
add_subdirectory(vendor/SindriKit)
target_link_libraries(my_tool PRIVATE sindri::engine)
Documentación
Referencia completa en docs/:
- Primeros pasos — CMake, niveles de compilación, arranque de DI, primer flujo de trabajo de cargador/inyección
- Arquitectura — Inyección de dependencias, máquinas de estado, sistema de estado
- Primitivas — Memoria, módulos, procesos, mapeo, syscalls, ejecución (FFI)
- Cargadores — Pipeline PE reflectivo
- Inyección — Inyección clásica de shellcode y PE
- Analizadores — Subdominios de PE y env (PEB)
- Comunes — Helpers sin CRT, buffers, hashing, estado
- Ejemplos y PoCs —
loader_winapi,loader_nowinapi,inject_pe,inject_shell,heavens_gate - Pruebas — Ejecutor de integración, mutador de PE
Planeado: Evasion dominio.
Aviso legal
SindriKit está diseñado únicamente para fines educativos, de investigación y Red Teaming autorizado. Para conocer el aviso legal completo y la información sobre consideraciones de OpSec, consulta la Política de seguridad.
Licencia