> Windows Syscalls
ntoskrnl.exeT1003.002T1003.004T1012

NtOpenKeyEx

Variante étendue de NtOpenKey avec OpenOptions — requise pour suivre les liens symboliques et l'ouverture en sémantique backup.

Prototype

NTSTATUS NtOpenKeyEx(
  PHANDLE            KeyHandle,
  ACCESS_MASK        DesiredAccess,
  POBJECT_ATTRIBUTES ObjectAttributes,
  ULONG              OpenOptions
);

Arguments

NameTypeDirDescription
KeyHandlePHANDLEoutReçoit le handle vers la clé ouverte en cas de succès.
DesiredAccessACCESS_MASKinMasque d'accès, ex. KEY_READ, KEY_QUERY_VALUE, KEY_WRITE, KEY_ALL_ACCESS.
ObjectAttributesPOBJECT_ATTRIBUTESinOBJECT_ATTRIBUTES contenant le chemin registre NT.
OpenOptionsULONGinDrapeaux : REG_OPTION_BACKUP_RESTORE (utilise SeBackupPrivilege), REG_OPTION_OPEN_LINK (ne suit pas le symlink).

IDs de syscalls par version de Windows

Version de WindowsID de syscallBuild
Win10 15070x10Cwin10-1507
Win10 16070x111win10-1607
Win10 17030x115win10-1703
Win10 17090x117win10-1709
Win10 18030x119win10-1803
Win10 18090x11Awin10-1809
Win10 19030x11Bwin10-1903
Win10 19090x11Bwin10-1909
Win10 20040x120win10-2004
Win10 20H20x120win10-20h2
Win10 21H10x120win10-21h1
Win10 21H20x121win10-21h2
Win10 22H20x121win10-22h2
Win11 21H20x127win11-21h2
Win11 22H20x129win11-22h2
Win11 23H20x129win11-23h2
Win11 24H20x12Bwin11-24h2
Server 20160x111winserver-2016
Server 20190x11Awinserver-2019
Server 20220x126winserver-2022
Server 20250x12Bwinserver-2025

Module noyau

ntoskrnl.exeNtOpenKeyEx

APIs liées

RegOpenKeyExWNtOpenKeyNtOpenKeyTransactedExNtCreateKeyNtQueryKeyNtQueryValueKey

Stub du syscall

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

Notes non documentées

NtOpenKeyEx = `NtOpenKey + OpenOptions`. Les deux seules options pertinentes côté offensif sont `REG_OPTION_BACKUP_RESTORE` (`0x4`) — qui pousse le configuration manager à sauter le check DACL et à se reposer sur `SeBackupPrivilege`/`SeRestorePrivilege` de l'appelant — et `REG_OPTION_OPEN_LINK` (`0x8`) — qui ouvre une clé lien symbolique sans suivre la cible, permettant d'auditer les redirections. Le SSN dérive sensiblement d'une build à l'autre car des syscalls voisins ont été ajoutés/retirés : Win10 1909 = 0x11B, Win10 22H2 = 0x121, Win11 24H2 = 0x12B. Coder en dur les SSN est ici très fragile — Hell's Gate / Halo's Gate est obligatoire pour du multi-build.

Usage courant par les malwares

Deux patrons offensifs. (1) **Accès ruche via privilège** : avec `SeBackupPrivilege` actif (accordé à Administrators et Backup Operators), ouvrir avec `REG_OPTION_BACKUP_RESTORE` contourne la DACL de `\Registry\Machine\SAM` et `\Registry\Machine\SECURITY` sans avoir à impersonner SYSTEM — c'est ce que fait `reg.exe save HKLM\SAM` en interne, et ce dont dépendent la plupart des dumpers SAM modernes (module local SAM de CrackMapExec/NetExec, `secretsdump.py -local-auth`). (2) **Persistance consciente des symlinks** : implants APT enchaînent `NtOpenKeyEx` avec `REG_OPTION_OPEN_LINK` pour introspecter les liens symboliques registre posés par eux-mêmes ou par d'anciennes intrusions (IFEO redirigé vers des clés attaquantes, CLSID COM symlinkés vers HKCU). Les outils forensiques font le même audit avec le même flag.

Opportunités de détection

Mêmes fournisseurs que NtOpenKey — l'ETW Microsoft-Windows-Kernel-Registry journalise chaque open avec PID et accès. L'empreinte de `REG_OPTION_BACKUP_RESTORE` est visible : le processus appelant doit détenir `SeBackupPrivilege` *activé*, ce que Sysmon Event ID 4673 (Sensitive Privilege Use) enregistre à l'exercice — coupler l'usage de `SeBackupPrivilege` à un open ultérieur de `\Registry\Machine\SAM` ou `\Registry\Machine\SECURITY` donne un signal de SAM dump à très forte fidélité. Les EDR enregistrant `CmRegisterCallbackEx` voient la valeur OpenOptions dans `RegNtPreOpenKeyEx`. La règle `RegistryEvent` `Sensitive Registry Object` du template SwiftOnSecurity attrape ça. La sous-catégorie d'audit « Sensitive Privilege Use » (4673/4674) filtrée sur `SeBackupPrivilege` est la baseline la moins chère.

Exemples de syscalls directs

cOpen SAM hive with backup privilege

// Caller must first enable SeBackupPrivilege in its token.
#define REG_OPTION_BACKUP_RESTORE 0x00000004

UNICODE_STRING name;
RtlInitUnicodeString(&name, L"\\Registry\\Machine\\SAM");

OBJECT_ATTRIBUTES oa;
InitializeObjectAttributes(&oa, &name, OBJ_CASE_INSENSITIVE, NULL, NULL);

HANDLE hKey = NULL;
NTSTATUS s = NtOpenKeyEx(&hKey, KEY_READ, &oa,
                         REG_OPTION_BACKUP_RESTORE);

asmDirect stub (SSN 0x12B, Win11 24H2)

; SSN drifts across builds — resolve dynamically when targeting multiple.
NtOpenKeyEx PROC
    mov  r10, rcx
    mov  eax, 12Bh         ; Win11 24H2
    syscall
    ret
NtOpenKeyEx ENDP

rustOpen key but don't follow registry symlink

use ntapi::ntregapi::NtOpenKeyEx;
use ntapi::ntrtl::RtlInitUnicodeString;
use winapi::shared::ntdef::{HANDLE, OBJECT_ATTRIBUTES, OBJ_CASE_INSENSITIVE, UNICODE_STRING};

const REG_OPTION_OPEN_LINK: u32 = 0x0000_0008;

pub unsafe fn open_link(path: *const u16) -> Option<HANDLE> {
    let mut us: UNICODE_STRING = core::mem::zeroed();
    RtlInitUnicodeString(&mut us, path);
    let mut oa = OBJECT_ATTRIBUTES {
        Length: core::mem::size_of::<OBJECT_ATTRIBUTES>() as u32,
        RootDirectory: core::ptr::null_mut(),
        ObjectName: &mut us,
        Attributes: OBJ_CASE_INSENSITIVE,
        SecurityDescriptor: core::ptr::null_mut(),
        SecurityQualityOfService: core::ptr::null_mut(),
    };
    let mut h: HANDLE = core::ptr::null_mut();
    if NtOpenKeyEx(&mut h, 0x20019 /* KEY_READ */, &mut oa, REG_OPTION_OPEN_LINK) == 0 {
        Some(h)
    } else { None }
}

Mappings MITRE ATT&CK

Last verified: 2026-05-20