إنتقل إلى المحتوى الرئيسي

Evasion detection

What this page is

A complete catalog of EDR evasion techniques that the sensor detects and the detection logic for each, including ETW-TI injection events, ETW/AMSI patching, direct syscall detection, kernel callback tampering, handle stripping, and PowerShell obfuscation. Every technique is mapped to MITRE ATT&CK.

Why it exists this way

EDR evasion is a mature adversarial discipline with documented bypasses for every major commercial sensor. Defending against evasion requires layered detection: the sensor must monitor the monitoring infrastructure itself. The evasion detection module (edr_windows::guard) treats any attempt to interfere with telemetry collection as a detection event with higher severity than the underlying behaviour the adversary is trying to hide.

How it works

The evasion detection runs as part of the guard module's integrity check cycle (every 30 seconds) and reactively on ETW-TI events.

ETW-TI injection events

The Microsoft-Windows-Threat-Intelligence provider exposes events that are invisible to user-mode API hooks. Three event types are critical for evasion detection:

  1. Event ID 1 (CreateRemoteThread): A thread is created in a remote process. Detected injection techniques: classic DLL injection, reflective DLL injection, process hollowing (resume), and APC injection.

  2. Event ID 2 (VirtualAllocEx_Remote): Memory is allocated in a remote process with executable permissions (PAGE_EXECUTE_READWRITE). This is the precursor to Process Hollowing (T1055.012) and Process Doppelganging (T1055.013).

  3. Event ID 8 (QueueUserAPC): An APC is queued to a remote thread. This is the delivery mechanism for Early Bird APC injection and Atom Bombing.

The sensor correlates these events with process creation events from Kernel-Process to build an injection timeline: attacker process, target process, injection method, and payload.

ETW patching detection

The most common user-mode evasion technique is patching EtwEventWrite in ntdll.dll to return 0 without writing the event. The sensor detects this via:

// Simplified integrity check
fn check_etw_event_write_patched() -> bool {
let ntdll = get_module_base("ntdll.dll");
let etw_addr = resolve_export(ntdll, "EtwEventWrite");
let first_bytes = read_memory(etw_addr, 8);
// Clean ntdll: mov [rsp+8], rbx; push rdi; sub rsp, 0x30
// Patched: xor eax, eax; ret (three variants tracked)
matches!(first_bytes, PATCHED_SIGNATURE_1 | PATCHED_SIGNATURE_2 | PATCHED_SIGNATURE_3)
}

The sensor compares the in-memory bytes of EtwEventWrite and EtwEventWriteFull against known clean signatures from the on-disk ntdll.dll. If a patch signature is detected, the sensor:

  1. Logs a critical evasion alert with the patched function address and the first 16 bytes of the patch.
  2. Attempts to restore the clean bytes from the known-good on-disk copy via WriteProcessMemory on the patching process.
  3. If restoration fails (patch re-applied within 30 seconds), triggers fail-deadly WFP isolation.

AMSI patching detection

AMSI bypasses typically patch AmsiScanBuffer in amsi.dll to always return AMSI_RESULT_CLEAN. The sensor's AMSI integrity check reads the in-memory code section of amsi.dll and compares its SHA-256 hash against the on-disk file. Mismatch triggers the same escalation path as ETW patching.

Additionally, the sensor monitors for COM hijacking of the IAntimalwareProvider interface via the registry key HKCR\CLSID\{...}\InProcServer32. If the registered DLL path does not point to the AuroraEDR AMSI provider, the sensor logs the hijack attempt with the replacing DLL path and its digital signature status.

Direct syscall detection

Adversaries bypass user-mode hooks (EtwEventWrite, NtCreateThread) by invoking the syscall instruction directly with manually-crafted arguments. The sensor detects direct syscalls via two mechanisms:

  1. ETW-TI Event ID 12 (SyscallStub): The Threat-Intelligence provider fires when a syscall is executed from a non-standard module (not ntdll.dll or win32u.dll). This catches inline syscalls and syscall stubs from manually-mapped DLLs.

  2. Call stack analysis: When the minifilter driver's pre-operation callback fires for IRP_MJ_CREATE, the driver walks the call stack via RtlWalkFrameChain. If the call originates from ntdll.dll!NtCreateFile but the return address in the caller's stack frame does not lie within a legitimate image, the driver reports a direct syscall detection.

Kernel callback tampering

The sensor queries callback health via IOCTL_QUERY_CALLBACK_HEALTH every 30 seconds. If any of the four kernel callbacks return NotRegistered, this indicates one of two attack vectors:

  1. Callback removal: A kernel-mode driver unregistered the EDR callback. This requires a signed driver and is detectable by correlating with the driver load timeline from the Services ETW provider.

  2. Callback hijack: A kernel-mode driver installed a new callback at a higher altitude that returns early before the EDR callback executes. The sensor detects this by comparing PsGetProcessCreateNotifyRoutine count before and after the sensor's callback registration.

