|Informative Information for the Uninformed|
Software-based vulnerabilities are a common problem that affect a wide array of operating systems. In some cases, these vulnerabilities can be exploited with greater ease depending on operating system specific features. One particular case of where this is possible is through the use of an SEH overwrite on 32-bit applications on the Windows platform. An SEH overwrite involves overwriting the Handler associated with an exception registration record. Once this occurs, an exception is generated that results in the overwritten Handler being called. As a result of this, the attacker can more easily gain control of code execution due to the context that the exception handler is called in.
Microsoft has attempted to address the problem of SEH overwrites with enhancements to the exception dispatcher itself and with solutions like SafeSEH and the /GS compiler flag. However, these solutions are limited because they require a recompilation of code and therefore only protect images that have been compiled with these flags enabled. This limitation is something that Microsoft is aware of and it was most likely chosen to reduce the potential for compatibility issues.
To help solve the problem of not offering complete protection against SEH overwrites, this paper has suggested a solution that can be used without any code recompilation and with negligible performance overhead. The solution involves appending a custom exception registration record, known as a validation frame, to the end of the exception list early on in thread startup. When an exception occurs in the context of a thread, the solution intercepts the exception and validates the exception handler chain for the thread by making sure that it can walk the chain until it reaches the validation frame. If it is able to reach the validation frame, then the exception is dispatched like normal. However, if the validation frame cannot be reached, then it is assumed that the exception handler chain is corrupt and that it's possible that an exploit attempt may have occurred. Since exception registration records are always prepended to the exception handler chain, the validation frame is guaranteed to always be the last handler.
This solution relies on the fact that when an SEH overwrite occurs, the Next attribute is overwritten before overwriting the Handler attribute. Due to the fact that attackers typically use the Next attribute as the location at which to store a short jump, it is not possible for them to both retain the integrity of the list and also use it as a location to store code. This important consequence is the key to being able to detect and prevent the leveraging of an SEH overwrite to gain code execution.
Looking toward the future, the usefulness of this solution will begin to wane as 64-bit versions of Windows begin to dominate the desktop environment. The reason 64-bit versions are not affected by this solution is because exception handling on 64-bit versions of Windows is inherently secure due to the way it's been implemented. However, this only applies to 64-bit binaries. Legacy 32-bit binaries that are capable of running on 64-bit versions of Windows will continue to use the old style of exception handling, thus potentially leaving them vulnerable to the same style of attacks depending on what compiler flags were used. On the other hand, this solution will also become less necessary due to the fact that modern 32-bit x86 machines support hardware NX and can therefore help to mitigate the execution of code from the stack. Regardless of these facts, there will always be a legacy need to protect against SEH overwrites, and the solution described in this paper is one method of providing that protection.