
SindriKit v2.0.0
Una libreria C fondamentale per costruire capacità offensive credibili a livello operativo
SindriKit
Lo sviluppo offensivo merita un'architettura migliore.
Una libreria C per costruire capacità offensive.
Concetto di base
La maggior parte delle utility offensive codifica in modo rigido le proprie meccaniche di esecuzione all'interno della logica della tecnica. Un reflective loader non si limita a mappare un'immagine; la mappa utilizzando una catena specifica e hardcoded di chiamate VirtualAlloc o NTAPI native. Quando un EDR inizia a monitorare quella catena specifica, sei costretto a riscrivere l'intero strumento.
SindriKit risolve questo problema imponendo una separazione delle responsabilità tramite tabelle di astrazione delle interfacce:
- La logica della tecnica: (ad es. loader, injection, patcher) si occupa del tracciamento dello stato e dell'orchestrazione dei dati. Non ha alcuna conoscenza di come viene allocata la memoria o di come vengono creati i thread.
- Le meccaniche di esecuzione: (ad es. Win32 API, Native NTAPI, Direct Syscalls) risiedono in tabelle API indipendenti e vengono iniettate nella tecnica a runtime.
Spostando le meccaniche di esecuzione su puntatori a funzione a runtime, puoi scambiare l'intera strategia da chiamate Win32 a syscall dirette raw con una singola riga di codice—senza modificare la logica di esecuzione del payload.
Architettura di progettazione
- Profili di esecuzione disaccoppiati: Scambia le meccaniche di memoria, moduli, mapping, processi, thread e file tramite tabelle indipendenti di puntatori a funzione (
snd_memory_api_t,snd_module_api_t,snd_process_api_t,snd_thread_api_t,snd_mapping_api_t,snd_file_api_t) senza toccare la logica della tecnica. - Copertura delle tecniche: Caricamento riflessivo PE (EXE/DLL) e COFF/BOF, injection classica ed early-bird APC su shellcode/PE/COFF, più FFI architecture-aware e Heaven's Gate — tutto sugli stessi profili componibili.
- Pipeline di syscall a cascata: Resolver SSN pluggable (
snd_syscall_resolve_ssn_scan,snd_syscall_resolve_ssn_sort) con una catena di priorità, disaccoppiati dagli invoker: direct, indirect (gadget NTDLL), o spoofed (spoofing dinamico dello stack di chiamata Fat-Frame). - Stato codificato per facility: Ogni chiamata fallibile restituisce
snd_status_t— un codice facility/locale impacchettato più l'errore OS catturato, con stringhe di contesto che vengono eliminate in fase di compilazione nel tier silent. - Offuscamento a compile-time: Gli algoritmi di hashing di stringhe e API (DJB2, FNV1A) possono essere scambiati globalmente tramite CMake. La compilazione randomizza automaticamente il seed globale per alterare le firme statiche.
- Motore di mutazione: Abilita un polimorfismo profondo tramite
SND_MORPH. Genera firme binarie uniche a ogni build iniettando predicati opachi volatili nel codice C, math/NOP funzionalmente equivalenti negli stub Assembly, e rimescolando il layout di memoria delle strutture core. - Build di release: Un tier silent rimuove tutte le stringhe diagnostiche, i descrittori di file e i frame di tracciamento; le build
SND_CRTLESSvanno oltre con/NODEFAULTLIB, nessun header SDK, un frontend PEB, e solo backend nativi.
Avvio rapido
Il repository fornisce una singola CLI unified che esercita ogni profilo:
build.bat pocs
build64\pocs\Release\unified.exe load pe -f payload.dll -e Run --sys
unified supporta load pe|coff, inject classic|apc|hijack (shell, PE, COFF), e hg, ciascuno su --win/--nt/--sys. Vedi Esempi & PoC e Guida introduttiva.
Integrare 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 due righe perché il tuo strumento erediti tutte le capacità di SindriKit: parsing PE e COFF, caricamento riflessivo, syscall a cascata, e profili di injection.
Il motore
Livello di astrazione delle 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 │
│ snd_mapping_api_t -> open · view · close (KnownDlls bootstrap) │
│ snd_thread_api_t -> queue_apc · resume · suspend │
│ snd_file_api_t -> load │
├──────────────────┬──────────────────────┬──────────────────────────────────┤
│ Win32 Profile │ Native Profile │ Bring Your Own Mechanic │
│ VirtualAlloc │ NtAllocateVirtual │ Driver · ROP · Exotic │
│ LoadLibraryA │ PEB Walk + EAT │ Operator-defined functions │
└──────────────────┴──────────────────────┴──────────────────────────────────┘
In pratica, questo significa che ogni dominio segue lo stesso contratto:
// 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 di syscall a cascata
SindriKit tratta la risoluzione delle syscall come una meccanica iniettabile, impilando strategie in ordine di priorità. Il motore procede a cascata finché una non riesce:
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);
L'invoker è disaccoppiato dalla risoluzione SSN — passa tra syscall dirette, indirette e spoofed senza modificare il codice del dominio. L'invocazione indiretta salta a un gadget NTDLL legittimo così l'indirizzo di ritorno rimane dentro ntdll.dll; l'invocazione spoofed pianta inoltre un indirizzo di ritorno del chiamante genuino dentro un "Fat Frame" scoperto dinamicamente, così gli unwind dello stack di chiamata rimangono coerenti.