> Windows Syscalls
ntoskrnl.exeT1003.002T1574T1106

NtLoadKeyEx

Moderner Hive-Load-Syscall — Basis für RegLoadKeyW, RegLoadAppKeyW und die AppContainer-Registry-Virtualisierung.

Prototyp

NTSTATUS NtLoadKeyEx(
  POBJECT_ATTRIBUTES TargetKey,
  POBJECT_ATTRIBUTES SourceFile,
  ULONG              Flags,
  HANDLE             TrustClassKey,
  HANDLE             Event,
  ACCESS_MASK        DesiredAccess,
  PHANDLE            RootHandle,
  PIO_STATUS_BLOCK   IoStatusBlock
);

Argumente

NameTypeDirDescription
TargetKeyPOBJECT_ATTRIBUTESinMount-Point-Objektattribute; bei REG_APP_HIVE ein privater, für andere Prozesse unsichtbarer Namespace.
SourceFilePOBJECT_ATTRIBUTESinHive-Datei auf der Platte (NT-Pfad). Muss auf einem lokalen Volume liegen; Remote-Pfade werden abgewiesen.
FlagsULONGinREG_NO_LAZY_FLUSH (0x4), REG_APP_HIVE (0x10), REG_PROCESS_PRIVATE (0x20), REG_HIVE_NO_RM (0x100), REG_HIVE_SINGLE_LOG (0x200), REG_BOOT_HIVE (0x400), REG_LOAD_HIVE_OPEN_HANDLE (0x800), REG_FLUSH_HIVE_FILE_GROWTH (0x1000), REG_OPEN_READ_ONLY (0x2000), REG_IMMUTABLE (0x4000), REG_NO_IMPERSONATION_FALLBACK (0x8000), REG_APP_HIVE_OPEN_READ_ONLY (0x10000).
TrustClassKeyHANDLEinOptionales Handle auf einen vertrauenswürdigen Hive zur Authentifizierung der Klassen-GUID des neuen Hives; üblicherweise NULL.
EventHANDLEinOptionales Event, das signalisiert wird, wenn der Hive aus einer Log-Datei wiederhergestellt wird; meist NULL.
DesiredAccessACCESS_MASKinAuf das zurückgegebene Root-Handle angeforderte Zugriffsmaske bei gesetztem REG_LOAD_HIVE_OPEN_HANDLE; sonst 0.
RootHandlePHANDLEoutEmpfängt ein Handle auf den Root-Schlüssel des geladenen Hives bei gesetztem REG_LOAD_HIVE_OPEN_HANDLE (so liefert RegLoadAppKeyW einen HKEY).
IoStatusBlockPIO_STATUS_BLOCKoutEmpfängt den finalen NTSTATUS und das Info-Wort des I/O-Subsystems (recovered, fresh usw.).

Syscall-IDs pro Windows-Version

Windows-VersionSyscall-IDBuild
Win10 15070xF8win10-1507
Win10 16070xFDwin10-1607
Win10 17030x101win10-1703
Win10 17090x102win10-1709
Win10 18030x103win10-1803
Win10 18090x103win10-1809
Win10 19030x104win10-1903
Win10 19090x104win10-1909
Win10 20040x109win10-2004
Win10 20H20x109win10-20h2
Win10 21H10x109win10-21h1
Win10 21H20x10Awin10-21h2
Win10 22H20x10Awin10-22h2
Win11 21H20x110win11-21h2
Win11 22H20x111win11-22h2
Win11 23H20x111win11-23h2
Win11 24H20x113win11-24h2
Server 20160xFDwinserver-2016
Server 20190x103winserver-2019
Server 20220x10Fwinserver-2022
Server 20250x113winserver-2025

Kernel-Modul

ntoskrnl.exeNtLoadKeyEx

Verwandte APIs

RegLoadKeyWRegLoadAppKeyWRegUnLoadKeyWNtLoadKeyNtLoadKey2NtLoadKey3NtUnloadKey2

Syscall-Stub

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

`NtLoadKeyEx` ist die kanonische moderne Hive-Load-Primitive. Zwei Win32-APIs setzen darauf auf: `RegLoadKeyW` (klassisches Admin-Mounten unter HKLM / HKU, benötigt `SeRestorePrivilege`) und das deutlich interessantere `RegLoadAppKeyW` (pro Prozess, pro Datei privater Hive, **ohne Privilegien** — funktioniert aus einem Low-IL-AppContainer). Die Flag-Kombination `REG_APP_HIVE | REG_PROCESS_PRIVATE | REG_LOAD_HIVE_OPEN_HANDLE` treibt die AppContainer-/Centennial-Registry-Virtualisierung; jedes UWP-Paket erhält einen privaten Hive unter `\Registry\WC\<package>`, der für andere Prozesse unsichtbar ist. Kernel-Handler ist `CmLoadKey` (`ntoskrnl.exe`), bewacht von `CmpCheckLoadHiveAccess`.

Häufige Malware-Nutzung

