NtSetEvent
Place un objet événement à l'état signalé, libérant les threads en attente.
Prototype
NTSTATUS NtSetEvent( HANDLE EventHandle, PLONG PreviousState );
Arguments
| Name | Type | Dir | Description |
|---|---|---|---|
| EventHandle | HANDLE | in | Handle vers l'événement avec l'accès EVENT_MODIFY_STATE. |
| PreviousState | PLONG | out | Optionnel ; reçoit l'état signalé précédent (1 = signalé, 0 = non signalé). |
IDs de syscalls par version de Windows
| Version de Windows | ID de syscall | Build |
|---|---|---|
| Win10 1507 | 0xE | win10-1507 |
| Win10 1607 | 0xE | win10-1607 |
| Win10 1703 | 0xE | win10-1703 |
| Win10 1709 | 0xE | win10-1709 |
| Win10 1803 | 0xE | win10-1803 |
| Win10 1809 | 0xE | win10-1809 |
| Win10 1903 | 0xE | win10-1903 |
| Win10 1909 | 0xE | win10-1909 |
| Win10 2004 | 0xE | win10-2004 |
| Win10 20H2 | 0xE | win10-20h2 |
| Win10 21H1 | 0xE | win10-21h1 |
| Win10 21H2 | 0xE | win10-21h2 |
| Win10 22H2 | 0xE | win10-22h2 |
| Win11 21H2 | 0xE | win11-21h2 |
| Win11 22H2 | 0xE | win11-22h2 |
| Win11 23H2 | 0xE | win11-23h2 |
| Win11 24H2 | 0xE | win11-24h2 |
| Server 2016 | 0xE | winserver-2016 |
| Server 2019 | 0xE | winserver-2019 |
| Server 2022 | 0xE | winserver-2022 |
| Server 2025 | 0xE | winserver-2025 |
Module noyau
APIs liées
Stub du syscall
4C 8B D1 mov r10, rcx B8 0E 00 00 00 mov eax, 0xE 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
Notes non documentées
Fait passer l'objet événement à l'état signalé via `KeSetEvent` dans ntoskrnl.exe. La SSN `0x0E` est stable sur chaque build Win10/11. Pour un `SynchronizationEvent` (auto-reset), exactement un thread en attente est libéré et l'événement repasse aussitôt à non-signalé ; pour un `NotificationEvent` (reset manuel), tous les waiters présents et futurs passent jusqu'à un `NtClearEvent` / `NtResetEvent`. Très peu coûteux — typiquement quelques centaines de cycles quand aucun waiter n'a besoin d'être débloqué.
Usage courant par les malwares
La moitié déclenchante du pattern sleep-mask : la routine APC de timer dans les chaînes à la Ekko appelle `NtSetEvent` pour réveiller le thread implant de son wait alertable à chaque étape de la chaîne ROP (chiffrer → dormir → déchiffrer → reprendre). Dans les designs C2 named-pipe, le producteur signale l'événement après écriture sur le pipe pour que le consommateur évite une boucle de polling. Certains loaders signalent aussi un événement kill-switch pour coordonner un teardown propre entre modules.
Opportunités de détection
`NtSetEvent` seul n'est pas journalisé et est omniprésent. La détection utile est contextuelle : la *paire* `NtSetEvent` suivie en quelques microsecondes par un `NtWaitForSingleObject` (alertable) sur le même handle, exécutée dans un thread dont le RIP code est en mémoire RWX privée, est une empreinte quasi pathognomonique du sleep-masking in-process. ETW Threat Intelligence n'émet pas d'événement dédié pour SetEvent ; la corrélation handle au niveau noyau ou l'inspection de la région mémoire aux bornes de sleep est la voie réaliste.
Exemples de syscalls directs
asmx64 direct stub
; Direct syscall stub for NtSetEvent (SSN 0x0E, stable across Win10/11)
NtSetEvent PROC
mov r10, rcx ; syscall convention
mov eax, 0Eh ; SSN
syscall
ret
NtSetEvent ENDPcTimer-APC sleep-mask trigger
// APC routine attached to an NtSetTimer; signals the wake-up event for the implant.
VOID NTAPI EkkoTimerApc(PVOID ctx, ULONG lo, ULONG hi) {
(void)lo; (void)hi;
HANDLE hEvent = (HANDLE)ctx;
NtSetEvent(hEvent, NULL); // wakes the alertable WaitForSingleObject in main thread
}rustwindows-sys SetEvent wrapper
// Cargo: windows-sys = "0.59" (Win32_System_Threading)
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::System::Threading::SetEvent;
unsafe fn signal(h: HANDLE) -> bool {
SetEvent(h) != 0
}Mappings MITRE ATT&CK
Last verified: 2026-05-20