RCE Endeavors 😅

April 4, 2015

Hiding Functionality with Exception Handlers (2/2)

Filed under: General x86,Programming,Reverse Engineering — admin @ 1:49 PM

This post will cover the second part of hiding functionality with exception handlers. Unlike the technique presented in the previous post, which modified the SEH record for the local thread, the aim here is to modify the SEH record for another thread in order to better hide what is actually going on. By the end of the post, there should be enough information to put together a working application capable of modifying the SEH list of any thread (barring some exceptions) and causing it to raise an exception to execute your code. The sample application will be a DLL that is injected into a process and hijacks one of its threads to perform some task.

What is the purpose of doing all of this if you’re injecting into a process anyway? After all, you can simply spawn your own thread or likely use the one created during the injection (if CreateRemoteThread was used) and just begin executing your code. I’d argue that this technique gives more obscurity to what is happening during static analysis and is something out of the norm. Plus its fun!

The overall code is very similar to what the first part showed, but now there need to be a few steps added in order to get the TIB of another thread. There are usually a few different approaches, of varying complexity and reliability.

  • Do it directly. Suspend the thread and gets its context. Change the instruction pointer to point to your code which changes the SEH list and raises an interrupt and resume. Perform your task and restore the original context in your SEH handler.
  • Do it indirectly. Suspend the thread, queue an asynchronous procedure call (APC) which changes the SEH list and raises an interrupt (with QueueUserAPC), and resume the thread. The thread must be in an alertable state (waiting on something) for this to work, which is typically the case for most threads in a process.
  • Take the middle ground. Suspend the thread and get the address of its FS segment directly using GetThreadSelectorEntry. Change the SEH list from within your thread and queue an APC to raise the interrupt, resume the thread.

The easiest approach is to do it indirectly with an APC. The code is really straightforward and looks like the following:

void InstallExceptionHandler(DWORD dwThreadId)
{
    auto handle = ThreadHandleTable[dwThreadId];
 
    DWORD dwError = SuspendThread(handle);
    if (dwError == -1)
    {
        fprintf(stderr, "Could not suspend thread. Error = %X.\n",
            GetLastError());
        return;
    }
 
    CONTEXT ctx = { CONTEXT_ALL };
    GetThreadContext(handle, &ctx);
    LDT_ENTRY ldtEntry = { 0 };
 
    GetThreadSelectorEntry(handle, ctx.SegFs, &ldtEntry);
    const DWORD dwFSAddress =
        (ldtEntry.HighWord.Bits.BaseHi << 24) |
        (ldtEntry.HighWord.Bits.BaseMid << 16) |
        (ldtEntry.BaseLow);
 
    fprintf(stderr, "FS segment address of target thread should be: %X.\n",
        dwFSAddress);
 
    dwError = QueueUserAPC(APCProc, handle, 0);
    if (dwError == 0)
    {
        fprintf(stderr, "Could not queue APC to thread. Error = %X.\n",
            GetLastError());
    }
 
    dwError = ResumeThread(handle);
    if (dwError == -1)
    {
        fprintf(stderr, "Could not resume thread. Error = %X.\n",
            GetLastError());
    }
}

Here the suspend/queue/resume wording is put directly in to code (with extra debug comments). When the thread resumes, APCProc will be invoked. APCProc will be running in the context of the target thread and is responsible for modifying the SEH list to add in a new handler. Because of this, APCProc can obtain the TIB without any extra overhead code to write and the code basically becomes a copy/paste from part one.

void CALLBACK APCProc(ULONG_PTR dwParam)
{
    fprintf(stderr, "APC callback invoked. Raising exception to trigger exception handler.\n");
 
    EXCEPTION_REGISTRATION *pHandlerBase = (EXCEPTION_REGISTRATION *)__readfsdword(0x18);
 
    fprintf(stderr, "Segment address of target thread: %X.\n", pHandlerBase);
 
    EXCEPTION_REGISTRATION NewHandler = { pHandlerBase->pPrevHandler,
        (EXCEPTION_REGISTRATION::pFncHandler)(MyTestHandler) };
 
    pHandlerBase->pPrevHandler = &NewHandler;
 
    RaiseException(STATUS_ACCESS_VIOLATION, 0, 0, nullptr);
}

The handler, NewHandler, being independent of all of this, doesn’t change much either.

EXCEPTION_DISPOSITION __cdecl MyTestHandler(EXCEPTION_RECORD *pExceptionRecord, void *pEstablisherFrame,
    CONTEXT *pContextRecord, void *pDispatcherContext)
{
    if (pExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION)
    {
        MessageBox(0, L"Some hidden functionality can go here.",
            L"Test", 0);
        return ExceptionContinueExecution;
    }
 
    return ExceptionContinueSearch;
}

Below are some screenshots of this at work on a 32-bit Notepad++ instance.

np1
Thread 5504 is chosen here.
np2The MessageBox in the exception handler successfully pops ups. Hitting the “OK” button resumes execution as normal.

The source for the projects (Visual Studio 2013, Update 4) presented in these parts can be found here. Thanks for reading and follow on Twitter for more updates.

April 3, 2015

Hiding Functionality with Exception Handlers (1/2)

Filed under: General x86,Programming,Reverse Engineering — admin @ 9:56 AM

This post will cover the topic of hiding functionality by taking advantage of the OS-supported exception handling provided by Windows. Namely, it will cover Structured Exception Handling (SEH), and how it can be utilized to obscure control flow at runtime and how it can make it more difficult to perform static analysis on a binary. Only the relevant parts of SEH will be covered here; the full details can be found on the MSDN page. Due to the differences in exception handling between Windows on x86 and x64, the general technique presented and accompanying code is relevant on x86 only. The code presented here will also discuss how to manually add exception records, without the use of the SetUnhandledExceptionFilter API. This technique as been seen in PE protectors, anti-intrusion bypass systems, and malware. As always, the material presented is for educational and research purposes; don’t do anything dumb/criminal with it.