Zwei klar verschiedene Missbrauchspfade. (1) **Admin / Post-Exploitation**: dasselbe Offline-Parsing von SAM/SYSTEM/SECURITY wie `NtLoadKey` — der Operator kopiert den Hive per VSS oder `reg save HKLM\SAM` und mountet ihn dann unter HKU mit `NtLoadKeyEx`. (2) **AppContainer-aware Loader**: Malware in einer Sandbox-UWP / im Edge-Renderer / im MSIX-Kontext kann mit `REG_APP_HIVE` einen privaten Hive instanziieren, der von einer schreibbaren Datei unter dem Paket-Daten-Verzeichnis gespeist wird — nützlich als Staging- oder Config-Cache, der einen Reboot übersteht, ohne HKCU zu berühren oder `RegSetValueEx` auf überwachten Schlüsseln auszulösen. Phantom-DLL-Hollowing-artige Loader nutzen außerdem `REG_APP_HIVE | REG_OPEN_READ_ONLY`, um einen Hive zu mounten, dessen Backing-File ein payloadbestückter `.dat`-Blob ist.

Erkennungs­möglichkeiten

Gleiche Blue-Team-Haltung wie `NtLoadKey`/`NtLoadKey2`: ETW-Event `Microsoft-Windows-Kernel-Registry` ID 9 (HiveLoaded) ist die maßgebliche Quelle. Das aussagekräftige Signal ist der Pfad der *Backing-File* — `RegLoadAppKeyW` lädt legitim Dateien unter `C:\Users\<u>\AppData\Local\Packages\<pkg>\Settings\settings.dat`; alles andere (insbesondere Hives unter `C:\Windows\Temp`, `\ProgramData\` oder heruntergeladene Blobs) ist anomal. Kombiniere mit Sysmon Event ID 11 (FileCreate) auf `*.dat`/`*.hve`-Writes in verdächtigen Verzeichnissen und Event ID 1 (Process Create), der die Aktivierung von `SeRestorePrivilege` für Vollbaum-Mounts zeigt.

Direkte Syscall-Beispiele

asmx64 direct stub (Win11 24H2)

; Direct syscall stub for NtLoadKeyEx (SSN 0x113 on Win11 24H2)
NtLoadKeyEx PROC
    mov  r10, rcx          ; TargetKey
    mov  eax, 113h         ; SSN — drifts per build
    syscall
    ret
NtLoadKeyEx ENDP

cAppContainer-style private hive (no privileges required)

// Replicates what RegLoadAppKeyW does internally. Works from Low-IL AppContainers.
#include <windows.h>
#include <winternl.h>

#define REG_APP_HIVE                0x00000010
#define REG_PROCESS_PRIVATE         0x00000020
#define REG_LOAD_HIVE_OPEN_HANDLE   0x00000800

typedef NTSTATUS (NTAPI *pNtLoadKeyEx)(
    POBJECT_ATTRIBUTES, POBJECT_ATTRIBUTES, ULONG,
    HANDLE, HANDLE, ACCESS_MASK, PHANDLE, PIO_STATUS_BLOCK);

HANDLE LoadPrivateHive(LPCWSTR ntHiveFile) {
    HANDLE hRoot = NULL;
    IO_STATUS_BLOCK iosb = {0};
    UNICODE_STRING uMount, uFile;
    OBJECT_ATTRIBUTES oaMount, oaFile;
    // Mount path is irrelevant under REG_APP_HIVE | REG_PROCESS_PRIVATE
    RtlInitUnicodeString(&uMount, L"\\REGISTRY\\A\\{00000000-0000-0000-0000-000000000000}");
    RtlInitUnicodeString(&uFile,  ntHiveFile);
    InitializeObjectAttributes(&oaMount, &uMount, OBJ_CASE_INSENSITIVE, NULL, NULL);
    InitializeObjectAttributes(&oaFile,  &uFile,  OBJ_CASE_INSENSITIVE, NULL, NULL);
    pNtLoadKeyEx fn = (pNtLoadKeyEx)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtLoadKeyEx");
    fn(&oaMount, &oaFile,
       REG_APP_HIVE | REG_PROCESS_PRIVATE | REG_LOAD_HIVE_OPEN_HANDLE,
       NULL, NULL, KEY_ALL_ACCESS, &hRoot, &iosb);
    return hRoot;  // HKEY-equivalent, usable with NtOpenKey / NtSetValueKey
}

rustwindows-sys: classic admin-mount of an offline SYSTEM hive

// Cargo: windows-sys = { version = "0.59", features = [
//   "Win32_Foundation", "Win32_System_Registry", "Win32_Security" ] }
use windows_sys::Win32::System::Registry::{RegLoadKeyW, HKEY_LOCAL_MACHINE};
use windows_sys::core::PCWSTR;

fn mount_offline_system(hive_path_utf16: &[u16], subkey_utf16: &[u16]) -> i32 {
    // RegLoadKeyW → NtLoadKeyEx with Flags=0, TrustClassKey=NULL,
    // no REG_LOAD_HIVE_OPEN_HANDLE. Requires SeRestorePrivilege+SeBackupPrivilege.
    unsafe {
        RegLoadKeyW(HKEY_LOCAL_MACHINE,
                    subkey_utf16.as_ptr() as PCWSTR,
                    hive_path_utf16.as_ptr() as PCWSTR) as i32
    }
}

MITRE ATT&CK-Mappings

Last verified: 2026-05-20