NtLoadEnclaveData
Kopiert einen seitenaligned Puffer (Code oder Daten) vom VTL0-Host in den VTL1-Bereich einer Enklave vor der Initialisierung.
Prototyp
NTSTATUS NtLoadEnclaveData( HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, SIZE_T BufferSize, ULONG Protect, PVOID PageInformation, ULONG PageInformationLength, PSIZE_T NumberOfBytesWritten, PULONG EnclaveError );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| ProcessHandle | HANDLE | in | Handle auf den Host-Prozess, der die Enklave besitzt. Üblicherweise NtCurrentProcess(). |
| BaseAddress | PVOID | in | Ziel-VTL1-Adresse innerhalb der Enklave, an die Buffer kopiert wird. Muss seitenaligned und im reservierten Enklaven-Bereich liegen. |
| Buffer | PVOID | in | Quell-Puffer in VTL0 (das gemappte Enklaven-Image oder eine Datenseite). Seitenaligned. |
| BufferSize | SIZE_T | in | Anzahl zu kopierender Bytes. Muss ein Vielfaches der Seitengröße sein. |
| Protect | ULONG | in | Endgültiger Seitenschutz innerhalb der Enklave (PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE_READ — niemals WRITE+EXECUTE in VBS). |
| PageInformation | PVOID | in | Typabhängiger Deskriptor: ENCLAVE_LOAD_DATA_SGX (SECINFO + EADD-Flags) oder ENCLAVE_LOAD_DATA_VBS (Seitentyp). |
| PageInformationLength | ULONG | in | Größe des PageInformation-Deskriptors in Bytes. |
| NumberOfBytesWritten | PSIZE_T | out | Empfängt die tatsächlich in die Enklave geschriebene Byte-Anzahl (bei Erfolg üblicherweise gleich BufferSize). |
| EnclaveError | PULONG | out | Empfängt den SGX-EADD- oder Securekernel-Fehlercode bei STATUS_ENCLAVE_FAILURE. |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1607 | 0xFA | win10-1607 |
| Win10 1703 | 0xFD | win10-1703 |
| Win10 1709 | 0xFE | win10-1709 |
| Win10 1803 | 0xFF | win10-1803 |
| Win10 1809 | 0x100 | win10-1809 |
| Win10 1903 | 0x101 | win10-1903 |
| Win10 1909 | 0x101 | win10-1909 |
| Win10 2004 | 0x106 | win10-2004 |
| Win10 20H2 | 0x106 | win10-20h2 |
| Win10 21H1 | 0x106 | win10-21h1 |
| Win10 21H2 | 0x107 | win10-21h2 |
| Win10 22H2 | 0x107 | win10-22h2 |
| Win11 21H2 | 0x10C | win11-21h2 |
| Win11 22H2 | 0x10D | win11-22h2 |
| Win11 23H2 | 0x10D | win11-23h2 |
| Win11 24H2 | 0x10F | win11-24h2 |
| Server 2016 | 0xFA | winserver-2016 |
| Server 2019 | 0x100 | winserver-2019 |
| Server 2022 | 0x10B | winserver-2022 |
| Server 2025 | 0x10F | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
4C 8B D1 mov r10, rcx B8 0F 01 00 00 mov eax, 0x10F 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
`NtLoadEnclaveData` ist der **seitenweise Ingest-Call**, der *zwischen* `NtCreateEnclave` und `NtInitializeEnclave` läuft. Auf SGX wird er pro Quellseite zu einem `EADD`; auf VBS kopiert der Secure-Kernel-`IumLoadEnclaveData` den Quell-Puffer über die VTL-Grenze und stempelt die Messung der Zielseite in den laufenden Enklaven-Hash. Der hier übergebene Schutz ist der *endgültige* Schutz — die Enklave kann ihn später nicht ummappen (kein per-Page-`mprotect` in VTL1). Für eine Enklaven-DLL macht `vertdll.dll` einen Aufruf pro `IMAGE_SCN_*`-Section: einen PAGE_READONLY für `.rdata`, einen PAGE_EXECUTE_READ für `.text`, einen PAGE_READWRITE für `.data`. Alle Loads müssen vor `NtInitializeEnclave` erfolgen; danach liefert der Aufruf `STATUS_ENCLAVE_NOT_TERMINATED`.
Häufige Malware-Nutzung
Aus offensiver Sicht ist dies der Aufruf, der *Code physisch in VTL1 platziert*. Die Missbrauchs-Barriere: die geladenen Bytes werden in den Enklaven-Hash gemessen, und dieser Hash muss mit dem matchen, was `IMAGE_ENCLAVE_CONFIG` zur Init-Zeit erlaubt. Zwei reale Hebel: (1) **Microsoft-signierte Enklave mit angreifer-kontrollierten Daten**: harmlose Datenseiten laden, deren Inhalt vom signierten Code als Befehle interpretiert wird — analog zu ROP innerhalb der Enklave; (2) **Research-Loader**: die Yuste / Soriano-Salvador-Arbeit lädt einen signierten *Stub*-Enklave, dessen 'Code' eigentlich ein Mini-Dispatcher ist, der zur `NtCallEnclave`-Zeit einen Shellcode-Pointer akzeptiert — die bösartige Payload wird nie in MRENCLAVE gemessen, nur der Dispatcher. Verteidiger können die geladenen Bytes nachträglich nicht inspizieren — VTL1-Speicher ist für VTL0 opak.
Erkennungsmöglichkeiten
Der Pre-Init-Load-Burst ist hochcharakteristisch: zehn bis hunderte `NtLoadEnclaveData`-Aufrufe in dichter Folge auf derselben Enklaven-Basis, gefolgt von `NtInitializeEnclave`. Der ETW-Provider `Microsoft-Windows-Kernel-Memory` emittiert pro Load ein Event. EDRs, die auf das Host-Syscall-Muster hooken, können die Sequenz trivial flaggen; das schwere Problem ist Attribution — welche DLL wird in die Enklave geladen. Der beste Verteidiger-Hebel ist die *Datei-Quelle*: das Host-Modul, das die Loads ausführt, hat ein `IMAGE_ENCLAVE_CONFIG`-Directory, das die Enklaven-DLL per Image-Hash benennt. Sysmon Event ID 7 (ImageLoad) auf dem Host zeigt das PE-Mapping der Enklaven-DLL vor den Load-Syscalls — beide für nachträgliche Identifikation paaren.
Direkte Syscall-Beispiele
cVBS enclave bring-up (step 2/3 — load image)
// Walk the PE sections of a signed enclave DLL and copy them into the enclave.
// (Helper for the create -> load -> initialize -> call sequence.)
#include <windows.h>
BOOL LoadEnclaveImage(PVOID enclaveBase, PVOID peImage, SIZE_T peSize) {
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)peImage;
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((BYTE*)peImage + dos->e_lfanew);
PIMAGE_SECTION_HEADER sec = IMAGE_FIRST_SECTION(nt);
for (WORD i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++) {
ULONG prot = PAGE_READONLY;
if (sec->Characteristics & IMAGE_SCN_MEM_EXECUTE) prot = PAGE_EXECUTE_READ;
else if (sec->Characteristics & IMAGE_SCN_MEM_WRITE) prot = PAGE_READWRITE;
PVOID dst = (BYTE*)enclaveBase + sec->VirtualAddress;
PVOID src = (BYTE*)peImage + sec->PointerToRawData;
SIZE_T size = ((sec->SizeOfRawData + 0xFFF) & ~0xFFFu);
if (!LoadEnclaveData(
GetCurrentProcess(),
dst, src, size, prot,
NULL, 0, // page info (VBS-specific, may be NULL)
NULL, // bytes written
NULL)) { // enclave error
return FALSE;
}
}
return TRUE;
}asmx64 direct stub (Win11 24H2)
; Direct syscall stub for NtLoadEnclaveData (SSN 0x10F on Win11 24H2 / Server 2025)
NtLoadEnclaveData PROC
mov r10, rcx ; ProcessHandle
mov eax, 10Fh ; SSN
syscall
ret
NtLoadEnclaveData ENDPMITRE ATT&CK-Mappings
Last verified: 2026-05-20