> Windows Syscalls
ntoskrnl.exeT1012T1082T1497

NtQueryKey

Liefert Metadaten zu einem geöffneten Registry-Schlüssel — Name, Klasse, Anzahl Unterschlüssel/Werte, letzte Änderung.

Prototyp

NTSTATUS NtQueryKey(
  HANDLE                KeyHandle,
  KEY_INFORMATION_CLASS KeyInformationClass,
  PVOID                 KeyInformation,
  ULONG                 Length,
  PULONG                ResultLength
);

Argumente

NameTypeDirDescription
KeyHandleHANDLEinHandle auf einen geöffneten Schlüssel. Der erforderliche Zugriff hängt von KeyInformationClass ab; KEY_QUERY_VALUE genügt meist.
KeyInformationClassKEY_INFORMATION_CLASSinAngeforderte Variante: KeyBasicInformation, KeyNodeInformation, KeyFullInformation, KeyNameInformation, KeyCachedInformation, KeyVirtualizationInformation usw.
KeyInformationPVOIDoutVom Aufrufer allokierter Puffer, der die angeforderte Struktur empfängt.
LengthULONGinGröße von KeyInformation in Bytes.
ResultLengthPULONGoutEmpfängt die tatsächlich zurückgegebene (oder bei STATUS_BUFFER_TOO_SMALL benötigte) Größe.

Syscall-IDs pro Windows-Version

Windows-VersionSyscall-IDBuild
Win10 15070x16win10-1507
Win10 16070x16win10-1607
Win10 17030x16win10-1703
Win10 17090x16win10-1709
Win10 18030x16win10-1803
Win10 18090x16win10-1809
Win10 19030x16win10-1903
Win10 19090x16win10-1909
Win10 20040x16win10-2004
Win10 20H20x16win10-20h2
Win10 21H10x16win10-21h1
Win10 21H20x16win10-21h2
Win10 22H20x16win10-22h2
Win11 21H20x16win11-21h2
Win11 22H20x16win11-22h2
Win11 23H20x16win11-23h2
Win11 24H20x16win11-24h2
Server 20160x16winserver-2016
Server 20190x16winserver-2019
Server 20220x16winserver-2022
Server 20250x16winserver-2025

Kernel-Modul

ntoskrnl.exeNtQueryKey

Verwandte APIs

RegQueryInfoKeyWNtEnumerateKeyNtQueryValueKeyNtSetInformationKeyNtQueryMultipleValueKey

Syscall-Stub

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

Bemerkenswert: die SSN von NtQueryKey ist von Windows 10 1507 bis Windows 11 24H2 auf `0x16` festgenagelt — eine der stabilsten Nummern in der SSDT, was eine hartkodierte SSN über Builds hinweg sicher macht. Die KEY_FULL_INFORMATION-Variante liefert LastWriteTime als FILETIME, die Anzahl der Unterschlüssel / Werte und die Maximallängen — dieselben Zahlen, auf die `reg query` und `regjump` setzen.

Häufige Malware-Nutzung

Drei Spielarten des Missbrauchs. (1) *Timestomp-Detection-Evasion*: ein Operator liest LastWriteTime vor der Manipulation eines Werts und stellt ihn anschließend per NtSetInformationKey (KeyWriteTimeInformation) wieder her. (2) *Enumerations-Tooling*: Registry-laufende Implants kombinieren NtEnumerateKey + NtQueryKey, um einen Teilbaum zu rekursieren und hochwertige Ziele (Autoruns, Services, AppCompat-Shims) zu identifizieren. (3) *Sandbox-Fingerprinting*: Schlüssel wie `HKLM\HARDWARE\DESCRIPTION\System\BIOS` abfragen und LastWriteTime inspizieren, um frisch gebaute Analyse-VMs zu erkennen.

Erkennungs­möglichkeiten

NtQueryKey allein ist Hintergrundrauschen in hoher Frequenz — der Explorer ruft es zigtausendfach pro Stunde auf. Das wertvolle Signal ist die folgende *Schreiboperation*: KeyWriteTimeInformation über NtSetInformationKey ist in legitimen Workloads selten und nahezu diagnostisch für Timestomp. EDRs, die CmRegisterCallbackEx hooken, sehen RegNtPostQueryKey, ignorieren es aber meist aus Kostengründen. ETW Microsoft-Windows-Kernel-Registry liefert RegistryQueryKey, ist aber standardmäßig deaktiviert. Hunt-Tipp: ein Prozess-Handle-Inventar, das einen Nicht-Explorer/Nicht-svchost-Prozess mit hunderten offenen Registry-Handles zeigt, ist eine bessere Spur als jeder einzelne NtQueryKey-Aufruf.

Direkte Syscall-Beispiele

cRead LastWriteTime for timestomp staging

// Capture the original LastWriteTime before tampering with a value,
// so it can be restored via NtSetInformationKey afterward.
KEY_BASIC_INFORMATION* kbi = (KEY_BASIC_INFORMATION*)buf;
ULONG ret = 0;
NTSTATUS st = NtQueryKey(hKey, KeyBasicInformation, kbi, sizeof(buf), &ret);
if (NT_SUCCESS(st)) {
    g_savedWriteTime = kbi->LastWriteTime;
}

asmx64 direct stub (stable SSN 0x16)

NtQueryKey PROC
    mov  r10, rcx
    mov  eax, 16h
    syscall
    ret
NtQueryKey ENDP

rustFull information enumeration

// Cargo: ntapi = "0.4"
let mut needed: u32 = 0;
let status = unsafe {
    NtQueryKey(h_key,
        KeyFullInformation,
        null_mut(),
        0,
        &mut needed)
};
assert_eq!(status, STATUS_BUFFER_TOO_SMALL as i32);
let mut buf = vec![0u8; needed as usize];
let status = unsafe {
    NtQueryKey(h_key,
        KeyFullInformation,
        buf.as_mut_ptr() as _,
        buf.len() as u32,
        &mut needed)
};
assert!(status == 0);

MITRE ATT&CK-Mappings

Last verified: 2026-05-20