> Windows Syscalls
ntoskrnl.exeT1562.001T1106

NtCancelIoFile

Cancela toda solicitud de E/S pendiente emitida por el hilo llamador sobre un handle de archivo.

Prototipo

NTSTATUS NtCancelIoFile(
  HANDLE           FileHandle,
  PIO_STATUS_BLOCK IoStatusBlock
);

Argumentos

NameTypeDirDescription
FileHandleHANDLEinHandle al archivo / dispositivo / pipe cuya E/S emitida por *el hilo llamador* debe cancelarse.
IoStatusBlockPIO_STATUS_BLOCKoutRecibe el resultado de la operación de cancelación en sí (Status, Information). No el estado de ningún IRP cancelado.

IDs de syscalls por versión de Windows

Versión de WindowsID de syscallBuild
Win10 15070x5Dwin10-1507
Win10 16070x5Dwin10-1607
Win10 17030x5Dwin10-1703
Win10 17090x5Dwin10-1709
Win10 18030x5Dwin10-1803
Win10 18090x5Dwin10-1809
Win10 19030x5Dwin10-1903
Win10 19090x5Dwin10-1909
Win10 20040x5Dwin10-2004
Win10 20H20x5Dwin10-20h2
Win10 21H10x5Dwin10-21h1
Win10 21H20x5Dwin10-21h2
Win10 22H20x5Dwin10-22h2
Win11 21H20x5Dwin11-21h2
Win11 22H20x5Dwin11-22h2
Win11 23H20x5Dwin11-23h2
Win11 24H20x5Dwin11-24h2
Server 20160x5Dwinserver-2016
Server 20190x5Dwinserver-2019
Server 20220x5Dwinserver-2022
Server 20250x5Dwinserver-2025

Módulo del kernel

ntoskrnl.exeNtCancelIoFile

APIs relacionadas

CancelIoNtCancelIoFileExNtCancelSynchronousIoFileNtReadFileNtWriteFile

Stub del syscall

4C 8B D1            mov r10, rcx
B8 5D 00 00 00      mov eax, 0x5D
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

SSN `0x5D` en todos los builds de Windows 10 / 11 / Server — estabilidad excepcional para un syscall de E/S de archivos. La advertencia crítica de alcance: NtCancelIoFile cancela sólo la E/S emitida por *el hilo llamador* sobre el handle dado. *No* afecta E/S emitida por otros hilos sobre el mismo handle (para eso se introdujo NtCancelIoFileEx en Vista). El `CancelIo` Win32 envuelve directamente esta llamada. El kernel recorre la lista de IRP adjunta al TCB del hilo y al FsContext del archivo, marca cada `IRP->Cancel = TRUE` y llama a la rutina de cancel del driver, que se espera complete los IRP con `STATUS_CANCELLED` (0xC0000120).

Uso común por malware

Usado en patrones defensivos de **evasión de hook de EDR**: muchos EDR user-mode hookean `ReadFile` / `WriteFile` / `NtReadFile` para inspeccionar contenido; si la rutina de inspección es asíncrona (encolando un callback en la finalización de E/S), un atacante puede race-cancelar el IRP antes de que dispare la rutina de finalización, impidiendo que el EDR observe nunca los bytes. Más común en uso ofensivo es código de fiabilidad en implants que hablan por named pipes — si el peer muere, el implant dispara `NtCancelIoFile` para flushear lecturas overlapped bloqueadas y recuperar el worker thread en lugar de quedar colgado hasta el timeout TCP / pipe del kernel. Algún tooling red-team también lo llama como parte de shutdown elegante para evitar dejar IRP huérfanas que aparezcan en salida `!irp` del debugger durante revisión forense.

Oportunidades de detección

NtCancelIoFile es extremadamente común en software legítimo intensivo en E/S (navegadores cancelando lecturas HTTPS en vuelo en navegación, IDE cancelando file watchers, OneDrive cancelando sync al offline-toggle) y por tanto es una mala señal primaria. La telemetría interesante es el *triplete*: una lectura async pendiente sobre un handle sensible (named-pipe \\.\pipe\protected_storage_pipe, handle IPC inyectado por EDR, socket HTTPS portando C2) cancelada en microsegundos tras emitirse por el mismo hilo que la emitió. ETW `Microsoft-Windows-Kernel-File` más correlación de IRP de finalización vía WPP pueden mostrar la ruta del IRP cancelado; combinar con PsSetCreateProcessNotifyRoutineEx para atribuir hilo-a-proceso. La mayoría de EDR no exponen un evento cancel de primera clase.

Ejemplos de syscalls directos

asmx64 direct stub

; Direct syscall stub for NtCancelIoFile (SSN 0x5D, all builds)
NtCancelIoFile PROC
    mov  r10, rcx          ; syscall convention
    mov  eax, 5Dh          ; SSN
    syscall
    ret
NtCancelIoFile ENDP

cImplant pipe shutdown

// Implant teardown: when the C2 peer dies, free our blocked overlapped
// read on the named pipe so the worker thread can exit instead of hanging.
#include <windows.h>

typedef struct _IO_STATUS_BLOCK {
    union { NTSTATUS Status; PVOID Pointer; };
    ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

typedef NTSTATUS (NTAPI *pNtCancelIoFile)(HANDLE, PIO_STATUS_BLOCK);

void ShutdownPipe(HANDLE h_pipe) {
    pNtCancelIoFile NtCancelIoFile = (pNtCancelIoFile)GetProcAddress(
        GetModuleHandleA("ntdll.dll"), "NtCancelIoFile");
    IO_STATUS_BLOCK iosb = {0};
    NtCancelIoFile(h_pipe, &iosb);   // only kills this thread's pending IRPs
    CloseHandle(h_pipe);
}

rustrace-cancel a hooked async read

// PoC: dispatch an async read, then cancel before the EDR's completion
// inspection runs. Same thread issues and cancels.
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::Storage::FileSystem::{ReadFile, OVERLAPPED};
use windows_sys::Win32::System::IO::CancelIo;

pub unsafe fn race_cancel(h: HANDLE, buf: &mut [u8], ov: *mut OVERLAPPED) {
    let mut dummy = 0u32;
    let _ = ReadFile(h, buf.as_mut_ptr() as _, buf.len() as u32, &mut dummy, ov);
    // Immediately yank the IRP before any completion routine fires.
    let _ = CancelIo(h);  // CancelIo == NtCancelIoFile under the hood
}

Mapeos MITRE ATT&CK

Last verified: 2026-05-20