> Windows Syscalls
ntoskrnl.exeT1620T1574T1106

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

NameTypeDirDescription
ProcessHandleHANDLEinHandle auf den Host-Prozess. NtCurrentProcess() ((HANDLE)-1) ist der einzige praktikable Wert.
BaseAddressPVOID*in/outZeiger auf die gewünschte Basis. NULL lässt den Kernel wählen. Empfängt die gewählte Basis bei Erfolg.
ZeroBitsULONG_PTRinAnzahl der Null-Bits in den höchstwertigen Bits von BaseAddress. Üblicherweise 0.
SizeSIZE_TinGesamte Adressbereichsgröße der Enklave in Bytes. Zweierpotenz auf SGX; seitenaligned auf VBS.
InitialCommitmentSIZE_TinInitial committete Bytes; der Rest wird reserviert. 0 = nur reservieren.
EnclaveTypeULONGinENCLAVE_TYPE_SGX (1), ENCLAVE_TYPE_SGX2 (2) oder ENCLAVE_TYPE_VBS (0x10). SGX seit 2024 deprecated.
EnclaveInformationPVOIDinTypabhängige Erzeugungsstruktur: ENCLAVE_CREATE_INFO_SGX oder ENCLAVE_CREATE_INFO_VBS (Owner-ID + Flags).
EnclaveInformationLengthULONGinGröße von EnclaveInformation in Bytes.
EnclaveErrorPSIZE_ToutEmpfängt den hardware-/securekernel-spezifischen Fehlercode, wenn NTSTATUS STATUS_ENCLAVE_FAILURE ist.

Syscall-IDs pro Windows-Version

Windows-VersionSyscall-IDBuild
Win10 16070x9Ewin10-1607
Win10 17030xA1win10-1703
Win10 17090xA2win10-1709
Win10 18030xA3win10-1803
Win10 18090xA3win10-1809
Win10 19030xA4win10-1903
Win10 19090xA4win10-1909
Win10 20040xA8win10-2004
Win10 20H20xA8win10-20h2
Win10 21H10xA8win10-21h1
Win10 21H20xA9win10-21h2
Win10 22H20xA9win10-22h2
Win11 21H20xABwin11-21h2
Win11 22H20xACwin11-22h2
Win11 23H20xACwin11-23h2
Win11 24H20xAEwin11-24h2
Server 20160x9Ewinserver-2016
Server 20190xA3winserver-2019
Server 20220xABwinserver-2022
Server 20250xAEwinserver-2025

Kernel-Modul

ntoskrnl.exeNtCreateEnclave

Verwandte APIs

CreateEnclaveNtInitializeEnclaveNtLoadEnclaveDataNtCallEnclaveNtTerminateEnclaveIsEnclaveTypeSupportedDeleteEnclave

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.

Erkennungs­mö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 ENDP

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