Valak evasion DLL for Sliver implants. ChaCha20 encrypted sleep, synthetic callstack frames via indirect syscalls, HWBP AMSI/ETW bypass, FreshyCalls, CRT-free.

This commit is contained in:
2026-07-18 09:30:00 +01:00
parent fe2726a430
commit 7ecc30f1cd
24 changed files with 727 additions and 466 deletions
+44 -46
View File
@@ -1,60 +1,58 @@
<p align="center">
<img src="assets/Valak.png" alt="Valak" width="600">
</p>
# Valak
## What
Zig DLL for Sliver implants. ChaCha20 encrypted sleep via indirect syscalls with synthetic callstack frames. HWBP AMSI/ETW bypass, no memory touched. FreshyCalls syscall extraction immune to inline hooks. CRT-free.
Standalone Zig evasion DLL for C2 implants. Drop-in sleep obfuscation, AMSI/ETW bypass, callstack spoofing. Protocol-agnostic — built for Sliver but works with any C2 that can call `syscall.SyscallN`.
For initial delivery use [Kage](https://github.com/Yenn503/Kage), minimal syscall-based shellcode loader.
## Evasion Stack
## Why Zig over C
| Technique | File | Detection Status (DbgMan, May 2026) |
|---|---|---|
| RC4 encrypted .text sleep | sleep.zig | 70% effective — core evasion primitive |
| Callstack return-address zeroing | arch/hells_gate.s | 55% effective — terminates EDR frame walks |
| HWBP AMSI bypass (DR0-VEH) | amsi.zig | 60% effective — no memory modification |
| HWBP ETW bypass (DR0-VEH) | etw.zig | 65% effective — no memory modification |
| FreshyCalls SSN extraction | syscall.zig | 65% effective — immune to inline hooks |
| Indirect syscall dispatch | syscall.zig | 60% effective — random gadget pool |
| KnownDlls ntdll unhooking | unhook.zig | 95% DETECTED by CrowdStrike/S1 |
| Module stomping | stomp.zig | 80% DETECTED — backing-file integrity checks |
| Token manipulation | token.zig | 90% DETECTED — lsass token access is T1 alert |
No CRT linked, smaller binary, fewer imports for AV to flag. Comptime guarantees struct layouts match the PE spec without padding bugs. All the Win32 types, inline assembly, and raw pointer math of C but the compiler refuses to build if you get a struct offset wrong.
Valak replaces `time.Sleep()` in your implant's beacon loop with ChaCha20-encrypted sleep via indirect syscalls. During sleep your implant's .text is PAGE_NOACCESS, scanners get access violation. On wake, it restores and decrypts.
## How it works
Every time Sliver would normally call `time.Sleep(interval)`, Valak runs this instead:
```
1. ChaCha20 encrypts Sliver's .text section in memory (SystemFunction040)
2. Protects .text to PAGE_NOACCESS — read, write, and execute all blocked
3. NtDelayExecution(interval) via indirect syscall with random gadget
4. EDR scanner sees encrypted garbage or access violation, not Go runtime
5. On wake: protects back to PAGE_EXECUTE_READ, ChaCha20 decrypts
6. Returns to Sliver, which continues normal beacon operations
```
The callstack during sleep shows kernel32!BaseThreadInitThunk → ntdll!RtlUserThreadStart — what every legitimate Windows thread looks like. No gap, no zeroed return address.
## Evasion stack
| Technique | How |
|---|---|
| ChaCha20 encrypted .text sleep | SystemFunction040/041 → NtDelayExecution + PAGE_NOACCESS |
| Synthetic callstack frames | kernel32!BaseThreadInitThunk → ntdll!RtlUserThreadStart |
| HWBP AMSI bypass | DR0 + VEH, no memory modified |
| HWBP ETW bypass | DR0 + VEH, no memory modified |
| FreshyCalls syscall extraction | ntdll export table sorted by RVA, immune to inline hooks |
| Indirect syscalls | Random gadget pool (64+ `syscall;ret` from ntdll .text) |
| CRT-free | No libc import, minimal IAT footprint |
## Build
```
cd evasion
zig build -Doptimize=ReleaseFast
cd evasion && zig build -Doptimize=ReleaseFast
# → zig-out/bin/valak.dll
```
Then embed the DLL bytes into `go-bridge/embed_dll.go`:
```go
var embeddedDLL = []byte{
// paste compiled .dll bytes
}
```
## Sliver integration
## Sliver Integration
See [docs/sliver-integration.md](docs/sliver-integration.md). TL;DR:
1. Copy `go-bridge/` into `implant/sliver/evasion/valak/`
2. In Sliver's implant init:
```go
import "github.com/BishopFox/sliver/implant/sliver/evasion/valak"
func init() {
valak.Start()
go func() {
time.Sleep(2 * time.Second) // wait for DLL load
valak.PatchAll()
}()
}
```
3. Replace `time.Sleep(d)` with `valak.EvasionSleep(d)` in Sliver's beacon loop
4. Build with: `go build -tags evasion`
## Verified Against
- Microsoft x64 ABI (shadow space, 16-byte alignment)
- PE/COFF .drectve section spec
- Go compiler no-auto-vectorize behavior
- DbgMan "EDR Tradecraft" (May 2026)
- CrowdStrike 2026 Global Threat Report
1. Embed valak.dll bytes into `go-bridge/embed_dll.go`
2. Drop `go-bridge/` into Sliver's `implant/sliver/evasion/valak/`
3. Replace `time.Sleep(d)` with `valak.EvasionSleep(d)` in runner.go
4. Build: `garble -tiny -literals -seed=random build -tags evasion -ldflags="-s -w -H windowsgui"`