What is SMEP?
Supervisor Mode Execution Protection (SMEP) is a feature introduced in the third generation of Intel Core processors (Ivy Bridge). It can be enabled by setting the bit 20 of the CR4 register. If SMEP is enabled, attempts to execute code stored in a page not owned by the kernel will be denied (page fault exception will be raised instead).
One of the reasons to introduce SMEP is to prevent a common pattern of kernel vulnerabilities exploits. If the kernel memory can be corrupted in a way that allows diverting kernel execution to an arbitrary address, then the most straightforward way to obtain kernel privileges is to prepare arbitrary shellcode in any executable user page and force the kernel to execute it.
When SMEP is enabled, such an exploit will fail.
The number of discovered Windows kernel vulnerabilities is growing recently; a notable example is Microsoft security bulletin MS13-016 from February 2013, where 30 vulnerabilities were fixed. Zero day Windows kernel vulnerabilities were used in targeted attacks. Kernel vulnerabilities exploits are powerful – they give the attacker total control over the operating system, even if launched by an unprivileged user in a restricted environment, for example in a software sandbox. Therefore mitigation mechanisms, even if imperfect (see the end of the post) are desirable.
Why it is useful to enable SMEP in vSentry micro-VMs?
You may remember from reading the vSentry whitepaper that even if a micro-VM is completely controlled by malicious code, including kernel privileges, vSentry is designed to prevent any damage to the host. Why bother then to detect and prevent certain types of kernel vulnerability exploitation in micro-VMs?
The gain is visibility. While executing a successful privilege escalation in a micro-VM does not allow breaking vSentry’s’ protection, we still would like to know that such an event has occurred. LAVA is a vSentry component that aims to provide advanced analysis capabilities, particularly detection of certain security-related events in micro-VM.
SMEP on Windows 7-based vSentry micro-VM
Microsoft has introduced support for SMEP in Windows 8. There is no such support in the Windows 7 kernel. Therefore, it is the vSentry microvisor that actually enables SMEP in its Windows 7-based micro-VMs, by directly setting the relevant bit in “guest CR4” field of virtual-machine control structure (VMCS). It is a good example of the total control the microvisor can exercise.
Then, when malicious code tries to exploit Windows 7 kernel vulnerability by executing kernel-mode shellcode in an user page, a page fault exception is raised, and…
Normally, an unexpected page fault in Windows kernel mode results in a bugcheck, and one could expect that is what should happen in this scenario. However, apparently the Windows 7 kernel treats this page fault as spurious – after all, the faulting instruction resides in an executable page. The page fault handler restarts the faulting instruction, it faults again, and the cycle repeats infinitely.
The above scenario is a problem, because even though exploitation has been prevented (well, at least turned privilege escalation to DoS) the goal is to let the microvisor know that something wrong has happened. Before SMEP support was added to vSentry, the microvisor configured micro-VMs so that all page faults were handled within a micro-VM, without the need to do vmexit. It is a common practice if using the Extended Page Tables (EPT) feature, as it is optimal for performance. But the outcome was: no bugcheck (easily noticeable by the microvisor), just infinite page faults (not observed by the microvisor, either).
Fortunately, Intel processors have the ability to configure micro-VMs so that page faults are treated selectively, depending on the page fault error code. This is exactly what we need – handle all usual page faults (resulting from e.g. demand paging) within a micro-VM, and exit to the hypervisor only in rare cases when page fault error code indicates a possible attack. More precisely, vmexit should happen upon page fault only if both the I/D (instruction fetch) and P (page present) flags are set in the page fault error code. Currently, the vSentry microvisor configures such treatment, which results in optimal performance and visibility of SMEP violation events.
How about SMEP bypass techniques?
There are quite a few articles about methods to bypass SMEP, for example here. Some of them will work in a vSentry micro-VM. Still, enabling SMEP raises the bar for the attacker. Also, as SMEP is not supported on bare metal Windows 7, an attacker may simply not expect the need to bypass SMEP when trying to exploit a Windows 7-based vSentry micro-VM.
However, note that vSentry can detect the most generic way of bypassing SMEP that relies on disabling SMEP by clearing the respective bit in CR4 register. This exploitation method consists of the following stages:
- Corrupt kernel mode execution context
- Divert execution into a piece of code (stored in kernel-owned pages), that clears SMEP bit in CR4
- Execute arbitrary code, which can be stored in usermode pages.
The element unique for this technique is step 2. It can be achieved using return-oriented programming, or by overwriting executable kernel memory.
The key difference in case of vSentry micro-VMs is that writing to the CR4 register results in vmexit, and the microvisor can check whether the micro-VM is trying to clear the SMEP bit. This presents an opportunity to detect and prevent further malicious code execution. Once again, it highlights the control the microvisor has over the code running in micro-VMs, even if it runs with kernel privileges.