Home 20 March 2010  
Main Menu
Home
News
Forums
Downloads
Contact Us
Search i-hacked
Become a Member
- - - - - - -
Computer Components
Consumer Electronics
Electronic Projects
Game Systems
Cell / Phone
Car / Home
Misc
- - - - - - -
Info and Contests
Reviews
About
Login Form





Lost Password?
Latest Edge
Advertisement
Privacy Policy
Vote for us in Top 100 Security Sites
Click here to Vote!
Newsflash
Understanding SEH (Structured Exception Handler) Exploitation Print E-mail
Written by Donny Hubener   
Friday, 03 July 2009

This document is also available for download as a PDF

The Structured Exception Handler (SEH) mechanism in Windows makes use of a data structure called a "Linked List" which contains a sequence of data records where each record has at least one data element field and a reference (pointer) to the next record in the sequence. The last record in the sequence has a Next Record field that points to 0xFFFFFFFF which is the end of the linked list. The diagram below shows a basic linked list example.

A Linked List works well for an exception structure because a new record can easily be inserted dynamically. If we wanted to insert another record, we can simply modify the next record pointers so that the new record is in the sequence. The diagram below shows how a new record containing Hank is inserted between Bob and Steve:

 


General SEH Exploit Design

As best put by Matt Miller, "While typical stack-based buffer overflows work by overwriting the return address in the stack, SEH overwrites work by overwriting the Handler attribute of an exception registration record that has been stored on the stack. Unlike overwriting the return address, where control is gained immediately upon return from the function, an SEH overwrite does not actually gain code execution until after an
exception has been generated. The exception is necessary in order to cause the
exception dispatcher to call the overwritten Handler."

In the case of SEH, the Data Element is actually a pointer that points to a function that attempts to handle the exception which has occurred such as a divide by zero. This could be a function that displays a "Divide by 0" error message pop-up box to the display for the user to see. The diagram below shows how this conceptually appears.

When an exception occurs in a thread of execution code, the system will begin traversing the SEH linked list. The pointer to the exception handling function is used to call the exception function. The exception function can either choose to handle the exception or tell the system to continue checking other exception functions in the list. For example, let's say an excessive string length exception has occurred using the structure shown above. The system will start traversing the SEH linked list and start by first checking the Divide by 0 exception handler function. Since this function does not know how to handle string length issues, it will tell the system to continue checking the other functions by returning EXCEPTION_CONTINUE_SEARCH. This will cause the system to move to the next exception record in the linked list. The next exception function in the list is the excessive string length function. This function will accept to handle the exception and possibly fix the issue that caused the exception.

If the exception function was able to handle the exception, its last act is to return the value EXCEPTION_CONTINUE_EXECUTION. When the operating system sees that EXCEPTION_CONTINUE_EXECUTION was returned, it interprets this to mean that the exception function fixed the problem and the faulting instruction should be restarted.

To better understand how SEH operates, we need to review how a basic stack is populated. The figure below shows how a basic stack may appear at runtime.

Most systems are designed such that the stack will grow downward in memory such that the top of the stack indicated by the ESP (Extended Stack Pointer) register is actually the lowest used memory address in the stack and the bottom of the stack is the highest memory address. When we start building our exploit, we will be using OllyDBG to debug our code. Since OllyDBG displays the stack vertically from low memory addresses to high with the stack growing upward, we have illustrated this in our diagrams to make the concepts easier to follow. However, you may see diagrams from other sources illustrated in reverse.

As an example with the diagram above, when the function funcA is called, the arguments passed to the function are pushed onto the stack first followed by the return address (address to return execution to after function is complete, also called EIP), the caller's EBP (Extended Base Pointer) and any local objects (variables) specific to function funcA. EBP is passed so that each function has a defined stack frame which is a range in memory reserved for a particular function to store information. The diagram above shows that function funcA was called first. While in function funcA, function funcB was called to perform another task and so a stack frame above funcA was created for function funcB. Likewise, while in function funcB, function funcC was called and so a stack frame above funcB was created for function funcC. When funcC completes its operation, its stack frame will be removed from the stack and system will continue to execute function funcB where it left off before calling funcC.

This process of creating and removing stack frames for functions is completed through what is called function prologue and epilogue. The function prologue is a few lines of assembly code which appear at the beginning of a function. It prepares the stack and registers for use within the function. Similarly, the function epilogue appears at the end of the function, and restores the stack and registers back to the state they were in before the function was called.

We mentioned earlier that by using a linked list structure we can insert additional records into the sequence. When a program is under normal operation, it may have functions that call other functions in a nesting fashion. Each of these program functions will generally have its own exception handler. When a new function is called inside an existing function, a new exception handler frame is created on the stack and a pointer to the previous handler's frame is established.

When SEH is used there is a registration process where an exception structure is created for every function as a local variable. The last field of the structure overlaps the location where frame pointer EBP points. Function's prologue creates this structure on its stack frame and registers it with the operating system at runtime. The significance of this is that the pointer to the exception handler and the pointer to the Next exception handler are both stored on the stack in the program function's local variables section of its stack frame.

The diagram below shows how a stack may appear at runtime with SEH applied.


