Clandestiny
June 8th, 2002, 03:39
Hiya,
I am currently writing an tutorial on SEH as it relates to reversing and was curious about methods of circumventing SEH based protection tricks. I realize that protectors often deliberately invoke a SEH handler in response to tracing or sometimes by injecting an invalid opcode into the instruction stream. Hooking the SetThreadContext / GetThreadContext APIs might suffice in some cases to prevent manipulation of the machine state via the CONTEXT structure, but many protectors are smart enough to build and manipulate the SEH frame directly on the stack, rendering them impervious to these type of hooks. Being that SEH is intrinsically an OS provided service, it would seem that the way to defeat these types of tricks might be to hook into the Kernel's internal exception handler functions. "A Crash Course on the Depths of Structured Exception Handling" by Matt Pietrek provides some intersting information on the OS's SEH internals as it relates to WinNT:
************************************************
KiUserExceptionDispatcher is in NTDLL.DLL and is where execution begins after an exception occurs. To be 100 percent accurate, what I just said isn't exactly true. For instance, in the Intel architecture an exception causes control to vector to a ring 0 (kernel mode) handler. The handler is defined by the interrupt descriptor table entry that corresponds to an exception. I'm going to skip all that kernel mode code and pretend that the CPU goes straight to KiUserExceptionDispatcher upon an exception
The heart of KiUserExceptionDispatcher is its call to RtlDispatchException. This kicks off the search for any registered exception handlers. If a handler handles the exception and continues execution, the call to RtlDispatchException never returns. If RtlDispatchException returns, there are two possible paths: either NtContinue is called, which lets the process continues, or another exception is raised. This time, the exception isn't continuable, and the process must terminate.
Moving on to the RtlDispatchExceptionCode, this is where you'll find the exception frame walking code that I've referred to throughout this article. The function grabs a pointer to the linked list of EXCEPTION_REGISTRATIONs and iterates over every node, looking for a handler. Because of the possibility of stack corruption, the routine is very paranoid. Before calling the handler specified in each EXCEPTION_REGISTRATION, the code ensures that the EXCEPTION_REGISTRATION is DWORD-aligned, within the thread's stack, and higher on the stack than the previous EXCEPTION_REGISTRATION.
RtlDispatchException doesn't directly call the address specified in the EXCEPTION_REGISTRATION structure. Instead, it calls RtlpExecuteHandlerForException to do the dirty work. Depending on what happens inside RtlpExecuteHandlerForException, RtlDispatchException either continues walking the exception frames or raises another exception. This secondary exception indicates that something went wrong inside the exception callback and that execution can't continue.
The code for RtlpExecuteHandlerForException is closely related to another function, RtlpExecutehandlerForUnwind. You may recall that I mentioned this function earlier when I described unwinding. Both of these "functions" simply load the EDX register with different values before sending control to the ExecuteHandler function. Put another way, RtlpExecuteHandlerForException and RtlpExecutehandlerForUnwind are separate front ends to a common function, ExecuteHandler.
ExecuteHandler is where the handler field from the EXCEPTION_REGISTRATION is extracted and called. Strange as it may seem, the call to the exception callback is itself wrapped by a structured exception handler. Using SEH within itself seems a bit funky but it makes sense if you ponder it for a moment. If an exception callback causes another exception, the operating system needs to know about it. Depending on whether the exception occurred during the initial callback or during the unwind callback, ExecuteHandler returns either DISPOSITION_NESTED_ EXCEPTION or DISPOSITION_COLLIDED_UNWIND. Both are basically "Red Alert! Shut everything down now!" kind of codes.
**************************************************
From this it seems as though it might be possible to hook into the KiUserExceptionDispatcher to intercept exceptions for the process you are interested and retrieve the current CONTEXT structure before the app gets a chance to play dirty with the debug registers and such. I have done several searches regarding the possiblity of hooking into the Kernel Exception Handler and came back with mere breadcrumbs and little definitive information about the feasiblity / validity of this type of approach. I am likewise, interested in the internal implementation of the SEH mechanism in Win9X as the above doc by Pietrek seems only to apply to WinNT. So far, I have found next to nothing regarding SEH internals for Win9X. The Win9X NTDLL.dll appears not to export many of the Ki / Rtl Exception functions mentioned above.
Though I know it is possible for an app to replace the "default" handler, it would only be invoked if no other handlers in the chain agree to handle the exception. I guess I'm curious if it is possible be notified immediately after an exception occurs, *before* any of the registered handlers have a chance at it.
Is hooking into the Kernel SEH functions a valid approach to this type of problem? Or is there a better approach to generically protecting against these type of SEH tricks (ie both ring 3 and ring 0)? Indeed, I'm pretty much a newbie to SEH so I will be grateful for any insight.
Thanks,
Clandestiny
I am currently writing an tutorial on SEH as it relates to reversing and was curious about methods of circumventing SEH based protection tricks. I realize that protectors often deliberately invoke a SEH handler in response to tracing or sometimes by injecting an invalid opcode into the instruction stream. Hooking the SetThreadContext / GetThreadContext APIs might suffice in some cases to prevent manipulation of the machine state via the CONTEXT structure, but many protectors are smart enough to build and manipulate the SEH frame directly on the stack, rendering them impervious to these type of hooks. Being that SEH is intrinsically an OS provided service, it would seem that the way to defeat these types of tricks might be to hook into the Kernel's internal exception handler functions. "A Crash Course on the Depths of Structured Exception Handling" by Matt Pietrek provides some intersting information on the OS's SEH internals as it relates to WinNT:
************************************************
KiUserExceptionDispatcher is in NTDLL.DLL and is where execution begins after an exception occurs. To be 100 percent accurate, what I just said isn't exactly true. For instance, in the Intel architecture an exception causes control to vector to a ring 0 (kernel mode) handler. The handler is defined by the interrupt descriptor table entry that corresponds to an exception. I'm going to skip all that kernel mode code and pretend that the CPU goes straight to KiUserExceptionDispatcher upon an exception
The heart of KiUserExceptionDispatcher is its call to RtlDispatchException. This kicks off the search for any registered exception handlers. If a handler handles the exception and continues execution, the call to RtlDispatchException never returns. If RtlDispatchException returns, there are two possible paths: either NtContinue is called, which lets the process continues, or another exception is raised. This time, the exception isn't continuable, and the process must terminate.
Moving on to the RtlDispatchExceptionCode, this is where you'll find the exception frame walking code that I've referred to throughout this article. The function grabs a pointer to the linked list of EXCEPTION_REGISTRATIONs and iterates over every node, looking for a handler. Because of the possibility of stack corruption, the routine is very paranoid. Before calling the handler specified in each EXCEPTION_REGISTRATION, the code ensures that the EXCEPTION_REGISTRATION is DWORD-aligned, within the thread's stack, and higher on the stack than the previous EXCEPTION_REGISTRATION.
RtlDispatchException doesn't directly call the address specified in the EXCEPTION_REGISTRATION structure. Instead, it calls RtlpExecuteHandlerForException to do the dirty work. Depending on what happens inside RtlpExecuteHandlerForException, RtlDispatchException either continues walking the exception frames or raises another exception. This secondary exception indicates that something went wrong inside the exception callback and that execution can't continue.
The code for RtlpExecuteHandlerForException is closely related to another function, RtlpExecutehandlerForUnwind. You may recall that I mentioned this function earlier when I described unwinding. Both of these "functions" simply load the EDX register with different values before sending control to the ExecuteHandler function. Put another way, RtlpExecuteHandlerForException and RtlpExecutehandlerForUnwind are separate front ends to a common function, ExecuteHandler.
ExecuteHandler is where the handler field from the EXCEPTION_REGISTRATION is extracted and called. Strange as it may seem, the call to the exception callback is itself wrapped by a structured exception handler. Using SEH within itself seems a bit funky but it makes sense if you ponder it for a moment. If an exception callback causes another exception, the operating system needs to know about it. Depending on whether the exception occurred during the initial callback or during the unwind callback, ExecuteHandler returns either DISPOSITION_NESTED_ EXCEPTION or DISPOSITION_COLLIDED_UNWIND. Both are basically "Red Alert! Shut everything down now!" kind of codes.
**************************************************
From this it seems as though it might be possible to hook into the KiUserExceptionDispatcher to intercept exceptions for the process you are interested and retrieve the current CONTEXT structure before the app gets a chance to play dirty with the debug registers and such. I have done several searches regarding the possiblity of hooking into the Kernel Exception Handler and came back with mere breadcrumbs and little definitive information about the feasiblity / validity of this type of approach. I am likewise, interested in the internal implementation of the SEH mechanism in Win9X as the above doc by Pietrek seems only to apply to WinNT. So far, I have found next to nothing regarding SEH internals for Win9X. The Win9X NTDLL.dll appears not to export many of the Ki / Rtl Exception functions mentioned above.
Though I know it is possible for an app to replace the "default" handler, it would only be invoked if no other handlers in the chain agree to handle the exception. I guess I'm curious if it is possible be notified immediately after an exception occurs, *before* any of the registered handlers have a chance at it.
Is hooking into the Kernel SEH functions a valid approach to this type of problem? Or is there a better approach to generically protecting against these type of SEH tricks (ie both ring 3 and ring 0)? Indeed, I'm pretty much a newbie to SEH so I will be grateful for any insight.
Thanks,
Clandestiny