Structured exception handling is best demonstrated through the use of the Microsoft extensions to C++ exception handling, namely using __try and __except statements. For example, the following code employs use of SEH:

__try
{
    printf("Hello, World!\n");
    int *pNull = nullptr;
    *pNull = 0x0BADC0DE;
}
__except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
{
    printf("In exception handler.\n");
}

Using SEH, the access violation arising from the null pointer dereference will be caught by the user defined handler; something not possible in standard C++. How this works is that at the beginning of the function, the compiler sets up the exception frame for this code. Viewing the disassembly for the function, it becomes more apparent how this happens.

00B21003 6A FF                push        0FFFFFFFFh  
00B21005 68 18 25 B2 00       push        0B22518h  
00B2100A 68 AC 10 B2 00       push        0B210ACh  
00B2100F 64 A1 00 00 00 00    mov         eax,dword ptr fs:[00000000h]  
00B21015 50                   push        eax  
00B21016 64 89 25 00 00 00 00 mov         dword ptr fs:[0],esp  

This code appears confusing at first, but can be cleared up by reading the crash course explanation page linked above. The code begins by pushing three values onto the stack. The two items in green will be ignored in the explanation and correspond to values in the exception record: the scope table and the try level. There are some obfuscation tricks to manipulating the scope table that can be done, but they won’t be discussed in this post. The full explanation of these fields and their purpose can be found on the crash course page. The next value, 0x0B210AC is an important one. Following this through in a debugger leads to the symbol __except_handler4.

This is the topmost handler of the exception chain and begins dispatching the exception. SEH works in such a way that the topmost exception handler in the chain is called and has a chance to handle the exception. If the exception is not handled, then the next entry in the exception chain is called until the exception is either handled or the final exception handler is called and the program aborts with an unhandled exception.

Afterwards, the value in FS:[0] is moved into the EAX register. FS:[0] contains the base address of a special Windows structure called the Thread Information Block (TIB). Among other things of interest, this structure contains a pointer to the current SEH frame at its base (+0x0). This value is then pushed onto the stack and the stack pointer at ESP is moved into FS:[0]. What is happening here is that an exception record structure is getting constructed on the stack and is being stored at the head of the SEH list. This allows for proper stack unwinding and exception handler call order in the event of an exception. The format of the exception record is documented on the crash course page and can be converted to a structure, with the irrelevant fields omitted, as follows:

typedef struct _EXCEPTION_REGISTRATION
{
    using pFncHandler = void (__cdecl*)(EXCEPTION_RECORD *, _EXCEPTION_REGISTRATION *,
        CONTEXT *, EXCEPTION_RECORD *);
 
    struct _EXCEPTION_REGISTRATION *pPrevHandler;
    pFncHandler pHandler;
 
    //Missing fields here:
    //Scope table
    //Try level
    //EBP
} EXCEPTION_REGISTRATION, *PEXCEPTION_REGISTRATION;

Now knowing the layout of these exception records and where to find them in memory, it is rather straightforward to modify the list. The steps are as follows:

  • Get the address of the TIB through the FS segment
  • Get a pointer to the current SEH frame from the TIB
  • Replace the head of the current SEH frame with a custom handler

Put into code, it looks like the following:

#include <cstdio>
#include <Windows.h>
 
typedef struct _EXCEPTION_REGISTRATION
{
    using pFncHandler = void (__cdecl *)(EXCEPTION_RECORD *, _EXCEPTION_REGISTRATION *,
        CONTEXT *, EXCEPTION_RECORD *);
 
    struct _EXCEPTION_REGISTRATION *pPrevHandler;
    pFncHandler pHandler;
 
} EXCEPTION_REGISTRATION, *PEXCEPTION_REGISTRATION;
 
//Base of TIB structure but we only care about exception chain.
EXCEPTION_REGISTRATION *pHandlerBase = (EXCEPTION_REGISTRATION *)__readfsdword(0x18);
 
EXCEPTION_DISPOSITION __cdecl MyTestHandler(EXCEPTION_RECORD *pExceptionRecord, void *pEstablisherFrame,
    CONTEXT *pContextRecord, void *pDispatcherContext)
{
    printf("Hello, World!\n");
 
    return ExceptionContinueExecution;
}
 
int main(int argc, char *argv[])
{
    fprintf(stderr, "TIB Base (Pointer to current SEH Frame): %p.\n", pHandlerBase);
 
    EXCEPTION_REGISTRATION NewHandler = { pHandlerBase->pPrevHandler,
        (EXCEPTION_REGISTRATION::pFncHandler)(MyTestHandler) };
 
    //Actually the pointer to first exception handler
    pHandlerBase->pPrevHandler = &NewHandler;
 
    RaiseException(0, 0, 0, nullptr);
 
    return 0;
}

Here a new handler, MyTestHandler, is added to the SEH chain. It gets invoked on the RaiseException call and tells the program to continue execution after printing out a string. Looking at the disassembly, there were no exception records generated for the code since it doesn’t use SEH, so the RaiseException call will appear to go to the unhandled exception filter and crash the application. However, the installation of the handler at runtime through the TIB prevents this and actually results in a call to somewhere unexpected. In addition to adding a new handler, it is also possible to replace an existing one.

Replacing entries in the SEH chain works on a per-thread basis. If the SEH list is modified on one thread and another thread raises an exception, the new SEH handler will not be called. Replacing SEH handlers for arbitrary threads and dispatching exceptions to run in their context will be the topic of the next post.

« Newer Posts

Powered by WordPress