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.

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.

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!

Monday, February 27, 2012

Basics of Executable Code Obfuscation

Source code for this article may be found here.

The problem of software security has already been raised in my previous articles more that once. This article is not an exception. 

Majority of software vendors position themselves as number one in the industry, even though there are always more then 1 number 1. But what unites them all (well, almost all) in reality, it the fact that they all suffer from piracy, they all are aware of that and the last one - they all do almost nothing to change the situation. It surely impossible to totally defeat software piracy but it is definitely realistic, to make the "pirating" process a pain in the neck for pirates.

In this article, I would like to cover the basics of executable code obfuscation - a relatively simple technique, which is, unfortunately, rarely utilized by software vendors as they mostly rely on out of the box solutions. Those of you who have read my previous articles know what my attitude towards those solutions is (roughly saying - more public - more vulnerable), but let me make a  bit different statement here - no matter how good and complex the out of the box solution is, most of software vendors mistakenly assume, that the presence of a well known (for its complexity) software protection package alone is enough, without even trying to utilize it properly. There are cases, however, when proper utilization of third party protection tools is not possible (then why use them at all?) due to negative impact of program's execution (by either consuming too much time or causing faults of different kind).

The lack of ability to protect software product brings forth much more problems then a trivial software piracy. How about proprietary algorithms? The question I always want to ask software vendors is - do you really think that listing patents and copyright notice in the "About" section is enough to push an attacker back?

There are numerous methods of executable code protection, starting with static/dynamic encryption and up to complex virtual machines. However, this article is intended to briefly cover the most basic and at the same time so rare (in the world of legitimate software) method as executable code obfuscation. Although, it is hard to believe that this would really stop someone with modern reverse engineering tools from compromising your software product, but it would definitely make the process of static analysis and algorithm restoration a lot harder. In addition, it would draw attacker's attention away from other protections utilized (at least for some time, depending on attacker's skills).

Executable Code Obfuscation
This technique is intended to prevent static analysis of the executable code and reduce the possibility of algorithm restoration. Obfuscated code would initially appear as nonsense at first glance:

But at first glance only. Take a closer look (this is the beginning if a main function) and you would see that sub_401421 is not a separate function, but belongs to the previous code - it calculates the address of the next instruction to be executed, pushes it onto the stack as if it was a return address and executes ret performing jump.

This is all nice, but let's get to a simple example - the best way to understand how it works and, which is more important, how it may be implemented.

Trivial Example
As it comes from the title of this paragraph, the example code I want to show here is not intended to perform any meaningful task. It simply prints out "Hello!!!" several times, tests an obfuscated call to a library function "printf" and exits. The code is 32 bits, runs on both Linux and Windows and may be compiled with either GCC or MinGW C compilers. You would have to adjust it a bit for usage with MSVC, however. It contains three functions:
  1. constructor - responsible for encryption of addresses of functions that are going to be called by other parts of the code (which are "function #2" and "printf";
  2. my_func - this is the "function #2'; it actually prints out the "Hello!!!" string and accepts an amount of times to print the string and a pointer to the string to be printed;
  3. main - well, this is the main function.

There are a couple of steps to be taken prior to writing the code itself - setup the addresses of the functions that are going to be used.

Declare three global variables of type unsigned int:

unsigned int  addr;    // Address of "my_func" function
unsigned int  printer; // Address of "printf" function
unsigned int  _mask;   // XOR mask for encryption of addresses

Next step is to implement constructor function (see this post about constructor functions in MSVC):

Getting it Done
Write the "my_func" function:

call2 is a macro that performs an obfuscated call and accepts the following parameters:
  • address - the address of the function to call;
  • param1 - first parameter of the callee;
  • param2 - second parameter of the callee.
Here is the definition of the call2 macro:

Those of you using Microsoft's C compiler (e.g. Microsoft Visual C++) should rewrite the Assembly code according to Intel syntax. Use this cheat sheet if you are not familiar with AT&T Assembly syntax.

The main function in this example is quite simple but it seems to illustrate the concept:

The code above is self explanatory enough. 
Put all code together, build and run. This is what the output looks like:

Quite simple, isn't it? Take a look at the compiled result in IDA Pro, for example, and see that it has become harder to read and, even more important, to understand the code.

For nerds: yes, you have to include stdio.h header file.

Taking it Further
Just as I mentioned above, this is a trivial example, neither a tutorial nor instructions to follow. It is obvious, that obfuscation macros in production code should be at least a bit more complicated, then what is shown here.

You may also add some macros with "junk" code in order to obfuscate other parts (not related to function calls) of your code. Like this, for example:

Despite the simplicity, even such trivial macros can convert readable code into something like this (main starts at loc_4013FB):

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