Search This Blog

Showing posts with label vectored exception handling. Show all posts
Showing posts with label vectored exception handling. Show all posts

Wednesday, February 29, 2012

Vectored Exception Handling for Linux

Source code for this article may be found here.


The title of this article may look weird. In deed, why would someone want to use Vectored Exception Handling in Linux, while this OS provides a perfectly working mechanism - signals? Well, there are several possible answers:

  • Many programmers, who started their career with Windows programming, are getting a bit frustrated when it comes to exception (signal) handling in Linux and keep asking about Linux analogs of Structured or Vectored Exception Handling.
  • It may be interesting to try to extend the existing model.
  • Boredom - as simple as that.
Single Handler vs Chained Handlers
It is a quite common assumption, that Linux signal handling model does not allow multiple handlers for the same signal. Another assumption is that in Linux, signal handlers are not provided with context information. These very assumptions are the main reason those switching from Windows development to Linux are looking for Windows-like solutions.

This assumption is obviously not true and is based on the fact that majority (still) of internet resources only refer to sighandler_t signal(int signum, sighandler_t handler) function. Despite the fact that this function's return value may be used for chaining signal handlers. Needless to mention that sigaction is still (although, this sounds weird) "gaining popularity".

The problem is, however, that implementation of such chaining mechanism must be done by a developer and is not provided by libc .

Winux (Windows to Linux) Method
Let me skip the description of Linux signal handling model as it is covered here (as well as on many online resources) and get straight to the customized implementation of the Vectored Exception handling mechanism.

Despite the fact, that VEH has been with us since Windows XP, it is still not known enough among developers (who tend to think that SEH is the only way), although, it provides more power (and leaves stack for better purposes). VectoredHandlers are "known" across all the threads running in the process and, therefore, saves us some time, as we do not need to register yet another handler when entering a function (however, both things are good in Windows).

The internal implementation of VEH is very simple. The OS maintains a linked list of handlers registered with AddVectoredExceptionHandler API function, which allows to add new handler to either the top of the list or it's tail and returns a handle to the handler. In order to remove certain VectoredHandler, RemoveVectoredExceptionHandler API function should be called.

This way, the intention is to implement these two functions for Linux targeted C code.

Basis - Definitions and Prototypes
Nothing we can do about it - we have to start with some definitions and prototypes:



EXCEPTION_CONTINUE_EXECUTION and EXCEPTION_CONTINUE_SEARCH are defined in Winbase.h and represent the two values that may be returned by VectoredHandler. They, actually, speak for themselves.

EXCEPTION_POINTERS is a structure used to pass pointers to siginfo_t and ucontext_t to the registered pseudo handlers, much like Windows passes  pointers to ExceptionRecord and ContextRecord.

vectored_handler_t - this type represents pointers to our pseudo handlers.

As we need some infrastructure to store information about the registered pseudo handlers, we define the VECTORED_HANDLER_ENTRY structure - a member of a linked list (vector) of VectoredHandlers.


This linked list is represented by head and tail pointers to VECTORED_HANDLER_ENTRY structures.

The AddVectoredExceptionHandler and RemoveVectoredExceptionHandler prototypes are almost identical to those of Windows with minor differences, the most important of which, is the int parameter in AddVectoredExceptionHandler. This parameter is the number of the signal, which the pseudo handler, specified by vectored_handler_t, is intended to handle.

WalkTheVector - this is the actual handler, which will be known to the system. When a new signal is being registered, this function is specified as its handler before a call to sigaction is executed.

SIGNAL_RECORD 
In order to make things simpler, we are not going to handle all possible signals by default, instead, when a new handler is being added to the list, for a signal which has no handler, SIGNAL_RECORD structure is created and added to the list of signal records. It's members contain all the information needed by our real handler - WalkTheVector. This is the way to register signals with the Linux VEH library. When the last handler for a given signal is being removed, the corresponding SIGNAL_RECORD structure is removed from the list of registered signals as well.

Members of the structure:
signum - number of corresponding signal.
old - this structure is only filled if the specified signal already had another (not related to our library) associated handler.
current - this structure, in turn, describes the new handler being installed.

As it has been mentioned above, this library installs the same handler for every signal being registered - WalkTheVector.

It has also been mentioned that registration/unregistration of signals is performed automatically by either AddVectoredExceptionHandler or RemoveVectoredExceptionHandler functions.