Based on this, we can see that it may be possible to overflow an argument buffer such that the Exception Handler pointer is overwritten. If we can overwrite the Exception Handler pointer, we can direct the execution of code to do something we want as a hacker to take control. Since the Exception Handler pointer is a pointer to a function, we need to point to an address that also uses executable code. In other words, we cannot simply overwrite the Exception Handler with executable shellcode and expect it to run.

It is worth noting that the register FS:0 always points to the start of the exception linked list chain. When a new function is called, the Exception_Registration_Record for the function is added to the stack. At this same time, the FS:0 register will be set to point to the new exception registration record and the Next record will be set to point to the previous value of FS:0. In this fashion, the new function will always be first in the exception list. Think back to our linked list example to better visualize how this is accomplished.

To this point we have talked about the Exception_Registration_Record which contains a pointer to another (Next) Exception_Registration_Record and a pointer to an Exception Handler. The specific prototype for the Handler field is actually a defined structure as:

typedef EXCEPTION_DISPOSITION (*ExceptionHandler)
  (IN EXCEPTION_RECORD ExceptionRecord,
IN PVOID EstablisherFrame,
IN PCONTEXT ContextRecord,
IN PVOID DispatcherContext);

When an exception occurs in a program function, the system exception dispatcher routine runs and sets up its own stack frame. While doing so, it will push elements of this Exception Handler structure onto the stack since this is part of a function prologue to execute the exception code. Keep in mind that this is a separate stack used for the exception dispatcher and not directly related to the program stack that we overwrote with the buffer.

As a hacker, we actually get a little bit fortunate here. The field of most importance is the EstablisherFrame. This field actually points to the address of the exception registration record that was pushed onto the program stack. It is also located at [esp+8] when the Handler is called as part of the dispatcher routine. If we overwrite the Handler with the address of a pop/pop/ret sequence, the result will be to transfer the execution path of the current thread of the dispatcher to the address of where the Next Exception_ Registration_Record would normally reside. Instead of an actual pointer address to the Next record, it instead is used to hold four bytes of arbitrary code that we supply as part of the buffer overwrite. Therefore, the Next Exception_Registration_Record field can be overwritten to be our first area of executable shellcode.

Lets talk just a little more about the pop/pop/ret to understand what is happening here. A "pop" command says to take the value currently located at the top of the stack (ESP) and assign it to a particular register. For example, "pop edx" would move the current value on the stack at ESP to register edx and then increment ESP up by one word (4 bytes) in memory to effectively remove the top element off the stack. Therefore, one pop will move ESP to +4 and pop/pop will move ESP to +8 where the EstablisherFrame is located and points to address of the exception registration record (which begins with our shellcode we overwrote for the Next field).

Normally when a function is called, the current instruction (EIP) of the calling routine is pushed onto the stack before the function is called so that after the function is complete it can return to where the calling routine left off. So, normally Ret would restore the saved value of EIP back into EIP when the function is complete. In the case of pop/pop/ret function, the system will continue execution from the address of whatever is on the top of the stack when Ret is performed. Since we have popped the top two elements off the stack, the address sitting at the top of the stack when Ret is ran will be the address to Next Exception_Registration_Record which has been overwritten with our stage one shellcode.

An important concept to grasp here is that we are not actually able to overwrite the value in the EstablisherFrame field. We are simply fortunate that this pointer exists on the dispatcher stack in such a way that we can use it to our benefit. As is often the case when writing an exploit, we use what resources we have available as part of the attack. Even though we cannot overwrite the address value stored in the EstablisherFrame, we can use the fact that it is on the dispatcher stack already and does point to an area in the program stack that we can overwrite. So, the pop/pop/ret will tell the system to continue execution at the address of what used to be the Next Exception_Registration_Record in the program stack.

The diagram below attempts to illustrate this:

The Program Stack and Exception Dispatcher Stack are shown above as two separate stacks even though they are in reality a shared stack. However, since the Exception Dispatcher sets up its own stack space, we treat it here as two different stacks to illustrate the concept.

When execution is passed back to the overwritten Next Exception_Registration_Record, we only have four contiguous bytes of memory to work with before hitting the Handler field (which we also overwrote with our address to pop/pop/ret). Since this is not much room to execute useful shellcode, this area becomes our stage one shellcode space. Most attackers will use a simple short jump sequence to jump past the handler and into the attacker controlled code that comes after it. This second area (stage two) can generally hold a lot more data and is usually where attackers will place their primary payload for the exploit. The figure below illustrates what this might look like after an attacker has overwritten an exception registration record.

While there are more details involved in how the exception handler operates, this overview provides us with enough information to be able to design a functional SEH exploit.



Last Updated ( Tuesday, 07 July 2009 )
 
Related Items
I-Hacked's Most Popular
2006 I-Hacked T-Shirts
 I-Hacked T-Shirts
Have been released, Now with
3 versions!

Check them out here

Latest Articles
Top of Page

If you see information here that you know is inaccurate, out of date, misleading, confusing, or just blatantly wrong, please let us know. Updates and corrections are reviewed and updated as they are received.

 
Disclaimer
I-hacked.com does not take any responsibility with the information presented. Any information provided on this site is not guaranteed in any way. Some articles may discuss topics that are illegal, so this information is provided for educational purposes only, use at your own risk. If you blow up your car, home, computer, or anything else -- it's not our fault, use good judgement and play nice.


© I-Hacked.com LLC