NtCancelTimer2
Cancela un objeto Timer2 previamente armado e indica si aún estaba pendiente.
Prototipo
NTSTATUS NtCancelTimer2( HANDLE TimerHandle, PT2_CANCEL_PARAMETERS Parameters );
Argumentos
| Name | Type | Dir | Description |
|---|---|---|---|
| TimerHandle | HANDLE | in | Handle a un objeto Timer2 previamente armado con NtSetTimer2. |
| Parameters | PT2_CANCEL_PARAMETERS | in/out | Estructura opcional: en entrada Version, en salida indica si el timer estaba pendiente. |
IDs de syscalls por versión de Windows
| Versión de Windows | ID de syscall | Build |
|---|---|---|
| Win10 1507 | 0x8F | win10-1507 |
| Win10 1607 | 0x8F | win10-1607 |
| Win10 1703 | 0x90 | win10-1703 |
| Win10 1709 | 0x91 | win10-1709 |
| Win10 1803 | 0x92 | win10-1803 |
| Win10 1809 | 0x92 | win10-1809 |
| Win10 1903 | 0x92 | win10-1903 |
| Win10 1909 | 0x92 | win10-1909 |
| Win10 2004 | 0x94 | win10-2004 |
| Win10 20H2 | 0x94 | win10-20h2 |
| Win10 21H1 | 0x94 | win10-21h1 |
| Win10 21H2 | 0x94 | win10-21h2 |
| Win10 22H2 | 0x94 | win10-22h2 |
| Win11 21H2 | 0x94 | win11-21h2 |
| Win11 22H2 | 0x94 | win11-22h2 |
| Win11 23H2 | 0x94 | win11-23h2 |
| Win11 24H2 | 0x96 | win11-24h2 |
| Server 2016 | 0x8F | winserver-2016 |
| Server 2019 | 0x92 | winserver-2019 |
| Server 2022 | 0x94 | winserver-2022 |
| Server 2025 | 0x96 | winserver-2025 |
Módulo del kernel
APIs relacionadas
Stub del syscall
4C 8B D1 mov r10, rcx B8 96 00 00 00 mov eax, 0x96 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
Contraparte de `NtSetTimer2`. Internamente `ExpCancelTimer2` retira el `EX_TIMER` de la cola de segunda generación por-PRCB vía `KeCancelTimer2`. Si el timer aún estaba pendiente el kernel devuelve `STATUS_SUCCESS` y rellena `Parameters` reflejando el estado anterior; si ya expiró y el callback corrió o está en vuelo, obtienes semántica tipo `STATUS_TIMER_RESUME_IGNORED` — la llamada no puede des-entregar un APC ya encolado a un hilo. Nota que `NtCancelTimer2` es notablemente estable (`0x8F` en 1507 → `0x96` en Win11 24H2): la SSN original de 1507 sobrevivió hasta la reorganización de la tabla de syscalls de Win11 24H2, porque el índice refleja la posición alfabética ordenada relativa a inserciones/eliminaciones — y muy poco se insertó *antes* de `Cancel*` durante años.
Uso común por malware
Usado como teardown simétrico para sleep masks basados en Timer2 (Cronos, Zilean): justo antes de que el implante salga, o cuando desmonta un ciclo de máscara temporal, `NtCancelTimer2` desarma el timer para que la alertable wait termine limpiamente. Algunos kits también lo usan defensivamente — si un EDR ha empezado a recorrer las listas de timers del threadpool, cancelar el timer pronto *retira el objeto de la lista* antes de que el escaneo correlacione el puntero callback con RWX privada. Señal de malware baja por sí solo.
Oportunidades de detección
No hay evento Sysmon para cancelación de Timer2, y la llamada por sí sola es benigna. Las investigaciones la consideran solo como parte de una *secuencia*: `NtCreateTimer2(HIGH_RESOLUTION) → NtSetTimer2(period ≈ 50 ms, callback en RWX) → NtWaitForSingleObjectEx(Alertable=TRUE) → NtCancelTimer2` repetido apretadamente es la huella canónica de un sleep-mask Timer2. Los EDR con componentes kernel (CrowdStrike Falcon, Defender for Endpoint vía MAPS) inspeccionan directamente las listas `EX_TIMER` en vez de depender de hooks de syscall para este.
Ejemplos de syscalls directos
asmx64 direct stub (Win11 24H2)
; Direct syscall stub for NtCancelTimer2 (SSN 0x96 on Win11 24H2 / Server 2025)
NtCancelTimer2 PROC
mov r10, rcx ; syscall convention
mov eax, 96h ; SSN — drifts; resolve dynamically for portability
syscall
ret
NtCancelTimer2 ENDPcSleep-mask teardown
// Sleep-mask cycle teardown: disarm the timer and close the handle.
typedef struct _T2_CANCEL_PARAMETERS {
ULONG Version;
ULONG Reserved;
} T2_CANCEL_PARAMETERS, *PT2_CANCEL_PARAMETERS;
T2_CANCEL_PARAMETERS cp = { 0 };
NTSTATUS st = NtCancelTimer2(hTimer, &cp);
// If st == STATUS_SUCCESS the timer was still armed; otherwise the APC already fired.
NtClose(hTimer);Mapeos MITRE ATT&CK
Last verified: 2026-05-20