> Windows Syscalls
ntoskrnl.exeT1003.002T1574T1106

NtLoadKeyEx

Syscall moderno de carga de colmena — respalda RegLoadKeyW, RegLoadAppKeyW y la virtualización de registro de AppContainer.

Prototipo

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

Argumentos

NameTypeDirDescription
TargetKeyPOBJECT_ATTRIBUTESinAtributos de objeto del punto de montaje; para REG_APP_HIVE es un namespace privado invisible a otros procesos.
SourceFilePOBJECT_ATTRIBUTESinArchivo de colmena en disco (ruta NT). Debe estar en un volumen local; rutas remotas son rechazadas.
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).
TrustClassKeyHANDLEinHandle opcional a una colmena de confianza para autenticar el GUID de clase de la nueva colmena; típicamente NULL.
EventHANDLEinEvento opcional señalado cuando la colmena se recupera de un archivo de log; normalmente NULL.
DesiredAccessACCESS_MASKinMáscara de acceso solicitada en el handle raíz retornado cuando REG_LOAD_HIVE_OPEN_HANDLE está activo; si no, 0.
RootHandlePHANDLEoutRecibe un handle a la clave raíz de la colmena cargada cuando REG_LOAD_HIVE_OPEN_HANDLE está activo (así RegLoadAppKeyW devuelve un HKEY).
IoStatusBlockPIO_STATUS_BLOCKoutRecibe el NTSTATUS final y la palabra de información del subsistema I/O (recuperado, nuevo, etc.).

IDs de syscalls por versión de Windows

Versión de WindowsID de syscallBuild
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

Módulo del kernel

ntoskrnl.exeNtLoadKeyEx

APIs relacionadas

RegLoadKeyWRegLoadAppKeyWRegUnLoadKeyWNtLoadKeyNtLoadKey2NtLoadKey3NtUnloadKey2

Stub del syscall

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

Notas no documentadas

`NtLoadKeyEx` es la primitiva moderna canónica de carga de colmena. Dos APIs Win32 se apoyan en ella: `RegLoadKeyW` (montaje admin clásico bajo HKLM / HKU, requiere `SeRestorePrivilege`) y el mucho más interesante `RegLoadAppKeyW` (colmena privada por proceso / por archivo, **sin privilegios** — funciona desde un AppContainer de baja integridad). La combinación `REG_APP_HIVE | REG_PROCESS_PRIVATE | REG_LOAD_HIVE_OPEN_HANDLE` impulsa la capa de virtualización de registro AppContainer / Centennial; cada paquete UWP recibe una colmena privada en `\Registry\WC\<package>` invisible a otros procesos. El handler de kernel es `CmLoadKey` (`ntoskrnl.exe`), filtrado por `CmpCheckLoadHiveAccess`.

Uso común por malware

Dos rutas de abuso distintas. (1) **Admin / post-explotación**: el mismo parseo offline de SAM/SYSTEM/SECURITY que `NtLoadKey` — el operador copia la colmena vía VSS o `reg save HKLM\SAM`, luego la monta bajo HKU con `NtLoadKeyEx`. (2) **Loaders conscientes de AppContainer**: malware corriendo en un UWP sandbox / renderer de Edge / contexto MSIX puede usar `REG_APP_HIVE` para instanciar una colmena privada respaldada por un archivo escribible bajo su directorio de datos del paquete — útil como caché de staging o configuración que sobrevive reinicio sin tocar HKCU ni disparar `RegSetValueEx` sobre claves monitorizadas. Loaders estilo Phantom DLL Hollowing también usan `REG_APP_HIVE | REG_OPEN_READ_ONLY` para montar una colmena cuyo archivo de respaldo es un blob `.dat` con payload.

Oportunidades de detección

Misma postura blue-team que `NtLoadKey`/`NtLoadKey2`: el evento ETW `Microsoft-Windows-Kernel-Registry` ID 9 (HiveLoaded) es la fuente autoritativa. La señal de calidad es la ruta del *archivo de respaldo* — `RegLoadAppKeyW` carga legítimamente archivos en `C:\Users\<u>\AppData\Local\Packages\<pkg>\Settings\settings.dat`; cualquier otra (especialmente colmenas en `C:\Windows\Temp`, `\ProgramData\` o blobs descargados) es anómala. Combinar con Sysmon Event ID 11 (FileCreate) sobre escrituras `*.dat`/`*.hve` en directorios sospechosos y Event ID 1 (Process Create) que muestre habilitación de `SeRestorePrivilege` para montajes de árbol completo.

Ejemplos de syscalls directos

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
    }
}

Mapeos MITRE ATT&CK

Last verified: 2026-05-20