ETW Patch
Overwrites the prologue of ntdll’s ETW event-writing exports so no Event Tracing for Windows events are emitted from the process.
Metadata
Section titled “Metadata”| ATT&CK | T1562.006 (Impair Defenses: Indicator Blocking) |
| Stability | Stable |
| Category | Preparation |
| YAML key | patch_etw |
| Introduced in | Phase 7 |
What it does
Section titled “What it does”Overwrites the prologue of the ETW event-writing exports in the current process
so no Event Tracing for Windows events are emitted from it. It does not run the
payload; it only modifies process state, which is why it is a Preparation
technique. Blinding ETW complements patch_amsi: AMSI gates script and .NET
content before it runs, ETW is the telemetry channel that reports what ran.
YAML parameters
Section titled “YAML parameters”| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
full | bool | no | true | Also patch EtwEventWriteFull (best effort). |
YAML example
Section titled “YAML example”runtime: - technique: patch_etw params: full: trueHow it works
Section titled “How it works”sequenceDiagram
participant L as Loader
participant N as ntdll.dll
L->>N: LoadLibraryA(ntdll.dll)
L->>N: GetProcAddress(EtwEventWrite)
L->>N: nt_protect_vm(RWX)
L->>N: write 33 C0 C3 (xor eax,eax; ret)
L->>N: restore original protection
opt full
L->>N: same for EtwEventWriteFull
end
1. Resolve the export
Section titled “1. Resolve the export”- Load
ntdll.dll(LoadLibraryA, a no-op if already loaded). - Resolve
EtwEventWritewithGetProcAddress.
2. Overwrite the prologue
Section titled “2. Overwrite the prologue”- Make the first three bytes writable (
nt_protect_vm→PAGE_EXECUTE_READWRITE). - Write
xor eax, eax; ret(33 C0 C3): returnSTATUS_SUCCESS(0) without writing an event. - Restore the original page protection.
3. Optionally patch the Full variant
Section titled “3. Optionally patch the Full variant”- If
fullistrue, repeat steps 2–5 forEtwEventWriteFull. This second patch is best effort: some builds do not export the Full variant, and a missing secondary export must not discard a working main patch.
If the main export cannot be resolved (or the page cannot be made writable), the preparation returns a clear error and the pipeline fails with a useful message.
What it evades
Section titled “What it evades”- ETW-based telemetry consumed in-process, e.g.
.NET/PowerShell script-block logging, WMI activity and other providers that write throughntdll’s event-writing exports. - EDR user-mode sensors that hook these exports (the overwrite also removes the hook’s first bytes).
What detects it
Section titled “What detects it”- Hooks on
VirtualProtect/NtProtectVirtualMemoryoverPAGE_EXECUTE_READWRITEtargetingntdll’s code section. - ETW-TI (
Microsoft-Windows-Threat-Intelligence, kernel-side) on suspicious memory writes tontdll. - Memory integrity checks / periodic re-reads of the event-writing exports,
which find the
33 C0 C3prologue. - Kernel callbacks (
PsSetCreateProcessNotifyRoutineEx, etc.) are unaffected: this blinds user-mode events, not kernel telemetry.
Measurements
Section titled “Measurements”- See
docs/measurements.md.
Implementation notes
Section titled “Implementation notes”33 C0 C3(xor eax, eax; ret) is used instead of a bareret(C3): the export returns aULONGNTSTATUS, and a bareretwould leak whatever was in EAX. On x64, writing EAX zero-extends to RAX, so33 C0clears the full 64-bit return register.- Only affects the current process. If the payload runs in another process (e.g. process hollowing), that process’s ETW exports are not patched here.
- The patch is deliberately unsynchronised. In practice
run_preparationsexecutes before the payload and before any thread the stub creates, so there is no concurrent reader of the bytes being rewritten. - The DLL and function names go through
StringsConfig(Params::render_fragment), sontdll.dll,EtwEventWriteandEtwEventWriteFullnever appear in cleartext in.rdata. The page protection change goes through the syscall layer’snt_protect_vm, somode: indirectremoves theVirtualProtectimport. - The function names are resolved dynamically through
GetProcAddress, so they never reach the import table.ntdll.dllmay still appear in the binary through thewindowscrate graph; the audit blanks import-table name strings, so it is not reported as a leaked literal.
References
Section titled “References”- Classic ETW patching (
EtwEventWrite→ret) used by C2 frameworks. - MITRE ATT&CK T1562.006 — Impair Defenses: Indicator Blocking.