NtOpenKey
Ouvre une clé de registre existante — entrée noyau de RegOpenKeyEx, utilisée pour atteindre les ruches SAM, SECURITY et de persistance.
Prototype
NTSTATUS NtOpenKey( PHANDLE KeyHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes );
Arguments
| Name | Type | Dir | Description |
|---|---|---|---|
| KeyHandle | PHANDLE | out | Reçoit le handle vers la clé ouverte en cas de succès. |
| DesiredAccess | ACCESS_MASK | in | Masque d'accès, ex. KEY_READ, KEY_QUERY_VALUE, KEY_ENUMERATE_SUB_KEYS, KEY_ALL_ACCESS. |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | OBJECT_ATTRIBUTES contenant le chemin registre NT, ex. \Registry\Machine\SAM\SAM. |
IDs de syscalls par version de Windows
| Version de Windows | ID de syscall | Build |
|---|---|---|
| Win10 1507 | 0x12 | win10-1507 |
| Win10 1607 | 0x12 | win10-1607 |
| Win10 1703 | 0x12 | win10-1703 |
| Win10 1709 | 0x12 | win10-1709 |
| Win10 1803 | 0x12 | win10-1803 |
| Win10 1809 | 0x12 | win10-1809 |
| Win10 1903 | 0x12 | win10-1903 |
| Win10 1909 | 0x12 | win10-1909 |
| Win10 2004 | 0x12 | win10-2004 |
| Win10 20H2 | 0x12 | win10-20h2 |
| Win10 21H1 | 0x12 | win10-21h1 |
| Win10 21H2 | 0x12 | win10-21h2 |
| Win10 22H2 | 0x12 | win10-22h2 |
| Win11 21H2 | 0x12 | win11-21h2 |
| Win11 22H2 | 0x12 | win11-22h2 |
| Win11 23H2 | 0x12 | win11-23h2 |
| Win11 24H2 | 0x12 | win11-24h2 |
| Server 2016 | 0x12 | winserver-2016 |
| Server 2019 | 0x12 | winserver-2019 |
| Server 2022 | 0x12 | winserver-2022 |
| Server 2025 | 0x12 | winserver-2025 |
Module noyau
APIs liées
Stub du syscall
4C 8B D1 mov r10, rcx B8 12 00 00 00 mov eax, 0x12 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
L'ouverture registre minimale — trois arguments, SSN `0x12` depuis l'aube de NT. L'espace de noms registre NT vit sous `\Registry`, avec `\Registry\Machine` mappé sur HKLM et `\Registry\User\<SID>` sur les ruches utilisateur ; advapi32 `RegOpenKeyEx` réécrit les handles `HKEY_*` prédéfinis vers ces chemins avant d'appeler NtOpenKey. Pas de paramètre `OpenOptions` ici — il faut `NtOpenKeyEx`. Les appelants qui veulent lire SAM/SECURITY doivent d'abord impersonner SYSTEM (`NtOpenProcessToken` sur lsass + `NtDuplicateToken` + `SetThreadToken`) car la DACL de la ruche exclut Administrators par défaut.
Usage courant par les malwares
Porte d'entrée du **vol de credentials via le registre**. Chaînes canoniques : (a) **T1003.002 ruche SAM** — ouvrir `\Registry\Machine\SAM\SAM\Domains\Account\Users\Names\<user>` pour énumérer les comptes, puis parcourir `\...\Users\<RID>\V` pour le hash chiffré, déchiffré avec la BootKey assemblée depuis quatre attributs `Class` de `\Registry\Machine\System\CurrentControlSet\Control\Lsa\{JD,Skew1,GBG,Data}` ; (b) **T1003.004 LSA secrets** — ouvrir `\Registry\Machine\SECURITY\Policy\Secrets\*\CurrVal` pour les mots de passe de comptes de service en cache et les clés DPAPI domain backup ; (c) **énumération de persistance** — ouvrir les Run, IFEO, AppInit_DLLs, Winlogon Notify, ruche services. `lsadump::sam` et `lsadump::secrets` de Mimikatz exécutent exactement ce chemin, tout comme `secretsdump.py` d'Impacket et `reg.exe save HKLM\SAM <file>` suivi de parsing hors-ligne.
Opportunités de détection
L'ETW Microsoft-Windows-Kernel-Registry (`{70EB4F03-C1DE-4F73-A051-33D13D5413BD}`) émet un évènement par open registre avec chemin complet, PID demandeur et masque d'accès. Sysmon Event ID 12 (RegistryEvent CreateKey/SetKey) et 13 (SetValue) couvrent les écritures ; **le côté lecture exige un filtrage Sysmon RegistryEvent type=CreateKey explicite sur `HKLM\SAM`, `HKLM\SECURITY`, `HKLM\Security\Policy\Secrets`** — ce sont les indicateurs de dump à plus forte fidélité. Les EDR hookent `NtOpenKey`/`NtOpenKeyEx` côté noyau via `CmRegisterCallbackEx` (notifications RegNtPreOpenKeyEx / RegNtPostOpenKey). La règle ASR Defender « Block credential stealing from lsass.exe » renchérit indirectement le prélude vol-de-token-LSA. Chasser tout processus non-LSASS/non-svchost ouvrant `\Registry\Machine\SAM` ou `\Registry\Machine\SECURITY`.
Exemples de syscalls directs
cOpen Run key for persistence read
UNICODE_STRING name;
RtlInitUnicodeString(&name,
L"\\Registry\\Machine\\Software\\Microsoft\\Windows\\CurrentVersion\\Run");
OBJECT_ATTRIBUTES oa;
InitializeObjectAttributes(&oa, &name, OBJ_CASE_INSENSITIVE, NULL, NULL);
HANDLE hKey = NULL;
NTSTATUS s = NtOpenKey(&hKey, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &oa);asmDirect stub (SSN 0x12)
NtOpenKey PROC
mov r10, rcx
mov eax, 12h
syscall
ret
NtOpenKey ENDPrustOpen key under impersonation context
use ntapi::ntregapi::NtOpenKey;
use ntapi::ntrtl::RtlInitUnicodeString;
use winapi::shared::ntdef::{HANDLE, OBJECT_ATTRIBUTES, OBJ_CASE_INSENSITIVE, UNICODE_STRING};
pub unsafe fn open_key(path: *const u16, access: u32) -> 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 NtOpenKey(&mut h, access, &mut oa) == 0 { Some(h) } else { None }
}Mappings MITRE ATT&CK
Last verified: 2026-05-20