Old Meets New: Microsoft Windows SafeSEH Incompatibility

By Joshua J. Drake ·

In recent years, Microsoft has made great strides to improve product security. This momentum can be seen clearly in their investments in security-focused processes, development, and research. The release of anti-exploitation features such as DEP, ASLR, Stack Cookies and SafeSEH are products of their commitment to security. Unfortunately, SafeSEH was incorrectly implemented on some versions of Windows leading to a loophole in the technology.


For quite a while, exploit developers would leverage the Structured Exception Handling (SEH) functionality to execute shellcode.  In order to frustrate exploitation, Microsoft added SafeSEH to the Microsoft Visual Studio .NET 2003 compiler. The SafeSEH feature allows only legitimate exception handlers to execute. It is implemented in two parts; a compile-time part and a runtime component.  The compile-time component begins when a module is compiled with the SafeSEH linker flag. First, the compiler will gather a list of legitimate exception handlers within the program. The compiler then stores the list into the executable module within the Portable Executable (PE) Load Configuration optional header. Within this header, a pointer named the Safe Exception Handler Table points to the list of exception handlers. Later, when an exception occurs, the operating system exception handling code uses the runtime component of SafeSEH, which ensure all exception handlers are legitimate before execution is transferred to any handler.

Implementation Details

The runtime component is implemented within the ntdll.dll module. When an exception occurs, the RtlDispatchException function is tasked with deciding how it should be handled. First, the exception passes through the registered Vectored exception handlers. If the exception was not handled, RtlDispatchException moves on to processing the stack-based SEH chain. The chain is made up of EXCEPTION_REGISTRATION records, which contain a pointer to the next record and the address of the exception handler function to be called. Before calling any handler functions in the chain, RtlDispatchException calls the RtlIsValidHandler function to validate the exception handler, including checking SafeSEH.


Inside RtlIsValidHandler, the SafeSEH functionality is implemented within the RtlCaptureImageExceptionValues function. As shown below, this function checks if a Load Configuration structure exists within the PE optional data directory. Once found, the handler function will be checked against the Safe Exception Handlers Table values. If the exception handler is found in the list, RtlIsValidHandler will return 1 and the handler will be executed via the RtlpExecuteHandlerForException function. Otherwise, RtlIsValidHandler returns 0 and the handler will not be executed.


RtlCaptureImageExceptionValues flow graph excerpt

RtlCaptureImageExceptionValues flow graph excerpt


The Problem

>As shown above, RtlCaptureImageExceptionValues determines the existence of the Load Configuration by checking index 10 within the PE Data Directory. If nothing is found, the module is assumed to be incompatible with SafeSEH and the handler is treated as legitimate. When index 10 is found, the code compares the size of the directory entry to 64. This comparison originates from the PE/COFF specification that states, “For compatibility with Windows XP and earlier versions of Windows, the size must be 64 for x86 images.” If it does not match, the module is assumed to be incompatible with SafeSEH and the handler is treated as legitimate. If it does match, the handler is vetted against the list of legitimate exception handlers.

Looking directly at a binary leads to an interesting discovery. As shown in Figure 3, the size of the Load Configuration within the data directory of msvcr71.dll is actually 72. When determining the module’s compatibility with SafeSEH, the comparison with 64 fails and all addresses within this module are treated as a legitimate exception handler.

The DATA_DIRECTORYitem size (in tooltip)

The DATA_DIRECTORYitem size (in tooltip)

Using the dumpbin program from the Microsoft Compiler, it is clear that the module is intended to be compatible with SafeSEH. Figure 3 shows the relevant output with the anomalous value highlighted in red. However, as was stated previously, if any module has a Load Configuration Directory size other than 64, certain versions of Windows will assume the module is not compatible with SafeSEH. Therefore, some modules that are compiled with SafeSEH compatibility do not possess the intended protection. A scan of an updated Windows 7 SP1 machine revealed PuTTY 0.61 and various VMware products also contain binaries with an incorrect directory size, proving that the scope of this issue is wider than a single DLL.

Microsoft ® COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file C:\Program Files (x86)\Java\jre6\bin\msvcr71.dll
49078 [ 48]RVA [size] of Load Configuration Directory
Section contains the following load config:
00000048 size
7C38B118 Security Cookie
7C3890C0 Safe Exception Handler Table
4 Safe Exception Handler Count


DUMPBIN output excerpt for JRE6 msvcr71

Windows XP SP3 contains a different implementation in ntdll. In that version, an additional check permits the data directory item size to differ from 64 so long as it matches the size contained within the Load Configuration data itself. The more permissive check present on Windows XP SP3 correctly processes msvcr71 and the use of arbitrary addresses as exception handlers is correctly blocked.  Therefore, Windows XP SP3 is not affected by this issue.

Vendor Response

After discussing this issue with Microsoft, it became clear that this is only an issue when the original RTM version of the VC7.1 compiler is used. Contacting MSRC led to an investigation being opened. During coordination, the issue was initially classified as a defense in depth measure and not as a vulnerability. MSRC specifically stated, “Considering this, we don't have fixed a specific timeline for defense in depth issues, but it will be surely addressed in a future security update.” Thankfully, Microsoft made good on that statement and released an update addressing the issue on January 10th, 2012. More information is available from their MS12-001 Security Bulletinand Security Research & Defense blog.


Microsoft PE/COFF Specification, Microsoft, http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/pecoff_v8.docx

OpenRCE.org Portable Executable Reference Poster, Ero Carrera Ventura,http://www.openrce.org/reference_library/files/reference/PE%20Format.pdf

/SAFESEH Reference, Microsoft, http://msdn.microsoft.com/en-us/library/9a89h429(v=vs.80).aspx

DUMPBIN Reference, Microsoft, http://msdn.microsoft.com/en-us/library/c1h23y6c(v=vs.71).aspx

Preventing the Exploitation of Structured Exception Handler (SEH) Overwrites with SEHOP, Microsoft,http://blogs.technet.com/b/srd/archive/2009/02/02/preventing-the-exploitation-of-seh-overwrites-with-sehop.aspx

Enhanced Mitigation Experience Toolkit v2.1, Microsoft,http://www.microsoft.com/download/en/details.aspx?id=1677

More information on the impact of MS12-001 http://blogs.technet.com/b/srd/archive/2012/01/10/more-information-on-the-impact-of-ms12-001.aspx