> Windows Syscalls
ntoskrnl.exeT1547.001T1112T1106

NtFlushKey

Erzwingt das Schreiben aller anstehenden Änderungen eines Registry-Schlüssels in seine Hive-Datei.

Prototyp

NTSTATUS NtFlushKey(
  HANDLE  KeyHandle
);

Argumente

NameTypeDirDescription
KeyHandleHANDLEinGeöffnetes Handle auf einen beliebigen Schlüssel der zu flushenden Hive; die gesamte Hive wird committet.

Syscall-IDs pro Windows-Version

Windows-VersionSyscall-IDBuild
Win10 15070xDAwin10-1507
Win10 16070xDDwin10-1607
Win10 17030xE0win10-1703
Win10 17090xE1win10-1709
Win10 18030xE2win10-1803
Win10 18090xE3win10-1809
Win10 19030xE4win10-1903
Win10 19090xE4win10-1909
Win10 20040xE9win10-2004
Win10 20H20xE9win10-20h2
Win10 21H10xE9win10-21h1
Win10 21H20xEAwin10-21h2
Win10 22H20xEAwin10-22h2
Win11 21H20xEFwin11-21h2
Win11 22H20xF0win11-22h2
Win11 23H20xF0win11-23h2
Win11 24H20xF2win11-24h2
Server 20160xDDwinserver-2016
Server 20190xE3winserver-2019
Server 20220xEEwinserver-2022
Server 20250xF2winserver-2025

Kernel-Modul

ntoskrnl.exeNtFlushKey

Verwandte APIs

RegFlushKeyNtFlushBuffersFileNtSaveKeyNtSetValueKey

Syscall-Stub

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

NtFlushKey committet alle In-Memory-Änderungen für die *Hive*, die den übergebenen Schlüssel enthält, in deren Backing-Datei. Trotz der Pro-Schlüssel-Signatur flusht der Kernel die gesamte Hive — der Configuration Manager hält keine Dirty-Bits pro Schlüssel auf Flush-Granularität. Unterschied zu `NtFlushBuffersFile`: Letzteres adressiert eine Datei via FILE_OBJECT, NtFlushKey adressiert eine Hive via Key-Handle. Win32-Wrapper ist `RegFlushKey`. Der Lazy-Flusher schreibt dirty hives normalerweise alle fünf Sekunden (`CmpLazyFlushIntervalInSeconds`); NtFlushKey erzwingt das sofortige Zurückschreiben.

Häufige Malware-Nutzung

Das Hauptmissbrauchsmuster ist **Anti-Forensik rund um Persistenz**: Nach dem Schreiben einer Run-Key, Scheduled-Task-Konfiguration, eines Service-Eintrags oder COM-Hijack-Werts ruft Malware NtFlushKey auf, um die Änderung *vor* dem nächsten unsauberen Reboot auf die Platte zu garantieren — wichtig, wenn das Lazy-Flush-Fenster breiter ist als das erwartete Gelegenheitsfenster (BSOD-auslösender Exploit, geplanter Hardreset, host-tötende Ransomware). Sekundäres Muster: Manche Dropper flushen einen frisch geschriebenen Autorun-Eintrag und löschen unmittelbar danach die referenzierte Binary auf der Platte, sodass Run-Key-Metadaten auf Inhalte zeigen, die beim Boot möglicherweise nicht mehr existieren — eine kleine Anti-Analyse-Lästigkeit.

Erkennungs­möglichkeiten

Für sich ist NtFlushKey uninteressant — explorer.exe und viele Treiber rufen ihn routinemäßig auf. Das nützliche Signal ist die *Sequenz*: Sysmon Event 13 (Registry-Value-Set) auf einem bekannten Persistenz-Schlüssel, unmittelbar gefolgt von einem Flush aus derselben PID, besonders wenn diese PID unsigniert oder frisch erzeugt ist. ETW `Microsoft-Windows-Kernel-Registry` liefert Flush-Events mit Key-Pfad und PID. Mit Sysmon Event 11 (File Create / Delete) für die referenzierte Persistenz-Binary korrelieren.

Direkte Syscall-Beispiele

asmx64 direct stub (Win11 24H2)

; Direct syscall stub for NtFlushKey (SSN 0xF2 on Win11 24H2 — drifts per build)
NtFlushKey PROC
    mov  r10, rcx          ; KeyHandle
    mov  eax, 0F2h         ; SSN
    syscall
    ret
NtFlushKey ENDP

cPersistence write-then-flush

// Write a Run key and immediately flush — defeats lazy-flush race on hard reboot.
#include <windows.h>

LONG PersistAndFlush(LPCWSTR name, LPCWSTR cmd) {
    HKEY hRun = NULL;
    LONG s = RegCreateKeyExW(HKEY_CURRENT_USER,
        L"Software\\Microsoft\\Windows\\CurrentVersion\\Run",
        0, NULL, 0, KEY_SET_VALUE, NULL, &hRun, NULL);
    if (s != ERROR_SUCCESS) return s;
    s = RegSetValueExW(hRun, name, 0, REG_SZ,
                       (const BYTE*)cmd,
                       (DWORD)((wcslen(cmd) + 1) * sizeof(WCHAR)));
    if (s == ERROR_SUCCESS) RegFlushKey(hRun);   // ← NtFlushKey under the hood
    RegCloseKey(hRun);
    return s;
}

rustDirect NtFlushKey

// Cargo: ntapi = "0.4"
use ntapi::ntregapi::NtFlushKey;
use winapi::shared::ntdef::{HANDLE, NTSTATUS};

unsafe fn flush(key: HANDLE) -> NTSTATUS {
    NtFlushKey(key)
}

MITRE ATT&CK-Mappings

Last verified: 2026-05-20