NtCreateTimer
Erzeugt ein Kernel-Timer-Objekt, das später mit NtSetTimer scharfgeschaltet werden kann.
Prototyp
NTSTATUS NtCreateTimer( PHANDLE TimerHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, TIMER_TYPE TimerType );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| TimerHandle | PHANDLE | out | Erhält das Handle auf das neu erzeugte Timer-Objekt. |
| DesiredAccess | ACCESS_MASK | in | Zugriffsmaske, üblicherweise TIMER_ALL_ACCESS oder TIMER_MODIFY_STATE | SYNCHRONIZE. |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | Optionale Objektattribute; NULL für anonym, Name unter \BaseNamedObjects für IPC-Nutzung. |
| TimerType | TIMER_TYPE | in | NotificationTimer (Broadcast, bleibt signalisiert) oder SynchronizationTimer (Auto-Reset). |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1507 | 0xB4 | win10-1507 |
| Win10 1607 | 0xB7 | win10-1607 |
| Win10 1703 | 0xBA | win10-1703 |
| Win10 1709 | 0xBB | win10-1709 |
| Win10 1803 | 0xBC | win10-1803 |
| Win10 1809 | 0xBD | win10-1809 |
| Win10 1903 | 0xBE | win10-1903 |
| Win10 1909 | 0xBE | win10-1909 |
| Win10 2004 | 0xC2 | win10-2004 |
| Win10 20H2 | 0xC2 | win10-20h2 |
| Win10 21H1 | 0xC2 | win10-21h1 |
| Win10 21H2 | 0xC3 | win10-21h2 |
| Win10 22H2 | 0xC3 | win10-22h2 |
| Win11 21H2 | 0xC8 | win11-21h2 |
| Win11 22H2 | 0xC9 | win11-22h2 |
| Win11 23H2 | 0xC9 | win11-23h2 |
| Win11 24H2 | 0xCB | win11-24h2 |
| Server 2016 | 0xB7 | winserver-2016 |
| Server 2019 | 0xBD | winserver-2019 |
| Server 2022 | 0xC7 | winserver-2022 |
| Server 2025 | 0xCB | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
4C 8B D1 mov r10, rcx B8 CB 00 00 00 mov eax, 0xCB 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
Undokumentierte Hinweise
Allokiert ein Executive-`KTIMER`-Objekt über `ExCreateTimer` / `ObCreateObject`. Das Objekt ist bei Erzeugung *unbewaffnet* — es tut nichts, bis `NtSetTimer` einen Due-Time und optional eine APC-Routine liefert. SSN driftet zwischen Builds (`0xB4` auf 1507 → `0xCB` auf Win11 24H2 / Server 2025), Direct-Syscall-Implementierungen müssen also dynamisch auflösen. `NotificationTimer` lässt das Dispatcher-Objekt nach Ablauf signalisiert (alle Waiter freigegeben, nachfolgende kommen durch), während `SynchronizationTimer` nach Freigabe eines Waiters automatisch zurücksetzt — Letzteres nutzen Sleep-Masks.
Häufige Malware-Nutzung
Die erste Hälfte des **Ekko-Sleep-Mask-Motors** (Austin Hudson, 2022) — und das Design wurde von Foliage, Cronos, Zilean und den meisten modernen davon abgeleiteten Crypter-Loadern unverändert übernommen. Ein Timer wird erzeugt, `NtSetTimer` bewaffnet ihn mit `TimerApcRoutine = RtlCaptureContext`/`SetEvent`/`VirtualProtect` als Kettenstufen, und das Implant führt einen alertable Wait aus. Jedes Timer-Ablauf reiht einen APC ein, der APC führt eine ROP-Stufe aus, die den Implant-Speicher neu verschlüsselt und neu bewaffnet — entsteht ein Beacon, dessen Code in jedem Zyklus RWX → RW → verschlüsselt wird und naive Memory-Scanner besiegt. NtCreateTimer allein ist harmlos; die *Triade* (Timer + Event + alertable Wait in privatem Speicher) ist der IOC.
Erkennungsmöglichkeiten
Kein dediziertes Sysmon-Event für Timer-Erzeugung. ETW `Microsoft-Windows-Kernel-Object` mit Keyword `Timer` legt Objekt-Erzeugung offen; eine Korrelation von Timer-Handles, die von einem Thread gehalten werden, dessen RIP zum Zeitpunkt von `NtSetTimer` in nicht-gemapptem / RWX-Speicher liegt, ist das hochfidele Signal. Die meisten EDRs, die Ekko aushebeln, scannen den Stack des suspendierten Threads und gehen bei der Zustellung eines Special User APC durch KiUserApcDispatcher-Frames rückwärts — sie fangen die Verschlüsselungsstufe im Flug ab, nicht die Timer-Erzeugung.
Direkte Syscall-Beispiele
asmx64 direct stub (Win11 24H2)
; Direct syscall stub for NtCreateTimer (SSN 0xCB on Win11 24H2 / Server 2025)
NtCreateTimer PROC
mov r10, rcx ; syscall convention
mov eax, 0CBh ; SSN — drifts; resolve dynamically for portability
syscall
ret
NtCreateTimer ENDPcEkko-style sleep-mask timer setup
// Step 1 of the sleep-mask triad: a synchronization timer the APC chain will arm.
HANDLE hTimer = NULL;
OBJECT_ATTRIBUTES oa = { sizeof(oa), 0 };
NTSTATUS st = NtCreateTimer(&hTimer,
TIMER_ALL_ACCESS,
&oa,
SynchronizationTimer);
if (!NT_SUCCESS(st)) return st;
// hTimer will be armed by NtSetTimer with TimerApcRoutine pointing at the ROP gadgets.rustwindows-sys CreateWaitableTimerW wrapper
// Cargo: windows-sys = "0.59" (Win32_System_Threading)
use windows_sys::Win32::System::Threading::CreateWaitableTimerW;
use std::ptr::null;
unsafe fn make_timer() -> *mut core::ffi::c_void {
// bManualReset = 0 → SynchronizationTimer kernel-side.
CreateWaitableTimerW(null(), 0, null())
}MITRE ATT&CK-Mappings
Last verified: 2026-05-20