> Windows Syscalls
ntoskrnl.exeT1620T1574T1106

NtCallEnclave

Überführt die Ausführung vom VTL0-Host-Code in eine Routine innerhalb einer initialisierten Enklave.

Prototyp

NTSTATUS NtCallEnclave(
  PVOID    Routine,
  PVOID    Parameter,
  BOOLEAN  WaitForThread,
  PVOID   *ReturnValue
);

Argumente

NameTypeDirDescription
RoutinePVOIDinVTL1-Adresse der Enklaven-Einstiegsfunktion. Muss im Bereich der initialisierten Enklave liegen und über die Enclave-Config exportiert sein.
ParameterPVOIDinEinzelner opaker Parameter, der der Enklaven-Routine in RCX übergeben wird. Üblicherweise ein Zeiger auf einen vom Host allokierten Request-Puffer.
WaitForThreadBOOLEANinTRUE blockiert, bis ein freier Enklaven-Thread verfügbar ist; FALSE liefert STATUS_ENCLAVE_NOT_TERMINATED, wenn alle reservierten Threads belegt sind.
ReturnValuePVOID*outEmpfängt den PVOID-Rückgabewert der Enklaven-Routine (deren RAX beim Rückkehren nach VTL0).

Syscall-IDs pro Windows-Version

Windows-VersionSyscall-IDBuild
Win10 17090x8Ewin10-1709
Win10 18030x8Fwin10-1803
Win10 18090x8Fwin10-1809
Win10 19030x8Fwin10-1903
Win10 19090x8Fwin10-1909
Win10 20040x91win10-2004
Win10 20H20x91win10-20h2
Win10 21H10x91win10-21h1
Win10 21H20x91win10-21h2
Win10 22H20x91win10-22h2
Win11 21H20x91win11-21h2
Win11 22H20x91win11-22h2
Win11 23H20x91win11-23h2
Win11 24H20x93win11-24h2
Server 20190x8Fwinserver-2019
Server 20220x91winserver-2022
Server 20250x93winserver-2025

Kernel-Modul

ntoskrnl.exeNtCallEnclave

Verwandte APIs

CallEnclaveNtCreateEnclaveNtInitializeEnclaveNtLoadEnclaveDataNtTerminateEnclaveGetProcAddressForCaller

Syscall-Stub

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

`NtCallEnclave` ist der **World-Switch**-Call. Intern führt er ein `EENTER` auf SGX bzw. einen `VMCALL` in den Secure Kernel für VBS aus — beides überträgt schließlich die logische CPU des Host-Threads in VTL1 mit gespeichertem Stack-/Register-Kontext. Die Enklaven-Routine läuft mit einem *frischen* Stack innerhalb des reservierten Enklaven-Bereichs; sie kann den VTL0-Host-Speicher niemals direkt anfassen. Datenaustausch: die Enklave liest `Parameter` (eine VTL0-Adresse, die der Secure Kernel beim Eintritt marshallt) und liefert einen Wert per `*ReturnValue`. Wiedereintritt ist durch `ThreadCount` aus `NtInitializeEnclave` begrenzt. Der User-Mode-Wrapper `CallEnclave` ist ein dünner Shim um diesen Syscall — er holt `Routine` aus der Export-Tabelle der Enklave.

Häufige Malware-Nutzung

Dies ist der Call, der **Angreifer-Code in VTL1 ausführt**, aber erst nachdem die Create/Load/Initialize-Kette die Signaturprüfungen bestanden hat. Realistische Missbrauchswege: (1) eine *Microsoft-signierte* Enklave mit präparierten Parametern aufrufen, die eine bekannte Schwachstelle triggern — die Enklave führt dann Angreifer-Logik mit VTL0-EDR-Blindheit aus; (2) eine *Research-Loader*-Enklave (z. B. der Yuste / Soriano-Salvador-Stub) aufrufen, die in `Parameter` absichtlich einen beliebigen Shellcode-Pointer akzeptiert und in VTL1 dorthin springt. Einmal drin, kann die Enklave `NtCallEnclave` mit `Routine = Adresse außerhalb der Enklave` nutzen, um zurück in den Host zu rufen (der `CallEnclave`-Mechanismus ist bidirektional); diesen Weg nutzt Recon-Class-Research, um normale Syscalls (z. B. `NtAllocateVirtualMemory`) aus der Enklave abzusetzen. EDR sieht den Host-Syscall, kann ihn aber nicht dem Enklaven-Thread zuordnen.

Erkennungs­möglichkeiten

Direkte Telemetrie aus dem Enklaven-Inneren ist von VTL0 aus unmöglich — by design. Stattdessen pivotieren auf (a) die *Frequenz* von `NtCallEnclave` pro Prozess (legitime Trustlets rufen es in stabiler Kadenz; ein Angreifer-Tool zeigt oft einen Burst zum Angriffszeitpunkt), (b) das *Callout*-Muster: eine Enklave, die sofort zurück in VTL0 ruft, um `NtAllocateVirtualMemory`/`NtWriteVirtualMemory` aufzurufen, ist verdächtig. Der ETW-Provider `Microsoft-Windows-Kernel-Memory` (Event 5) traced Enklaven-Entries/Exits, ist aber nicht standardmäßig aktiv — auf wertvollen Endpoints aktivieren. Aus einem Kernel-Driver heraus existiert `KeRegisterEnclaveCallback` *nicht*; den Enklaven-Call können Sie aus einem normalen Driver nicht abfangen. Das Signal muss aus der Host-Syscall-Sequenz kommen.

Direkte Syscall-Beispiele

cVBS enclave bring-up (step 4 — call into VTL1)

// Final step of a minimal enclave session: invoke a named export inside the enclave.
// 'enclaveBase' came from CreateEnclave; 'EnclaveEntry' is exported by the signed enclave DLL.
#include <windows.h>

typedef int (*PENCLAVE_ENTRY)(void *param);

int InvokeEnclave(PVOID enclaveBase, PVOID hostRequest) {
    PENCLAVE_ENTRY entry = (PENCLAVE_ENTRY)GetProcAddressForCaller(
        enclaveBase, "EnclaveEntry");
    PVOID retVal = NULL;
    if (!CallEnclave(entry, hostRequest, TRUE /*WaitForThread*/, &retVal)) {
        return -1;
    }
    return (int)(INT_PTR)retVal;
}

asmx64 direct stub (Win11 24H2)

; Direct syscall stub for NtCallEnclave (SSN 0x93 on Win11 24H2 / Server 2025)
; SSN was 0x91 from Win10 2004 through Win11 23H2 — stable for ~5 years.
NtCallEnclave PROC
    mov  r10, rcx          ; Routine
    mov  eax, 93h          ; SSN
    syscall
    ret
NtCallEnclave ENDP

rustwindows-sys CallEnclave

// Cargo: windows-sys = { version = "0.59", features = ["Win32_System_Threading"] }
use std::ptr::null_mut;
use windows_sys::core::BOOL;

extern "system" {
    fn CallEnclave(
        routine: *const core::ffi::c_void,
        param: *mut core::ffi::c_void,
        wait_for_thread: BOOL,
        ret: *mut *mut core::ffi::c_void,
    ) -> BOOL;
}

pub unsafe fn call_enclave_entry(
    routine: *const core::ffi::c_void,
    request: *mut core::ffi::c_void,
) -> Option<*mut core::ffi::c_void> {
    let mut ret: *mut core::ffi::c_void = null_mut();
    if CallEnclave(routine, request, 1 /*TRUE*/, &mut ret) == 0 {
        return None;
    }
    Some(ret)
}

MITRE ATT&CK-Mappings

Last verified: 2026-05-20