Usage
It is as simple to use this library, as it is to use those API functions in Windows (just don't forget to link to it ;-) ).

Here is the working example:


Note for nerds: yes, of course, you have to include <stdio.h> and "veh.h", and include <stdlib.h>, <signal.h>, <ucontext.h> and <sys/ucontext.h> in the "veh.h" and no, this code does not perform any checks, as it is not production code, but a presentation.

And the output of this example looks like this:



Exception Handling Implementation
While in normal situation, in Linux, you typically assign one handler to one signal, in this case, you assign the same handler to any signal that you want to handle:


Once a signal is received (given that it has been registered), it is passed to the WalkTheVector function, which, in turn, iterates through all the added VectoredHandlers until either reaching end of list or encountering a handler that returns EXCEPTION_CONTINUE_EXECUTION, in which case, WalkTheVector peacefully returns or prints an error message and kills the process if no relevant handler was found.

ExceptionRecord and ContextRecord Analogs
Each handler in the list receives this information in EXCEPTION_POINTERS structure, much like in Windows. However, if you are new to Linux, or have never dealt with signals, my suggestion is to take a look at the following two include files: bits/siginfo.h and bits/sigcontext.h (or read this post) as siginfo_t and ucontext_t structures have nothing to do woth EXCEPTION_RECORD and CNOTEXT_RECORD structures in Windows.

That's it for now. I hope this post was helpful or at least interesting.

See you at the next!

Tuesday, October 4, 2011

Windows Structured and Vectored Exception Handling Mechanisms

We are all familiar with try - except constructs from C++ (or Java, etc.) code and we all know what this construct is used for. However, I will try to take us deeper into the exception handling mechanism in this post.


Structured Exception Handling aka SEH
The MSDN definition of SEH is "Structured exception handling is a mechanism for handling both hardware and software exceptions. Therefore, your code will handle hardware and software exceptions identically. Structured exception handling enables you to have complete control over the handling of exceptions, provides support for debuggers, and is usable across all programming languages and machines." We will not cover hardware exceptions here, instead we are going to see how the software side is implemented.


SEH is based on frames. Each frame represents an instance of EXCEPTION_REGISTRATION structure and has the following format:


typedef struct _EXCEPTION_REGISTRATION
{
       struct _EXCEPTION_REGISTRATION*  prev;
       DWORD                            handler;
} EXCEPTION_REGISTRATION, *PEXCEPTION_REGISTRATION;


where prev is a pointer to previously defined Exception Registration and handler is a pointer to exception handler - a function that is invoked when exception occurs. Due to the nature of SEH, when you register an exception handler within a function, you have to unregister it before you leave that function. However, you do not have to bother yourself with this if you are writing in high level language such as C++. In this case all these operations are inserted by the compiler and are totally transparent to you - the developer. 
If you ever took a look at a function that uses exception handling in disassembler, you probably saw something like this:


    push pointer_to_exception_handler
    push dword [FS:0]
    mov  [FS:0], ESP


This is exactly how EXCEPTION_REGISTRATION frames are created. The first thing is to store the address of the function we want to be called when an exception occurs (pointer_to_exception_handler). This address is stored on stack. The next step - we store the address of current record. [FS:0] points to the beginning of the TIB (Thread Information Block) structure, where the first cell contains the address of the latest exception registration record added. Finally, we have to store the address of the exception registration record we have recently added. As it has been already mentioned, the address of the topmost EXCEPTION_REGISTRATION structure is stored at [FS:0], thus, as our ESP register points exactly at it, we simply move it to [FS:0].


We are done. Now our function is the first that would gain control should in case of exception.


The following set of operations removes the topmost EXCEPTION_REGISTRATION record from the chain:


    mov ESP,[FS:0]     ;this should not be needed
    pop dword [FS:0]
    add ESP, 4


Exception Handler
Exception Handler is an application defined function/code (unless the handler resides in one of the loaded DLLs, in which case it is not defined by the application) which is intended to fix the situation that lead to exception, if possible. In most cases, such function would simply abort the operation that raised the exception. The definition of such function should be as follows:


LONG CALLBACK  ExceptionHandler( 
               __in PEXCEPTION_POINTERS ExceptionInformation);


where PEXCEPTION_POINTERS is a pointer to EXCEPTION_POINTERS structure which, in turn, contains all the information about the exception and the state of the process at the time of exception. The fields are pointers to EXCEPTION_RECORD and CONTEXT structures respectively. The following is the declaration of the EXCEPTION_POINTERS structure:


typedef struct _EXCEPTION_POINTERS
{
       PEXCEPTION_RECORD  ExceptionRecord;
       PCONTEXT           ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;


ExceptionRecord describes the exception that was raised and caused the invocation of our handler. It contains the following data:


typedef struct _EXCEPTION_RECORD
{
   DWORD                     ExceptionCode;
   DWORD                     ExceptionFlags;
   struct _EXCEPTION_RECORD* ExceptionRecord;
   PVOID                     ExceptionAddress;
   DWORD                     NumberParameters;
   ULONG_PTR                 ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
} EXCEPTION_RECORD, *PEXCEPTION_RECORD;


You may find the full description of this structure here.


ContextRecord is much more interesting as it provides us with fill description of the state of the process right at the moment the exception was raised. It is relatively hard to find its detailed description on the internet, although, MSDN provides us with some information. In either case, here is the declaration of this structure as I use it in my assembly code (FASM syntax):


struc CONTEXT
{
  ;Field                             Offset
  .ContextFlags     dd ?             ;0x00
  ;Debug registers
  .Dr0              dd ?             ;0x04
  .Dr1              dd ?             ;0x08
  .Dr2              dd ?             ;0x0C

  .Dr3              dd ?             ;0x10

  .Dr6              dd ?             ;0x14

  .Dr7              dd ?             ;0x18
  ;FPU data
  .FloatSave        FLOATING_SAVE_AREA  ;0x1C
  ;Segment registers
  .SegGs            dd ?             ;0x8C
  .SegFs            dd ?             ;0x90
  .SegEs            dd ?             ;0x94
  .SegDs            dd ?             ;0x98
  ;General purpose registers
  .Edi              dd ?             ;0x9C
  .Esi              dd ?             ;0xA0
  .Ebx              dd ?             ;0xA4
  .Edx              dd ?             ;0xA8
  .Ecx              dd ?             ;0xAC
  .Eax              dd ?             ;0xB0
  .Ebp              dd ?             ;0xB4
  .Eip              dd ?             ;0xB8
  ;CS register
  .SegCs            dd ?             ;0xBC
  ;EFlags register
  .EFlags           dd ?             ;0xC0
  ;Stack pointer
  .Esp              dd ?             ;0xC4
  ;Stack segment register
  .SegSs            dd ?             ;0xC8
}


It, somehow, appears to be that it is even harder to find the description of the FLOATING_SAVE_AREA structure then the description of CONTEXT structure, but our will is our limit, so here is the declaration of FLOATING_SAVE_AREA too:


struc FLOATING_SAVE_AREA
{
  ;Field                             Offset
  .ControlWord      dd ?             ;0x00
  .StatusWord       dd ?             ;0x04
  .TagWord          dd ?             ;0x08
  .ErrorOffset      dd ?             ;0x0C
  .ErrorSelector    dd ?             ;0x10
  .DataOffset       dd ?             ;0x14
  .DataSelector     dd ?             ;0x18
  .RegisterArea     rb 80            ;0x1C
  .Cr0NpxState      dd ?             ;0x6C
}


But let us get back to the CONTEXT structure. It not only provides us with a clear picture of what is going on in the process, but also represents a powerful tool for us to manipulate the environment. For instance, we may alter the content of the EIP register and this would cause the program to continue from a different place when it gains control again. We can check whether our program is being debugged by checking the values of debug registers (a well known anti-debugging trick)  and so on.


Once we are done with our handler, we should return one of the following values:

  • EXCEPTION_CONTINUE_EXECUTION (0xFFFFFFFF) - this would tell the operating system to pass control back to our program;
  • EXCEPTION_CONTINUE_SEARCH (0x0) - this, in turn, would signal the operating system that the exception has not been handled by this handler and it should try other handlers in the chain.

Vectored Exception Handling
Vectored Exception Handling is defined as an extension to SEH. One major difference is that when we register a vectored handler it is intact throughout the whole process, unlike structured exception handler which may only be used within a single function.

Unlike SEH, we do not have to manipulate stack or deal with memory allocations, or whatsoever. If we want to add a vectored exception handler we should simply call the AddVectoredExceptionHandler function:

   PVOID WINAPI AddVectoredExceptionHandler(
        __in ULONG FirstHandler,
        __in PVECTORED_EXCEPTION_HANDLER VectoredHandler );

or RemoveVectoredExceptionHandler function to remove it:

    ULONG WINAPI RemoveVectoredExceptionHandler( __in PVOID Handler );

The AddVectoredExceptionHandler function returns the handle (or NULL if it failed) to our handler and accepts the following parameters:
FirstHandler - if this parameter is not zero, then our handler is the first handler to be called or the last otherwise.
VectoredHandler - the address of our handler.

When removing our handler we call the RemoveVectoredExceptionHandler function passing the previously obtained handle as a parameter.

The rest is very similar to SEH except one tiny important thing - although, SEH and VEH handlers accept the same parameter (at least according to their declarations) it is not how it really works.

In case of SEH, the handler receives the pointer to EXCEPTION_POINTERS structure, whereas in case of VEH, the handler receives the EXCEPTION_POINTERS structure itself on the stack. Let me show it by a simple example:

SEH stack

0x0006FAA0      0x0006FAA4      ;pointer to EXCEPTION_POINTERS structure
0x0006FAA4      0x0006FAB0      ;pointer to EXCEPTION_RECORD structure
0x0006FAA8      0x0006FC00      ;pointer to CONTEXT structure

VEH stack

0x0006FAA0      0x0006FAB0      ;pointer to EXCEPTION_RECORD structure
0x0006FAA4      0x0006FC00      ;pointer to CONTEXT structure


It appears to be that the underlying logic of exception handling in Windows is quite interesting and even more than that, it provides us with additional powerful tools. Being a reverse engineer for the most of my career, I have found that this mechanism provides developers with one of the most basic yet powerful anti-debugging abilities, which are often underestimated. 

Hope this post was helpful. See you at the next post!