![]() |
Informative Information for the Uninformed | ![]() |
||||||||||||
![]() |
![]() |
|||||||||||||
![]() ![]() |
![]() |
|
||||||||||||
![]() |
Next: Handling Unhandled Exceptions
Up: Understanding Unhandled Exception Filters
Previous: Understanding Unhandled Exception Filters
Contents
Setting the Top-Level UEFIn order to make it possible for applications to handle all exceptions on a process-wide basis, the exception dispatcher exposes an interface for registering an unhandled exception filter. The purpose of the unhandled exception filter is entirely application specific. It can be used to log extra information about an unhandled exception, perform some advanced error recovery, handle language-specific exceptions, or any sort of other task that may need to be taken when an exception occurs that is not handled. To specify a function that should be used as the top-level unhandled exception filter for the process, a call must be made to kernel32!SetUnhandledExceptionFilter which is prototyped as[6]:
LPTOP_LEVEL_EXCEPTION_FILTER SetUnhandledExceptionFilter( LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter ); When called, this function will take the function pointer passed in as the lpTopLevelExceptionFilter argument and encode it using kernel32!RtlEncodePointer. The result of the encoding will be stored in the global variable kernel32!BasepCurrentTopLevelFilter, thus superseding any previously established top-level filter. The previous value stored within this global variable is decoded using kernel32!RtlDecodePointer and returned to the caller. Again, the encoding and decoding of this function pointer is intended to prevent attackers from being able to use an arbitrary memory overwrite to redirect it as has been done pre-XPSP2. There are two reasons that kernel32!SetUnhandledExceptionFilter returns a pointer to the original top-level UEF. First, it makes it possible to restore the original top-level UEF at some point in the future. Second, it makes it possible to create an implicit ``chain'' of UEFs. In this design, each UEF can make a call down to the previously registered top-level UEF by doing something like the pseudo code below:
... app specific handling ... if (!IsBadCodePtr(PreviousTopLevelUEF)) return PreviousTopLevelUEF(ExceptionInfo); else return EXCEPTION_CONTINUE_SEARCH;
When a block of code that has registered a top-level UEF wishes to
deregister itself, it does so by setting the top-level UEF to the
value that was returned from its call to
kernel32!SetUnhandledExceptionFilter. The reason it does
it this way is because there is no true list of unhandled exception
filters that is maintained. This method of deregistering has one
very important property that will serve as the crux of this
document. Since deregistration happens in this fashion, the
register and deregister operations associated with a top-level UEF
must occur in symmetric order. An example of this is
illustrated in figure
In the diagram in figure
|