NtInitializeEnclave
Finalises an enclave after image load — verifies signatures and transitions it to executable state.
Prototype
NTSTATUS NtInitializeEnclave( HANDLE ProcessHandle, PVOID BaseAddress, PVOID EnclaveInformation, ULONG EnclaveInformationLength, PULONG EnclaveError );
Arguments
| Name | Type | Dir | Description |
|---|---|---|---|
| ProcessHandle | HANDLE | in | Handle to the host process. Typically NtCurrentProcess() ((HANDLE)-1). |
| BaseAddress | PVOID | in | Base address returned by NtCreateEnclave for the enclave being finalised. |
| EnclaveInformation | PVOID | in | Type-specific init blob: ENCLAVE_INIT_INFO_SGX (SIGSTRUCT + EINITTOKEN) or ENCLAVE_INIT_INFO_VBS (LengthOfStruct + ThreadCount). |
| EnclaveInformationLength | ULONG | in | Size in bytes of EnclaveInformation. Mismatch with the enclave type triggers STATUS_INVALID_PARAMETER. |
| EnclaveError | PULONG | out | Receives the secure-kernel / SGX EINIT error code on STATUS_ENCLAVE_FAILURE returns. |
Syscall IDs by Windows version
| Windows version | Syscall ID | Build |
|---|---|---|
| Win10 1607 | 0xF2 | win10-1607 |
| Win10 1703 | 0xF5 | win10-1703 |
| Win10 1709 | 0xF6 | win10-1709 |
| Win10 1803 | 0xF7 | win10-1803 |
| Win10 1809 | 0xF8 | win10-1809 |
| Win10 1903 | 0xF9 | win10-1903 |
| Win10 1909 | 0xF9 | win10-1909 |
| Win10 2004 | 0xFE | win10-2004 |
| Win10 20H2 | 0xFE | win10-20h2 |
| Win10 21H1 | 0xFE | win10-21h1 |
| Win10 21H2 | 0xFF | win10-21h2 |
| Win10 22H2 | 0xFF | win10-22h2 |
| Win11 21H2 | 0x104 | win11-21h2 |
| Win11 22H2 | 0x105 | win11-22h2 |
| Win11 23H2 | 0x105 | win11-23h2 |
| Win11 24H2 | 0x107 | win11-24h2 |
| Server 2016 | 0xF2 | winserver-2016 |
| Server 2019 | 0xF8 | winserver-2019 |
| Server 2022 | 0x103 | winserver-2022 |
| Server 2025 | 0x107 | winserver-2025 |
Kernel module
Related APIs
Syscall stub
4C 8B D1 mov r10, rcx B8 07 01 00 00 mov eax, 0x107 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
Undocumented notes
`NtInitializeEnclave` is the **measurement-and-seal** step. By the time it is called, the host has used `NtLoadEnclaveData` to copy the enclave image (and its data pages) into the reserved VTL1 range. Initialisation does three things: (1) compute the enclave's identity hash (MRENCLAVE on SGX, image-hash on VBS), (2) verify the developer signature against the embedded `IMAGE_ENCLAVE_CONFIG` policy and — on VBS — against HVCI's allowed-enclave list, (3) flip the enclave from a *loading* state to an *executable* state. After this call, no further `NtLoadEnclaveData` is permitted on the enclave: its memory layout is frozen. The `ThreadCount` field of `ENCLAVE_INIT_INFO_VBS` reserves the maximum number of enclave threads (analogous to SGX TCS count) — this is the count of host threads that can simultaneously be inside the enclave via `NtCallEnclave`.
Common malware usage
An adversary who has reached `NtInitializeEnclave` has already passed image signing — the practical attacks happen *before* this call (planting a benign-looking enclave image), or rely on a bug *inside* a Microsoft-signed enclave that exposes a primitive callable post-init (the Recon 2023 work). The init call itself is just the trip wire that grants execution. Defenders should care that a successful return means a verified-signed enclave is now live; an attacker holding a stolen Microsoft enclave key would chain `NtCreateEnclave` → `NtLoadEnclaveData` (× N) → `NtInitializeEnclave` → `NtCallEnclave` to bootstrap an unauditable VTL1 payload. No commodity malware is publicly known to do this end-to-end today.
Detection opportunities
ETW `Microsoft-Windows-Kernel-Memory` event 6 (VBS enclave activity) and the `Microsoft-Windows-Hyper-V-Worker/Operational` log both record a successful initialisation. Cross-reference with the `Microsoft-Windows-Security-Mitigations` log to confirm the enclave's image hash. Any init coming from a process whose loaded modules do *not* contain a Microsoft-rooted `IMAGE_ENCLAVE_CONFIG.EnclaveFlags = ENCLAVE_FLAG_PRIMARY_IMAGE` and an MS-issued signer is high signal — almost certainly a research tool, a Microsoft Insider build component, or an attacker with a stolen key. Pair the syscall with the host's full process tree for context: legitimate enclave hosts (LsaIso, vmms, vmcompute) have a stable launch ancestry.
Direct syscall examples
cVBS enclave bring-up (step 3/3 — initialize)
// After CreateEnclave + LoadEnclaveData (the enclave DLL is now mapped into VTL1),
// initialise to lock layout and verify the signature against HVCI's allowlist.
#include <windows.h>
typedef struct _ENCLAVE_INIT_INFO_VBS {
ULONG Length;
ULONG ThreadCount;
} ENCLAVE_INIT_INFO_VBS;
BOOL FinalizeVbsEnclave(PVOID enclaveBase) {
ENCLAVE_INIT_INFO_VBS init = {0};
init.Length = sizeof(init);
init.ThreadCount = 4; // max concurrent host->enclave calls
DWORD enclaveError = 0;
if (!InitializeEnclave(
GetCurrentProcess(),
enclaveBase,
&init, sizeof(init),
&enclaveError)) {
// STATUS_ENCLAVE_NOT_TERMINATED / STATUS_INVALID_SIGNATURE / etc.
return FALSE;
}
return TRUE;
}asmx64 direct stub (Win11 24H2)
; Direct syscall stub for NtInitializeEnclave (SSN 0x107 on Win11 24H2 / Server 2025)
NtInitializeEnclave PROC
mov r10, rcx ; ProcessHandle
mov eax, 107h ; SSN
syscall
ret
NtInitializeEnclave ENDPMITRE ATT&CK mappings
Last verified: 2026-05-20