Handle stripping detection

Adversaries strip the PROCESS_VM_READ right from EDR process handles via NtSetInformationProcess(ProcessHandleInformation). The sensor's ObRegisterCallbacks pre-operation callback intercepts handle duplication and creation requests targeting the EDR user-mode process. If a handle is opened with OBJ_KERNEL_HANDLE or OBJ_FORCE_ACCESS_CHECK flags (indicating kernel-mode origin or privileged access), the driver:

  1. Logs the requesting process ID and access mask.
  2. Strips PROCESS_VM_READ, PROCESS_QUERY_INFORMATION, and PROCESS_DUP_HANDLE from the granted access.
  3. Returns the modified handle with STATUS_SUCCESS so the adversary's code does not detect the stripping.

PowerShell obfuscation

PowerShell attacks use obfuscation to evade signature-based detection. The sensor consumes PowerShell ETW events:

  • Event ID 4104 (ScriptBlock logging): Captures the de-obfuscated script block text after PowerShell's own parser has resolved escape sequences, string concatenation, and re-ordering tricks. The sensor ships this text to the Collector for analysis.

  • Event ID 4103 (Module logging): Captures the full pipeline execution details including command invocations, parameter values, and output types. This catches invocation-obfuscation techniques like &("i"+"e"+"x") and re-assigned aliases.

The sensor also checks for System.Management.Automation.dll being loaded from a non-standard path (common in reflection-load bypasses) by monitoring ETW-TI Event ID 3 (LoadLibrary).

MITRE ATT&CK evasion coverage

ATT&CK IDTechniqueDetection mechanismCovered
T1055.001DLL injectionETW-TI id=1 (CreateRemoteThread)Yes
T1055.002Portable Executable injectionETW-TI id=2 (VirtualAllocEx_Remote) + id=1Yes
T1055.012Process hollowingETW-TI id=2 + id=12 (syscall stub)Yes
T1055.013Process doppelgangingMinifilter IRP_MJ_CREATE + TI id=2Yes
T1562.001Disable or modify toolsETW/AMSI integrity checksYes
T1562.002Disable Windows Event LoggingEventLog ETW provider + guard pollYes
T1562.003Impair command history loggingPowerShell 4104 integrity checkYes
T1562.006Indicator blockingCallback health IOCTL pollYes
T1564.001Hidden files and directoriesMinifilter IRP_MJ_CREATE (FILE_ATTRIBUTE_HIDDEN)Yes
T1564.003Hidden windowKernel-Process id=1 (STARTF_USESHOWWINDOW)Yes
T1574.001DLL search order hijackingETW-TI id=3 (LoadLibrary) + path checkYes
T1574.002DLL side-loadingETW-TI id=3 + digital signature checkYes
T1059.001PowerShell obfuscationScriptBlock 4104 + Module 4103 loggingYes
T1027.005Multi-stage obfuscationPowerShell 4103 pipeline traceYes
T1036.005Match legitimate name or locationKernel-File id=30 + path comparisonYes
T1106Native API (direct syscalls)ETW-TI id=12 + call stack analysisYes
T1134.001Token impersonation/theftETW-TI id=6 (TokenAdjust)Yes
T1134.002Process injection via APCETW-TI id=8 (QueueUserAPC)Yes
T1055.004Thread execution hijackingETW-TI id=1 + call stack anomalyYes
T1556.002Password filter DLLETW-TI id=3 (LoadLibrary in LSASS)Yes
T1562.004Disable system firewallsWFP filter state poll (guard module)Yes
T1547.001Registry run keysCmRegisterCallback (kernel driver)Yes
T1547.009Shortcut modificationKernel-File id=30 (*.lnk in Startup)Yes

What goes wrong

  • ETW-TI provider is not available (Windows 10 <1809 or Server 2016). Injection detection relies on Kernel-Process events only, which do not capture remote thread creation with the same granularity. The sensor logs a PartialInjectionCoverage warning.
  • EtwEventWrite patch detection produces a false positive when a legitimate hooked version (e.g., from AppVerifier or Application Verifier) is present. The sensor checks the digital signature of the hooking module and whitelists Microsoft-signed hooks.
  • Call stack analysis fails for 32-bit processes on 64-bit systems (WoW64). The minifilter driver only walks the 64-bit stack and reports PartialCallStack for WoW64 processes.
  • PowerShell obfuscation detection relies on ScriptBlock logging being enabled (default since PowerShell 5.0). If an adversary downgrades to PowerShell 2.0 via -Version 2, neither 4104 nor 4103 events fire. The sensor detects this by monitoring for powershell.exe -Version 2 in process command lines.