NtTerminateEnclave
Tears down an enclave, releasing its VTL1 memory and signalling any threads still inside.
Prototype
NTSTATUS NtTerminateEnclave( PVOID BaseAddress, BOOLEAN WaitForThread );
Arguments
| Name | Type | Dir | Description |
|---|---|---|---|
| BaseAddress | PVOID | in | Base address of the enclave previously returned by NtCreateEnclave. |
| WaitForThread | BOOLEAN | in | TRUE blocks until in-enclave threads exit; FALSE returns immediately and AEX-traps surviving threads asynchronously. |
Syscall IDs by Windows version
| Windows version | Syscall ID | Build |
|---|---|---|
| Win10 1709 | 0x1B4 | win10-1709 |
| Win10 1803 | 0x1B6 | win10-1803 |
| Win10 1809 | 0x1B7 | win10-1809 |
| Win10 1903 | 0x1B8 | win10-1903 |
| Win10 1909 | 0x1B8 | win10-1909 |
| Win10 2004 | 0x1BE | win10-2004 |
| Win10 20H2 | 0x1BE | win10-20h2 |
| Win10 21H1 | 0x1BE | win10-21h1 |
| Win10 21H2 | 0x1C0 | win10-21h2 |
| Win10 22H2 | 0x1C0 | win10-22h2 |
| Win11 21H2 | 0x1CA | win11-21h2 |
| Win11 22H2 | 0x1CE | win11-22h2 |
| Win11 23H2 | 0x1CE | win11-23h2 |
| Win11 24H2 | 0x1D1 | win11-24h2 |
| Server 2019 | 0x1B7 | winserver-2019 |
| Server 2022 | 0x1C6 | winserver-2022 |
| Server 2025 | 0x1D1 | winserver-2025 |
Kernel module
Related APIs
Syscall stub
4C 8B D1 mov r10, rcx B8 D1 01 00 00 mov eax, 0x1D1 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
`NtTerminateEnclave` is the **destructor** for the enclave lifecycle. It marks the enclave as terminated, frees the VTL1 backing pages, and unmaps the VTL0 view. When `WaitForThread` is `TRUE`, the kernel waits for every host thread that entered via `NtCallEnclave` to return naturally — this is the clean shutdown used by `DeleteEnclave`. When `FALSE`, the kernel uses an Asynchronous Enclave Exit (AEX) to force in-flight threads out at the next interrupt boundary; this can be observed by the host as a `STATUS_ENCLAVE_NOT_TERMINATED` from a concurrent `NtCallEnclave`. After return, the base address is invalid — any read by the host raises a normal page fault.
Common malware usage
Low offensive interest. The interesting work happens in `NtCallEnclave`; termination is mostly cleanup. One niche use: an attacker who has bootstrapped a transient enclave-hosted payload (e.g. extracted a wrapped secret via a Microsoft-signed enclave bug) will call `NtTerminateEnclave` immediately after to minimise forensic surface — the VTL1 pages and the in-enclave heap are released and zeroed before any sysmon/EDR enumeration can run.
Detection opportunities
Largely a *correlation* signal — a tight `NtCreateEnclave` … `NtTerminateEnclave` window with no persistent host-side enclave references is consistent with one-shot abuse; legitimate trustlets (LsaIso, vmms) keep enclaves alive for the lifetime of the host. The ETW provider `Microsoft-Windows-Kernel-Memory` records both create and terminate, so the pair can be reconstructed even after the fact. Defenders should treat termination on its own as benign and focus on the create-call-terminate burst pattern.
Direct syscall examples
cClean enclave shutdown
// Tear down a VBS enclave and wait for in-flight threads.
#include <windows.h>
BOOL ShutdownEnclave(PVOID enclaveBase) {
if (!TerminateEnclave(enclaveBase, TRUE /*WaitForThread*/)) {
return FALSE;
}
return DeleteEnclave(enclaveBase); // releases the host-side reservation
}asmx64 direct stub (Win11 24H2)
; Direct syscall stub for NtTerminateEnclave (SSN 0x1D1 on Win11 24H2 / Server 2025)
NtTerminateEnclave PROC
mov r10, rcx ; BaseAddress
mov eax, 1D1h ; SSN
syscall
ret
NtTerminateEnclave ENDPMITRE ATT&CK mappings
Last verified: 2026-05-20