
SindriKit v2.0.0
Uma biblioteca C fundamental para construir capacidades ofensivas operacionalmente críveis.
SindriKit
O Desenvolvimento Ofensivo Merece uma Arquitetura Melhor.
Uma biblioteca C para construir capacidades ofensivas.
Conceito Central
A maioria dos utilitários ofensivos codifica rigidamente seus mecanismos de execução dentro da lógica da técnica. Um loader reflexivo não apenas mapeia uma imagem; ele a mapeia usando uma cadeia específica e codificada de chamadas VirtualAlloc ou NTAPI nativas. Quando um EDR começa a monitorar essa cadeia específica, você é forçado a reescrever a ferramenta inteira.
O SindriKit resolve isso impondo uma separação de responsabilidades por meio de tabelas de abstração de interface:
- A Lógica da Técnica: (ex.: loaders, injeções, patchers) lida com o rastreamento de estado e a orquestração de dados. Ela não tem conhecimento de como a memória é alocada ou como as threads são criadas.
- Os Mecanismos de Execução: (ex.: Win32 API, NTAPI Nativa, Syscalls Diretas) estão dentro de tabelas de API independentes e são injetados na técnica em tempo de execução.
Ao deslocar os mecanismos de execução para ponteiros de função em tempo de execução, você pode trocar toda a sua estratégia de chamadas Win32 para syscalls diretas brutas com uma única linha de código—sem alterar a lógica de execução do seu payload.
Arquitetura de Design
- Perfis de Execução Desacoplados: Troque os comportamentos subjacentes de manipulação de memória, módulo e thread por meio de tabelas de ponteiros de função sem quebrar a técnica chamadora.
- Fallbacks em Cascata de Syscalls: Resolvedores de SSN plugáveis (
snd_syscall_resolve_ssn_scan,snd_syscall_resolve_ssn_sort) com uma cadeia de prioridade — troque ou estenda estratégias sem tocar no código de domínio. - Ofuscação em Tempo de Compilação: Algoritmos de hash de strings e APIs (DJB2, FNV1A) podem ser trocados globalmente via CMake. A compilação randomiza automaticamente a seed global para alterar assinaturas estáticas.
- Motor de Mutação: Habilita polimorfismo profundo via
SND_MORPH. Gera assinaturas binárias únicas a cada build ao injetar predicados opacos voláteis em código C, matemática/NOPs funcionalmente equivalentes em stubs Assembly, e embaralhar o layout de memória de structs centrais. - Builds de Release: Uma camada silenciosa remove todas as strings de diagnóstico, descritores de arquivo e frames de rastreamento do binário final, reduzindo sua pegada estática a primitivas básicas.
Integrando o 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
Apenas duas linhas para que sua ferramenta herde todas as capacidades do SindriKit: parsing de PE, resolução de syscalls, carregamento reflexivo...
O Motor
Camada de Abstração de API
┌────────────────────────────────────────────────────────────────────────────┐
│ QUALQUER INTENÇÃO OFENSIVA │
│ Loader · Injector · Spoofer · Patcher · Bypasser · Harvester · ... │
├────────────────────────────────────────────────────────────────────────────┤
│ CAMADA DE ABSTRAÇÃO DE API DO 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 │
│ [ tabelas futuras ] -> thread · object · ... │
├──────────────────┬──────────────────────┬──────────────────────────────────┤
│ Perfil Win32 │ Perfil Nativo │ Traga Seu Próprio Mecanismo │
│ VirtualAlloc │ NtAllocateVirtual │ Driver · ROP · Exótico │
│ LoadLibraryA │ PEB Walk + EAT │ Funções definidas pelo operador │
└──────────────────┴──────────────────────┴──────────────────────────────────┘
Na prática, isso significa que todo domínio segue o mesmo 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 em Cascata
O SindriKit trata a resolução de syscalls como um mecanismo injetável, empilhando estratégias em ordem de prioridade. O motor percorre a cadeia até que uma tenha sucesso:
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);
O invocador é desacoplado da resolução de SSN — alterne entre syscalls diretas e indiretas sem modificar o código de domínio. A invocação indireta salta para um gadget legítimo da NTDLL, mantendo o endereço de retorno da syscall dentro de ntdll.dll.
Agilidade de Algoritmos em Tempo de Compilação
Todo nome de API e string de módulo é removido do binário final em tempo de compilação por meio de uma única variável 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 é calculado com uma seed gerada aleatoriamente (se SND_RANDOMIZE_SEED=ON). A pegada estática muda completamente entre compilações sem tocar em uma linha de C.
FFI Dinâmica com Consciência de Arquitetura
Uma ponte assembly MASM personalizada para invocação arbitrária de funções em tempo de execução. Builds x64 seguem precisamente a convenção de chamada Microsoft x64 (shadow space, posicionamento de argumentos em registradores, alinhamento de pilha). Builds x86 empilham argumentos em ordem reversa com suporte tanto para alvos cdecl quanto stdcall.
Parser de PE com Verificação de Limites
Um parser unificado PE32/PE32+ com uma flag is_mapped que lida corretamente tanto com imagens brutas em disco quanto com views mapeadas em memória. Todo acesso a data directory é validado contra os limites do buffer rastreado antes da desreferenciação. A resolução de exportações suporta cadeias de forwarders até profundidade 4 com busca baseada em hash.
Testado contra:
- Mais de 40 combinações de testes centrais visando EXEs de casos extremos, DLLs, argumentos inválidos, exportações ausentes e callbacks TLS em x86 e x64.
- Mais de 100 mutações dinâmicas de PE geradas pelo módulo
pe_mutator: nomes de seção zerados, overflows de inteiros, limites inválidos dee_lfanew, imports corrompidos. - Corpus completo do Corkami: carrega amostras válidas de forma limpa, rejeita amostras malformadas de forma limpa sem travar em 99% das amostras.
Contextos de Domínio com Rastreamento de Estado
Toda operação ofensiva é gerenciada por meio de uma estrutura de contexto discreta com enumeração de estágios. As operações podem ser pausadas entre estágios para ofuscação de sleep ou implantação em estágios, retomadas de forma limpa, e inspecionadas quanto ao ponto exato de falha até o subsistema e o motivo.
A Filosofia de Design da API
Inicialize o pipeline de syscalls uma vez (padrão típico):
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);
O invocador é desacoplado da resolução de SSN — alterne entre syscalls diretas e indiretas sem modificar o código de domínio. A invocação indireta salta para um gadget legítimo da NTDLL, mantendo o endereço de retorno da syscall dentro de ntdll.dll.
Troque o perfil de execução com uma única atribuição:
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)
A resolução de módulos segue o mesmo padrão (snd_mod_win vs snd_mod_nt). Não há backend de módulo baseado em syscalls — os imports usam PEB walk + EAT mesmo em perfis _sys completos.
Camadas de Build
Camada de Debug — SND_ENABLE_DEBUG=ON
Para desenvolvimento local. snd_status_t expande para incluir file, line e um buffer de string context de 128 bytes. SND_ERR_CTX e SND_DEBUG_PRINT emitem transições de máquina de estados, valores de campos de PE parseados e resultados de resolução de syscalls. Use SND_USE_PRINTF=ON para direcionar a saída para stdout em vez do console de debug.
Camada Silenciosa — SND_ENABLE_DEBUG=OFF
A configuração padrão de implantação para binários operacionais. Toda string de diagnóstico, referência de arquivo e número de linha é compilada para fora completamente. snd_status_t colapsa para dois inteiros. Nada mais.
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)
Documentação
Referência completa em docs/:
- Getting Started — CMake, camadas de build, bootstrap de DI, primeiro fluxo de trabalho de loader/injeção
- Architecture — Injeção de dependência, máquinas de estado, sistema de status
- Primitives — Memória, módulos, processo, mapeamento, syscalls, execução (FFI)
- Loaders — Pipeline de PE reflexivo
- Injection — Injeção clássica de shellcode e PE
- Parsers — Subdomínios PE e env (PEB)
- Common — Helpers sem CRT, buffers, hashing, status
- Examples & PoCs — Perfis executáveis
unified(load, inject, hg) - Tests — Runner de integração, mutador de PE
Planejado: domínio Evasion.
Aviso Legal
O SindriKit é construído apenas para fins educacionais, de pesquisa e Red Teaming autorizado. Para o aviso legal completo e informações sobre considerações de OpSec, consulte a Política de Segurança.
Licença