One of the responsibilities of Microsoft’s Security Engineering Center is to investigate defense in depth techniques that can be used to make it harder for attackers to successfully exploit a software vulnerability. These techniques are commonly referred to as exploit mitigations and have been delivered to users in the form of features like /GS, Data Execution Prevention (DEP), and Address Space Layout Randomization (ASLR). In Windows Server 2008 and Windows Vista SP1, Microsoft released support for a new platform mitigation known as Structured Exception Handler Overwrite Protection (SEHOP). The purpose of this article is to explain the problem this feature is attempting to solve, how it goes about solving it, and what you can do take advantage of it.

The exploitation technique: SEH overwrites

The purpose of the SEHOP mitigation is to prevent an attacker from being able to make use of the Structured Exception Handler (SEH) overwrite exploitation technique. This exploitation technique was publicly documented by David Litchfield of NGS Software in a research paper that he published in September, 2003[1]. Since this publication, the SEH overwrite technique has become a standard weapon in an attacker’s arsenal. Roughly 20% of the exploits included in the latest version of the Metasploit framework make use of the SEH overwrite technique. SEH overwrites are also commonly used by exploits that target the increasing number of browser-based vulnerabilities[4].

At a high-level, the SEH overwrite technique uses a software vulnerability to execute arbitrary code by abusing the 32-bit exception dispatching facilities provided by Windows. At a functional level, an SEH overwrite is generally accomplished by using a stack-based buffer overflow to overwrite an exception registration record that has been stored on a thread’s stack. To provide some context, an exception registration record is composed of two fields: a next pointer and an exception handler function pointer. The next pointer is used to link an exception registration record to the next record in the singly-linked list of registered exception handlers. The exception handler function pointer is called by the Windows exception dispatcher when an exception occurs. The definition for an exception registration record can be seen below:

After an exception registration record has been overwritten, an exception must be raised so that the exception dispatcher will attempt to handle it. This can be accomplished in a number of ways, such as by overwriting a return address on the stack with a bogus address in order to cause an access violation exception to be raised. When an exception is raised, the exception dispatcher will attempt to enumerate the list of exception registration records for the thread and call the exception handler that is associated with each record. By corrupting the next pointer and exception handler function pointer of one of the exception registration records, the exception dispatcher can be made to execute code from an arbitrary address as specified by the corrupt exception handler function pointer.

In many cases, an attacker will choose to overwrite the exception handler function pointer with an address that contains instructions that are equivalent to a pop reg, pop reg, ret. This allows an attacker to reliably execute arbitrary code by transferring control to the EstablisherFrame that the exception dispatcher passes as the second parameter when calling an exception handler. This works because the EstablisherFrame parameter holds the address of the attacker-controlled exception registration record. Attackers have also used heap spraying in conjunction with an SEH overwrite to reliably execute arbitrary code. The following diagram illustrates what an SEH overwrite would typically look like from an exploitation perspective:

The mitigation technique: SEHOP

There are two general approaches that can be considered when attempting to mitigate the SEH overwrite exploitation technique. The first approach involves making changes to the compiled versions of code such that executable files are made to contain metadata that the platform would need to properly mitigate this technique. Microsoft pursued this approach and released a functional mitigation with Visual Studio 2003. This mitigation took the form of a new linker flag known as /SAFESEH. Unfortunately, the need to rebuild executables in combination with the inability to completely handle cases where an exception handler is pointed outside of an image file make the SafeSEH approach less attractive. The details relating to how SafeSEH works are beyond the scope of this article, but more information can be found on MSDN[2].

The second approach involves adding dynamic checks to the exception dispatcher that do not rely on having metadata derived from a binary. This is the approach taken by SEHOP. At a high-level, SEHOP prevents attackers from being able to use the SEH overwrite technique by verifying that a thread’s exception handler list is intact before allowing any of the registered exception handlers to be called. This mitigation technique is made possible because of an implicit side effect of an SEH overwrite. When the majority of stack-based buffer overflows occur, an attacker will implicitly overwrite the next pointer of an exception registration record prior to overwriting the record’s exception handler function pointer. Since the next pointer is corrupted, the integrity of the exception handler chain is broken. This insight, in combination with ASLR, is what allows SEHOP to effectively mitigate SEH overwrites.

From an implementation perspective, SEHOP achieves this functionality in two distinct steps. The first step involves the insertion of a symbolic exception registration record as the tail record in a thread’s exception handler list. This step occurs when a thread first begins executing in user mode. Since exception registration records are always inserted at the head of the exception handler list, the symbolic record is guaranteed to be the final exception registration record.

The second step consists of walking the exception handler list at the time that an exception is being dispatched to ensure that the symbolic record can be reached and that it is valid. This step happens when the exception dispatcher is notified that an exception has occurred in user mode. If the symbolic record cannot be reached, the exception dispatcher can assume that the exception handler list is corrupt and that an SEH overwrite may have occurred. The exception dispatcher is then able to safely terminate the process. If the symbolic record is found, the exception dispatcher is able to proceed as it normally would and call each of the registered exception handlers. An illustration of this logic can be seen in the following diagram:

How you can use SEHOP

SEHOP is enabled by default on Windows Server 2008 and disabled by default on Windows Vista SP1. The primary reason this feature was disabled by default on Windows Vista SP1 was due to a lack of adequate application compatibility data. KB article 956607 documents how SEHOP can be enabled or disabled on a system-wide basis[3].

Wrapping up

We are continuing to investigate new and enhanced exploit mitigation techniques and feel that SEHOP is a valuable addition that can help protect users. We encourage users to enable this feature if it is not enabled by default in order to better protect themselves against the SEH overwrite exploitation technique. For more information about the origins of SEH overwrites and SEHOP, it may be helpful to refer to the cited work[1,5].

Matt Miller, MSEC Security Science

*Posting is provided "AS IS" with no warranties, and confers no rights.*