Why Processor Rings Are Not Enough
Processor rings alone proved insufficient. Attackers exploit the kernel directly or abuse bring-your-own-vulnerable-driver techniques to run code at ring 0. VBS adds a new security boundary by reusing HyperV’s VM isolation primitive. Instead of isolating two VMs, it isolates a region of memory within the OS itself. This creates Virtual Trust Levels. VTL0 is the normal OS: user mode and kernel. VTL1 is more privileged: VTL0 code cannot read or write VTL1 memory, but VTL1 can access VTL0. VTL1 adds a secure kernel and Isolated User Mode (IUM), which survives even a full kernel compromise.
VBS Enclaves: Isolated Memory Inside a Process
An enclave is an isolated memory region within a process. The process cannot read or write enclave memory; it can only call methods the enclave exports. VBS enclaves implement this by splitting a process in two: the normal half runs in VTL0 user mode, the enclave runs in IUM (VTL1). That placement means even a compromised OS cannot read enclave data. A practical use: store an API key in the enclave, expose only an “encrypt this value” function, and the key never touches VTL0 memory. Loading an enclave requires a DLL signed with a Microsoft certificate designated for enclaves.
Getting Code Into a Signed Enclave
The signing requirement is the main barrier. Four paths exist. First: obtain a legitimate certificate, as threat actors have done with drivers and executables. Second: exploit the loader’s signature validation (a patched example was demonstrated publicly the year before). Third: abuse debuggable enclaves. When compiling with a debug flag, the secure kernel allows VTL0 code to read and modify the enclave’s memory. An attacker who finds a signed debuggable enclave can load it, overwrite an exported function with shellcode, and call it via CallEnclave. Fourth: bring your own vulnerable enclave.
Mirage: Sleep Obfuscation via CVE-2023-36880
CVE-2023-36880 is an information disclosure vulnerability in a Microsoft Edge enclave module, found by Alex Gough of Chrome security. It provides arbitrary read/write into the enclave’s address space. Direct shellcode execution fails: enclaves enforce Arbitrary Code Guard (ACG), so no dynamic code runs and no pages can be made writable. David built Mirage around this. Mirage loads the vulnerable enclave, writes shellcode into VTL1 via the exploit, then re-triggers the bug to write that shellcode back into VTL0, executes it, and immediately overwrites the buffer with benign data. The PoC is on Akamai’s GitHub.
What Attackers Can Do From Inside VTL1
Microsoft restricts enclave APIs: no file I/O, no networking, no process access, no registry. But attack primitives remain. The enclave reads and writes VTL0 memory of its host process. CallEnclave is dual-use: from inside the enclave it invokes any VTL0 address, so an EDR sees only a call followed by a new thread. Anti-debugging is the sharpest primitive. Checking the Process Environment Block for debugger flags, or using RDTSC to measure CPU clock cycles, both work from VTL1. A VTL0 debugger cannot patch out the check. Moving decryption logic into the enclave makes it unavoidable.
Notable Quotes
zero visibility into anything that goes Ori David · ▶ 10:40
if you do today, no one will detect. Um Ori David · ▶ 16:57
So what can we do? Ori David · ▶ 28:00
Key Takeaways
- VBS enclaves run in VTL1, giving code complete isolation from EDR hooks and memory scans.
- CVE-2023-36880 in a Microsoft Edge enclave enables Mirage, a sleep obfuscation technique that hides shellcode in VTL1.
- Debuggable enclave modules allow shellcode injection via CallEnclave, with API calls invisible to VTL0 security tools.
- Enclave-based anti-debugging using RDTSC and PEB inspection cannot be patched out by a VTL0 debugger.
About the Speaker(s)
Ori David is a senior security researcher at Akamai, focused on offensive security, malware analysis, and threat hunting.