NtCreateEnclave
Allokiert eine neue Enklave (SGX oder VBS/VTL1) im Adressraum eines Zielprozesses.
Prototyp
NTSTATUS NtCreateEnclave( HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits, SIZE_T Size, SIZE_T InitialCommitment, ULONG EnclaveType, PVOID EnclaveInformation, ULONG EnclaveInformationLength, PSIZE_T EnclaveError );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| ProcessHandle | HANDLE | in | Handle auf den Host-Prozess. NtCurrentProcess() ((HANDLE)-1) ist der einzige praktikable Wert. |
| BaseAddress | PVOID* | in/out | Zeiger auf die gewünschte Basis. NULL lässt den Kernel wählen. Empfängt die gewählte Basis bei Erfolg. |
| ZeroBits | ULONG_PTR | in | Anzahl der Null-Bits in den höchstwertigen Bits von BaseAddress. Üblicherweise 0. |
| Size | SIZE_T | in | Gesamte Adressbereichsgröße der Enklave in Bytes. Zweierpotenz auf SGX; seitenaligned auf VBS. |
| InitialCommitment | SIZE_T | in | Initial committete Bytes; der Rest wird reserviert. 0 = nur reservieren. |
| EnclaveType | ULONG | in | ENCLAVE_TYPE_SGX (1), ENCLAVE_TYPE_SGX2 (2) oder ENCLAVE_TYPE_VBS (0x10). SGX seit 2024 deprecated. |
| EnclaveInformation | PVOID | in | Typabhängige Erzeugungsstruktur: ENCLAVE_CREATE_INFO_SGX oder ENCLAVE_CREATE_INFO_VBS (Owner-ID + Flags). |
| EnclaveInformationLength | ULONG | in | Größe von EnclaveInformation in Bytes. |
| EnclaveError | PSIZE_T | out | Empfängt den hardware-/securekernel-spezifischen Fehlercode, wenn NTSTATUS STATUS_ENCLAVE_FAILURE ist. |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1607 | 0x9E | win10-1607 |
| Win10 1703 | 0xA1 | win10-1703 |
| Win10 1709 | 0xA2 | win10-1709 |
| Win10 1803 | 0xA3 | win10-1803 |
| Win10 1809 | 0xA3 | win10-1809 |
| Win10 1903 | 0xA4 | win10-1903 |
| Win10 1909 | 0xA4 | win10-1909 |
| Win10 2004 | 0xA8 | win10-2004 |
| Win10 20H2 | 0xA8 | win10-20h2 |
| Win10 21H1 | 0xA8 | win10-21h1 |
| Win10 21H2 | 0xA9 | win10-21h2 |
| Win10 22H2 | 0xA9 | win10-22h2 |
| Win11 21H2 | 0xAB | win11-21h2 |
| Win11 22H2 | 0xAC | win11-22h2 |
| Win11 23H2 | 0xAC | win11-23h2 |
| Win11 24H2 | 0xAE | win11-24h2 |
| Server 2016 | 0x9E | winserver-2016 |
| Server 2019 | 0xA3 | winserver-2019 |
| Server 2022 | 0xAB | winserver-2022 |
| Server 2025 | 0xAE | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
4C 8B D1 mov r10, rcx B8 AE 00 00 00 mov eax, 0xAE 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
`NtCreateEnclave` ist der Einstiegspunkt zu Windows' beiden Enklaven-Technologien: **Intel SGX** (`ENCLAVE_TYPE_SGX`/`SGX2`) und **Virtualization-Based-Security-Enklaven** (`ENCLAVE_TYPE_VBS` = 0x10). SGX ist faktisch tot — Intel hat SGX im Client-Core ab 12. Gen entfernt, und Microsoft deprecated die API-Oberfläche seit 2024. VBS-Enklaven sind die strategische Primitive: ein Stück Adressraum in einem User-Mode-Prozess, dessen Code und Daten in **VTL1** (Virtual Trust Level 1) ausgeführt werden — einer höher privilegierten Vertrauensebene, die der **Secure Kernel** (securekernel.exe) auf Hyper-V verwaltet. Aus Sicht des Host-Prozesses ist die Enklave ein normaler Speicherbereich; aus Sicht des *Kernels* ist sie opak — VTL0 (wo ntoskrnl läuft) kann VTL1-Seiten weder lesen noch schreiben. Erstellung erfordert `SeEnableVirtualizationPrivilege` (nur signierte Prozesse mit `IMAGE_ENCLAVE_CONFIG` haben es) und das endgültige Enklaven-Image muss Authenticode-signiert mit einem Microsoft-Enclave-Signing-Cert sein (oder Debug-Enklave auf Test-Signed-Maschine). Der Host bindet `vertdll.dll`, das die Create/Init/Call/Load-Sequenz an das LSASS-nahe `LsaIso.exe`-Trustlet-Modell marshallt. Heutige Produktivnutzer: **Credential Guard**, **vTPM**, **Win32k-Mitigation-Attestierung** und einige Microsoft-Forschungs-Deployments.
Häufige Malware-Nutzung
Enklaven sind eine **offensive Primitive im Forschungsstadium**, noch keine feste Größe in Commodity-Malware. Der Reiz ist strukturell: VTL0-Kernel-Mode-EDR-Driver (jeder Microsoft-, CrowdStrike-, SentinelOne-, Defender-Driver) **können VTL1-Speicher nicht lesen** — Hyper-V verweigert das Mapping. Shellcode in einer Enklave ist also für Kernel-Mode-AV-Scans unsichtbar; Kernel-Callbacks feuern nur nachträglich auf die *Seiteneffekte*. Bemerkenswerte Public Work: **Schenk & Park (Black Hat USA 2022)** zur Enklaven-Isolation; **Yuste / Soriano-Salvador (Recon 2023)** demonstrierten einen VBS-Enklaven-Loader für beliebigen unsignierten Shellcode via Missbrauch eines signierten Loader-Stubs; **TrustedSec** und **MDSec** haben öffentliche PoCs. Die praktische Barriere ist die *Signaturpflicht* — Missbrauch erfordert heute (a) einen gestohlenen Microsoft-Enclave-Signing-Key, (b) eine Trustlet-Schwachstelle mit privatem Code-Signing-Key oder (c) einen Microsoft-signierten Enklaven-Loader mit Memory-Corruption-Bug (der realistischste Weg). Keine breit attribuierte In-the-Wild-Familie nutzt bisher Enklaven.
Erkennungsmöglichkeiten
Enklaven-Erstellung ist **auf normalen Endpoints nahe null** — das ist die gesamte Erkennungsstrategie. ETW-Provider `Microsoft-Windows-Kernel-Memory` emittiert Events bei VBS-Enklaven-Erzeugung; `Microsoft-Windows-Hyper-V-Worker` zeigt VTL1-Aktivität. Auf Win11 24H2 enthält `Microsoft-Windows-Security-Mitigations/KernelMode` den Enklaven-Lifecycle. Praktischer Hunt: Prozesse listen, die das Recht `SeEnableVirtualizationPrivilege` halten, mit dem Vorhandensein eines `IMAGE_ENCLAVE_CONFIG`-Directory in ihren geladenen Modulen abgleichen und auf alles alarmieren, was **nicht** `lsass.exe`, `LsaIso.exe`, `securekernel.exe`-Peers oder bekannte Microsoft-Trustlets ist. EDR-Vendoren *sehen* die Enklaven-interne Ausführung nicht, aber sie sehen die `NtCreateEnclave` / `NtLoadEnclaveData` / `NtInitializeEnclave`-Syscall-Sequenz des Hosts — hooken (oder Kernel-Syscall-ETW abgreifen) und die Kette außerhalb von `lsass` als High-Fidelity-Signal behandeln. Defender nutzt die HVCI-Schicht, um unsignierte Enklaven-Images abzulehnen; HVCI niemals in verwalteten Umgebungen deaktivieren.
Direkte Syscall-Beispiele
cVBS enclave bring-up (step 1/3 — create)
// Minimal VBS enclave creation skeleton. Requires:
// * Host binary compiled with /ENCLAVE flag and an IMAGE_ENCLAVE_CONFIG directory
// * Enclave DLL Authenticode-signed with a Microsoft-issued enclave cert
// * SeEnableVirtualizationPrivilege available (granted to host by signing policy)
// See NtInitializeEnclave + NtCallEnclave for the rest of the lifecycle.
#include <windows.h>
#include <ntsecapi.h>
typedef struct _ENCLAVE_CREATE_INFO_VBS {
ULONG Flags; // 0 or ENCLAVE_VBS_FLAG_DEBUG
UCHAR OwnerID[32]; // 32-byte owner identity
} ENCLAVE_CREATE_INFO_VBS;
PVOID CreateVbsEnclave(SIZE_T size) {
ENCLAVE_CREATE_INFO_VBS info = {0};
info.Flags = ENCLAVE_VBS_FLAG_DEBUG; // omit in production
// OwnerID can be left zero for a single-owner test enclave
PVOID base = CreateEnclave(
GetCurrentProcess(),
NULL, // let kernel choose base
size,
0, // initial commit = 0
ENCLAVE_TYPE_VBS,
&info, sizeof(info),
NULL); // enclaveError
if (!base) {
DWORD ec = GetLastError(); // NTSTATUS-mapped
return NULL;
}
return base;
}asmx64 direct stub (Win11 24H2)
; Direct syscall stub for NtCreateEnclave (SSN 0xAE on Win11 24H2 / Server 2025)
; Note: enclave SSNs drift across builds — resolve dynamically for portable code.
NtCreateEnclave PROC
mov r10, rcx ; ProcessHandle
mov eax, 0AEh ; SSN
syscall
ret
NtCreateEnclave ENDPrustwindows-sys CreateEnclave wrapper
// Cargo: windows-sys = { version = "0.59", features = [
// "Win32_System_Threading", "Win32_Foundation", "Win32_System_Memory"
// ] }
use std::ptr::{null, null_mut};
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::System::Threading::GetCurrentProcess;
#[repr(C)]
struct EnclaveCreateInfoVbs {
flags: u32,
owner_id: [u8; 32],
}
extern "system" {
fn CreateEnclave(
process: HANDLE, base: *const u8, size: usize, initial_commit: usize,
ty: u32, info: *const core::ffi::c_void, info_len: u32, err: *mut u32,
) -> *mut core::ffi::c_void;
}
const ENCLAVE_TYPE_VBS: u32 = 0x10;
const ENCLAVE_VBS_FLAG_DEBUG: u32 = 1;
pub unsafe fn create_vbs_enclave(size: usize) -> Option<*mut core::ffi::c_void> {
let info = EnclaveCreateInfoVbs { flags: ENCLAVE_VBS_FLAG_DEBUG, owner_id: [0u8; 32] };
let mut enclave_err: u32 = 0;
let base = CreateEnclave(
GetCurrentProcess(), null(), size, 0,
ENCLAVE_TYPE_VBS,
&info as *const _ as *const _, core::mem::size_of::<EnclaveCreateInfoVbs>() as u32,
&mut enclave_err,
);
if base.is_null() { None } else { Some(base) }
}MITRE ATT&CK-Mappings
Last verified: 2026-05-20