Windows OPSEC
Windows agents can be compiled with an additional set of pre-flight and runtime hardening modules that target the Windows detection surface. These modules are independent of the Linux OPSEC suite and are enabled via separate ldflags at generate time.
All modules in this section are Windows-only. They compile to no-ops on Linux. On Windows they run before the first beacon and remain active for the agent's lifetime.
Module overview
| Module | Category | What it does |
|---|---|---|
etw-patch |
Pre-flight | Patches ETW (Event Tracing for Windows) to suppress kernel telemetry events |
amsi-bypass |
Pre-flight | Patches AMSI to return AMSI_RESULT_CLEAN for all scans |
ppid-spoof |
Pre-flight | Spoofs the parent process ID of the agent process at spawn time |
ntdll-unhook |
Pre-flight | Restores ntdll.dll from a clean on-disk copy to remove AV/EDR inline hooks |
indirect-syscall |
Runtime | Replaces Nt* API calls with indirect syscall stubs to avoid userland hook detection |
sleepmask-win |
Runtime | XOR-masks agent memory region and flips page protection during sleep (Windows equivalent) |
kill-date |
Lifecycle | Agent self-terminates after a hardcoded expiry timestamp |
working-hours |
Lifecycle | Agent beacons only within a configured time window; sleeps outside it |
etw-patch
Category: Pre-flight
Ldflag: embeddedWinEtwPatch=true
Writes a ret stub (or xor eax,eax / ret on x64) to the entry point of EtwEventWrite in the process's ntdll.dll mapping. This prevents the ETW provider from writing process-creation and module-load events to the NT kernel logger session, which feeds Windows Defender, Sysmon, and many EDR kernel callbacks.
ETW patching suppresses userland telemetry only. Kernel-mode callbacks registered by EDR drivers (PsSetCreateProcessNotifyRoutine, ObRegisterCallbacks) are not bypassed by this module.
amsi-bypass
Category: Pre-flight
Ldflag: embeddedWinAmsiBypass=true
Patches AmsiScanBuffer in amsi.dll to unconditionally return AMSI_RESULT_CLEAN (0x1). The patch is applied to the in-process memory mapping of amsi.dll; it does not touch the on-disk file.
Effective against PowerShell AMSI, .NET AMSI, VBA AMSI, and any in-process AMSI consumer that loads amsi.dll into the same process.
ppid-spoof
Category: Pre-flight
Ldflag: embeddedWinPpidSpoof=true, embeddedWinPpidTarget=<process-name>
Uses PROC_THREAD_ATTRIBUTE_PARENT_PROCESS to assign a spoofed parent PID when the agent process is created. The target parent is resolved by name at runtime (defaults to explorer.exe) and passed as an inheritable handle to CreateProcess.
This causes process-tree tools (Process Hacker, Sysmon Event ID 1) to show the agent parented under the spoofed process rather than the actual launcher.
# Spoof parent as svchost.exe (default: explorer.exe)
sentrava > generate --os windows --win-ppid-target svchost.exe --win-opsec ppid-spoof --listener <ip>:4433
ntdll-unhook
Category: Pre-flight
Ldflag: embeddedWinNtdllUnhook=true
Opens a fresh file handle to ntdll.dll on disk, maps it into memory, and copies the clean .text section over the in-process mapping. This overwrites any inline hooks (5-byte JMP patches) injected by EDR userland components, restoring native syscall thunks.
Execution order: runs before AMSI bypass and ETW patch to ensure all subsequent patching goes through clean thunks.
indirect-syscall
Category: Runtime
Ldflag: embeddedWinIndirectSyscall=true
Replaces direct Nt* Win32 API calls with assembly stubs that invoke the syscall instruction at an address inside ntdll.dll (not inside the agent's own code section). This technique:
- Avoids userland hooks that intercept the standard call path through
ntdll - Causes the kernel's stack trace to show a return address inside
ntdllrather than the agent - Defeats EDR "syscall origin" checks that flag syscalls with unbacked return addresses
Syscall numbers (SSN) are resolved dynamically at runtime by parsing the ntdll.dll export table, avoiding hardcoded SSN tables that differ between Windows versions.
sleepmask-win
Category: Runtime
Ldflag: embeddedWinSleepMask=true
Windows equivalent of the Linux sleepmask module. During the beacon sleep interval:
- XOR-masks the agent's heap and stack regions with a random key
- Changes page protection of agent memory to
PAGE_NOACCESSviaVirtualProtect - Calls
SleepExfor the configured interval - Restores
PAGE_EXECUTE_READ_WRITEand re-randomizes the XOR key on wake
Makes the agent invisible to memory scanners that look for readable/executable shellcode during sleep.
kill-date
Category: Lifecycle
Ldflag: embeddedKillDate=<unix-timestamp>
The agent checks the current system clock against the embedded kill timestamp on every check-in cycle. When the current time exceeds the kill date, the agent exits immediately and removes itself from disk (if --self-delete is also set).
# Kill date 2026-12-31 (Unix timestamp)
sentrava > generate --kill-date 2026-12-31 --os windows --listener <ip>:4433
# Kill date with self-delete on expiry
sentrava > generate --kill-date 2026-12-31 --self-delete --os windows --listener <ip>:4433
The kill date check uses the target's local clock. Large clock skew between operator and target can cause premature or delayed expiry. Prefer UTC timestamps and document the target's time zone.
working-hours
Category: Lifecycle
Ldflag: embeddedWorkingHoursStart=<HH:MM>, embeddedWorkingHoursEnd=<HH:MM>
Restricts beacon activity to a configured time window (local time on the target). Outside the window the agent sleeps without connecting to the C2 server. This mimics legitimate business-hours traffic patterns and avoids beaconing when analyst teams are typically active after hours.
# Active 09:00–18:00 local time on target
sentrava > generate --working-hours 09:00-18:00 --os windows --listener <ip>:4433
# Combined with kill date and full OPSEC
sentrava > generate --os windows --opsec full --win-opsec full --working-hours 09:00-18:00 --kill-date 2026-12-31 --listener <ip>:4433
Windows OPSEC presets
| Preset | Modules enabled |
|---|---|
--win-opsec none |
None (default) |
--win-opsec basic |
amsi-bypass, etw-patch |
--win-opsec full |
ntdll-unhook, amsi-bypass, etw-patch, ppid-spoof, indirect-syscall, sleepmask-win |
# Full Windows OPSEC stack + lifecycle controls
sentrava > generate --os windows --opsec full --win-opsec full \
--working-hours 09:00-18:00 --kill-date 2026-12-31 \
--transport mtls --listener 192.168.1.10:4433
Module registry IDs
| Module | Registry ID |
|---|---|
| etw-patch | win.opsec.etw |
| amsi-bypass | win.opsec.amsi |
| ppid-spoof | win.opsec.ppid |
| ntdll-unhook | win.opsec.ntdll |
| indirect-syscall | win.opsec.syscall |
| sleepmask-win | win.opsec.sleepmask |