> Windows Syscalls
ntoskrnl.exeT1106T1027.013

NtResetEvent

Restablece un objeto evento a no señalado y devuelve su estado señalado anterior.

Prototipo

NTSTATUS NtResetEvent(
  HANDLE  EventHandle,
  PLONG   PreviousState
);

Argumentos

NameTypeDirDescription
EventHandleHANDLEinHandle al evento con acceso EVENT_MODIFY_STATE.
PreviousStatePLONGoutOpcional; recibe el estado señalado del evento antes del reset (1 = señalado, 0 = no).

IDs de syscalls por versión de Windows

Versión de WindowsID de syscallBuild
Win10 15070x15Ewin10-1507
Win10 16070x165win10-1607
Win10 17030x16Bwin10-1703
Win10 17090x16Ewin10-1709
Win10 18030x170win10-1803
Win10 18090x171win10-1809
Win10 19030x172win10-1903
Win10 19090x172win10-1909
Win10 20040x178win10-2004
Win10 20H20x178win10-20h2
Win10 21H10x178win10-21h1
Win10 21H20x17Awin10-21h2
Win10 22H20x17Awin10-22h2
Win11 21H20x182win11-21h2
Win11 22H20x185win11-22h2
Win11 23H20x185win11-23h2
Win11 24H20x187win11-24h2
Server 20160x165winserver-2016
Server 20190x171winserver-2019
Server 20220x180winserver-2022
Server 20250x187winserver-2025

Módulo del kernel

ntoskrnl.exeNtResetEvent

APIs relacionadas

ResetEventNtSetEventNtClearEventNtPulseEventNtWaitForSingleObject

Stub del syscall

4C 8B D1            mov r10, rcx
B8 87 01 00 00      mov eax, 0x187
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

NtResetEvent es el inverso de NtSetEvent: lleva un objeto evento al estado no señalado y devuelve opcionalmente el estado *anterior* vía `PreviousState`. La diferencia con NtClearEvent (que hace lo mismo pero descarta el estado anterior) es puramente si al llamante le interesa el valor previo — útil para implementar semántica test-and-clear sin un viaje extra a NtQueryEvent. La rutina kernel `KeResetEvent` subyace tanto a NtResetEvent como a NtClearEvent.

Uso común por malware

Común en implementaciones de *sleep mask* y *bucles ociosos event-driven* usadas por beacons modernos. Patrón típico: el implante arma un evento con NtSetEvent antes de dormir en un homólogo y luego lo resetea vía NtResetEvent al reanudar para estar listo en la siguiente iteración. El sleep mask user-defined de Cobalt Strike, Sleepmask-rs y varios módulos post-ex de Sliver usan así las primitivas event NT para evitar la huella temporal obvia de `NtDelayExecution`. Visto también en bucles worker condicionados por una señal maestra.

Oportunidades de detección

NtResetEvent es *extremadamente* común en código legítimo (toda CRITICAL_SECTION en contención, todo teardown de completación de I/O async), así que por sí solo no es señal. Lo que importa es la correlación: ciclos cortos repetidos `NtCreateEvent → NtSetEvent → NtWait → NtResetEvent` desde un solo hilo con una región de pila RWX o con la secuencia de llamadas en un búfer asignado en heap es coherente con un sleep mask. ETW Threat Intelligence (`Microsoft-Windows-Threat-Intelligence`) expone algunas transiciones de context-switch y wait útiles; si no, telemetría de stack-walking.

Ejemplos de syscalls directos

asmx64 direct stub

; Direct syscall stub for NtResetEvent (SSN 0x187 on Win11 24H2)
NtResetEvent PROC
    mov  r10, rcx          ; EventHandle
    mov  eax, 187h         ; SSN — verify per-build
    syscall
    ret
NtResetEvent ENDP

cTest-and-clear without round-trip

// Atomically clear hEvent and learn whether it was previously signaled.
#include <windows.h>
#include <winternl.h>

typedef NTSTATUS (NTAPI *pNtResetEvent)(HANDLE, PLONG);

BOOL ConsumeOneShot(HANDLE hEvent) {
    LONG prev = 0;
    pNtResetEvent fn = (pNtResetEvent)GetProcAddress(
        GetModuleHandleA("ntdll.dll"), "NtResetEvent");
    NTSTATUS s = fn(hEvent, &prev);
    return (s >= 0) && (prev != 0);
}

rustEvent-paced sleep mask skeleton

// Cargo: windows-sys = "0.59", ntapi = "0.4"
// Toy sleep-mask loop: park on event, decrypt-process-encrypt, reset, repeat.
use ntapi::ntpsapi::NtResetEvent;
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::System::Threading::WaitForSingleObject;

unsafe fn beacon_loop(wake: HANDLE) {
    loop {
        WaitForSingleObject(wake, u32::MAX);   // park
        // ... unmask payload, run task, remask payload ...
        let mut prev: i32 = 0;
        NtResetEvent(wake, &mut prev);          // rearm for next pulse
    }
}

Mapeos MITRE ATT&CK

Last verified: 2026-05-20