You're Gonna Carry That Weight

This commit is contained in:
sibouzitoun
2026-06-22 12:38:04 +01:00
commit 5e26626615
162 changed files with 10836 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
# Examples & Proof of Concepts
This directory contains standalone execution wrappers built on top of the SindriKit library.
## Table of Contents
- [loader_winapi.md](loader_winapi.md)
Walkthrough of standard reflective loading using noisy Win32 APIs for pipeline validation.
- [loader_nowinapi.md](loader_nowinapi.md)
Walkthrough of evasive loading using direct syscalls, Hell's Gate, and PEB walking.
- [loader_noCRT_nowinapi.md](loader_noCRT_nowinapi.md)
Walkthrough of the ultimate evasive profile: stripping the MSVC C Runtime entirely for minimal footprint.
- [heavens_gate.md](heavens_gate.md)
Walkthrough of transitioning a 32-bit WoW64 process into native 64-bit execution.
+63
View File
@@ -0,0 +1,63 @@
# PoC: heavens_gate
**Location:** `pocs/heavens_gate/`
This PoC demonstrates SindriKit's capability to transition from a 32-bit WoW64 environment into native 64-bit mode using the `0x33` segment selector (Heaven's Gate).
## What it demonstrates
- Checking whether the current process is running under WoW64.
- Passing a 64-bit function pointer and argument array across the boundary.
- Executing 64-bit shellcode from a 32-bit process and retrieving a 64-bit return value in `RAX`.
## Walkthrough
Because this primitive relies on the WoW64 subsystem, the PoC is only functional when compiled as a 32-bit executable (`x86`) and run on a 64-bit Windows OS.
### Step 1: Validate the Environment
```c
if (!snd_is_wow64()) {
printf("[-] Not running in WOW64... Heaven's Gate requires WOW64.\n");
return SND_STATUS_ARCH_MISMATCH;
}
```
The framework parses the PEB to determine if the 32-bit process is being emulated by the 64-bit OS.
### Step 2: Allocate 64-bit Payload
For demonstration purposes, this PoC uses `VirtualAlloc` to allocate a simple 64-bit shellcode block that loads a magic value into `RAX` and returns:
```nasm
mov rax, 0x1122334455667788
ret
```
```c
unsigned char shellcode64[] = {
0x48, 0xB8, 0x88, 0x77, 0x66,
0x55, 0x44, 0x33, 0x22, 0x11,
0xC3
};
PVOID pExec = VirtualAlloc(NULL, sizeof(shellcode64), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(pExec, shellcode64, sizeof(shellcode64));
```
### Step 3: Transition and Execute
The PoC invokes the `snd_hg_execute_64` API, which performs the segment selector transition internally, executes the provided address, and passes back the 64-bit return value.
```c
UINT64 result = 0;
// Invoke Heaven's Gate with 0 arguments
snd_status_t status = snd_hg_execute_64((UINT64)(ULONG_PTR)pExec, 0, NULL, &result);
if (status.code == SND_SUCCESS) {
// result == 0x1122334455667788
}
```
**OpSec impact:** Bypassing WoW64 completely blinds any security products that have only placed userland hooks inside the 32-bit `ntdll.dll`. The execution happens entirely in native 64-bit mode.
+58
View File
@@ -0,0 +1,58 @@
# Evasive Loader (No-CRT / No-WinAPI)
**Path:** `pocs/loader_noCRT_nowinapi`
This Proof-of-Concept demonstrates the ultimate operational profile of SindriKit: a reflective loader completely independent of both high-level Windows APIs and the Microsoft C Runtime (CRT). By combining direct syscalls via Hell's Gate, PEB module walking, and the `/NODEFAULTLIB` compiler flag, this loader achieves a minimal, stealthy footprint ideal for production implants.
## 1. CRT Independence
When compiled in Release mode (`SND_ENABLE_DEBUG=OFF`), this PoC invokes strict CRT-stripping flags:
```cmake
target_link_options(loader_noCRT_nowinapi PRIVATE
/NODEFAULTLIB
/ENTRY:main
)
```
Without the CRT, standard functions like `memcpy` or `memset` are unavailable. SindriKit compensates for this by selectively compiling `src/common/crt_manifest.c` in Release builds, providing framework-native intrinsic fallbacks. This ensures the compiled artifact contains no implicit telemetry or standard library dependencies.
## 2. Global `ntdll.dll` Resolution
Because the PoC operates without Win32 APIs (like `GetModuleHandle`), it must resolve its own dependencies manually. It does this by walking the Process Environment Block (PEB) to locate `ntdll.dll` by its compile-time hash.
```c
PVOID ntdll;
status = snd_peb_get_module_base_by_hash(SND_HASH_NTDLL_DLL, &ntdll);
```
Once resolved, it globally registers the `ntdll` base using the modules API, allowing the rest of the framework (like the native memory allocator or module loader) to utilize it implicitly.
```c
snd_set_ntdll(ntdll);
```
## 3. Syscall Strategy
The PoC activates the `snd_hell_extract_syscall` strategy. From this point forward, memory allocations and page protections required during the reflective loading process are executed via dynamically resolved syscalls, entirely bypassing user-land hooks in `ntdll.dll`.
```c
snd_set_syscall_strategy(snd_hell_extract_syscall);
```
## 4. Execution
Like the other loaders, the context is populated with the Native APIs (`snd_mem_native`, `snd_mod_native`), and the target payload is loaded, mapped, and executed reflectively from memory.
## Building and Running
To compile this PoC specifically, ensure you are building in Release mode:
```bash
# Debug must be OFF to strip the CRT
cmake -B build -DSND_BUILD_PAYLOADS=ON -DSND_ENABLE_DEBUG=OFF
cmake --build build --config Release
```
Execution:
```bash
build\pocs\loader_noCRT_nowinapi\Release\loader_noCRT_nowinapi.exe
```
+71
View File
@@ -0,0 +1,71 @@
# PoC: loader_nowinapi
**Location:** `pocs/loader_nowinapi/`
This PoC drops the entire Win32 API layer. It retrieves a clean `ntdll.dll` from KnownDlls, configures a cascading SSN resolution pipeline, and then loads the payload using only direct kernel syscalls and PEB walking.
## What it demonstrates
- The full SindriKit bootstrapping sequence required before any native primitive can be used.
- The complete cascading syscall pipeline covering four EDR hook evasion strategies.
- That the loader's core logic is entirely unchanged — only the injected API tables differ from `loader_winapi`.
## Walkthrough
The bootstrapping phase must complete before the loader context is initialized.
### Step 1: Retrieve a clean `ntdll.dll` from KnownDlls
```c
PVOID clean_ntdll = NULL;
// Configure the KnownDlls loader to use Win32 wrappers for the initial bootstrap.
// (Native strategy is available once the syscall pipeline itself is armed.)
snd_status_t status = snd_map_knowndll(&snd_knowndlls_win, L"ntdll.dll", &clean_ntdll);
```
This maps a clean, pre-hook copy of `ntdll.dll` directly from the `\KnownDlls` Object Manager directory. The EDR's hooks on the PEB-resident copy do not exist in this mapping.
### Step 2: Feed the clean base to the global cache
```c
snd_set_ntdll(clean_ntdll);
```
This globally registers the unhooked `ntdll.dll` base. It will be used by the syscall resolution pipeline to extract unhooked stub bytes, and by the Native module API (`snd_mod_native`) to implicitly resolve APIs like `LdrLoadDll` without additional PEB lookups.
### Step 3: Configure the cascading syscall pipeline
```c
snd_set_syscall_strategy(snd_hell_extract_syscall);
snd_add_syscall_strategy(snd_halo_extract_syscall);
snd_add_syscall_strategy(snd_tartarus_extract_syscall);
snd_add_syscall_strategy(snd_veles_extract_syscall);
```
`snd_resolve_syscall` will now attempt each strategy in order, returning on the first success. This covers unhooked stubs (Hell's Gate), `0xE9`-hooked stubs (Halo's Gate), `0xEB`-hooked stubs (Tartarus' Gate), and the `syscall`-anchor fallback (VelesReek).
### Step 4: Load the payload and initialize the loader context
```c
snd_buffer_t payload = { ... }; // raw PE bytes from disk
snd_loader_ctx_t ctx = {0};
ctx.raw_source = &payload;
ctx.mem_api = &snd_mem_native; // -> NtAllocateVirtualMemory via direct syscall
ctx.mod_api = &snd_mod_native; // -> PEB walking + manual export table parsing
```
### Step 5: Execute
```c
snd_status_t s = snd_prepare_reflective_image(&ctx);
if (s.code != SND_SUCCESS) {
snd_status_print(s);
return 1;
}
s = snd_execute_reflective_image(&ctx);
```
**OpSec impact:** `VirtualAlloc` and `VirtualProtect` are never called. Memory allocation goes directly to `NtAllocateVirtualMemory` via the SSN resolved from the clean KnownDlls ntdll copy. Import resolution uses PEB walking for module base lookup and manual export table parsing for symbol resolution.
+44
View File
@@ -0,0 +1,44 @@
# PoC: loader_winapi
**Location:** `pocs/loader_winapi/`
This PoC loads a raw PE payload from disk using standard, fully documented Win32 APIs throughout. Every memory operation (`VirtualAlloc`, `VirtualProtect`) and every module operation (`LoadLibraryA`, `GetProcAddress`) hits the standard API layer and any EDR hooks installed on it. It is intended strictly for diagnostic use and pipeline validation, not operational deployment.
## What it demonstrates
- The baseline reflective loading pipeline: parse → alloc → map → relocate → resolve imports → protect → TLS → execute.
- That the context-based architecture works correctly before introducing evasion complexity.
- A clean baseline to diff against when debugging why a stealth variant fails.
## Walkthrough
No syscall bootstrapping is required. The setup reduces to injecting the Win32-backed API tables and calling the execution chain wrapper:
```c
// Read the raw PE payload from disk into a buffer
snd_buffer_t payload = { ... };
// Initialize the loader context with Win32 primitives
snd_loader_ctx_t ctx = {0};
ctx.raw_source = &payload;
ctx.mem_api = &snd_mem_win; // -> VirtualAlloc / VirtualProtect
ctx.mod_api = &snd_mod_win; // -> LoadLibraryA / GetProcAddress
// Run the full prepare chain (parse, alloc, map, relocate, IAT, protect, TLS)
snd_status_t s = snd_prepare_reflective_image(&ctx);
if (s.code != SND_SUCCESS) {
snd_status_print(s);
return 1;
}
// Execute the entry point
s = snd_execute_reflective_image(&ctx);
if (s.code != SND_SUCCESS) {
snd_status_print(s);
}
// Optional cleanup
snd_free_mapped_image(&ctx);
```
**OpSec impact:** Every allocation and protection change is made via documented Win32 APIs. Any EDR with userland hooks on `VirtualAlloc` and `VirtualProtect` will see every operation in full. String artifacts from `LoadLibraryA` calls appear in the call stack. This profile is an absolute EDR flare.