Vectored Exception Handling, Hooking Via Forced Exception
As a security researcher, it comes to my attention that the ability to modify and manipulate code execution is extremely crucial. Maybe you want to decrypt a browser’s HTTPS connection, or maybe you want to write a rootkit that will hide all your evil doing — all of which would benefit greatly from the technique we all know as Hooking.
What is hooking?
“The term hooking covers a range of techniques used to alter or augment the behavior of an operating system, of applications, or of other software components by intercepting function calls or messages or events passed between software components.” — Wikipedia
This give us the ungodly ability to read/modify a function’s argument(s)/return’s value, detour execution flow, and “replace” a function’s logic. I’ll leave it up to your imagination on how one would use such power.
How do I achieve this power?
If this sounds amazing to you, then you are in luck. There are multiple ways to achieve this ungodly power. I will just list a few on top of my head.
- Virtual Method Table (VMT) Hooking
- Import/Export Address Table (IAT/EAT) Hooking
- PageGuard/VEH Hooking
Why so many?
As the need for detection increases, so did the amount of methods required to evade those detection. For each and every single method, there are pros and cons. Let’s go over a few pros and cons.
Pro: Simple to implement, very fast, and work universally.
Con: Required byte patching in .text section. Image in memory will not match the image on disk. High detection rate.
Virtual Method Table
Pro: Fast, simple to implement, does not require patching .text section, and no native API to detect this method.
Con: Only work on virtual table’s functions, still require modification of memory (most likely inside .data).
Import/Export Address Table
Very similar to VMT hooking — however it only work on Import/Export table’s functions.
PageGuard/Vectored Exception Handling
Pro: Require no memory modification and stealthy.
Con: Complicated to implement, and VERY VERY slow.
Now, that is out of the way, let’s go into the main topic…
What is an exception handle?
On windows (and linux), an exception handling is a piece of code that provides a single mechanism to handle an exception (duh). In linux, the amount of exception handling are very straightforward and limited. However in Windows, there are countless exception handling attempting to save your process from crashing, with an added benefit of allowing the user to register their own vectored exception handler (as supposed to SEH aka __try, __finally, __except).
How can we use this to our benefit?
Like I mentioned previously, in Windows — There is an ability for the user to register a custom VEH, using the WINAPI AddVectoredExceptionHandler. Looking at
PVECTORED_EXCEPTION_HANDLER , we can see that we will have access to an argument of type
_EXCEPTION_POINTERS. You can view the struct here. What we are interested in is the ContextRecord, which give us access to the debug registers, floating point registers, segments registers, general purpose registers as well as control registers. This allows us to directly modify control registers such as EIP/RIP to achieve execution flow modification.
Sounds good! But how do we cause the exception?
Easy, do something stupid! I’m just half kidding. We can reliably cause an exception that will can be reliably caught by our VEH through using one of two methods.
The first method is to tag a page with the flag “PAGE_GUARD”, read more here, and that will triggers an exception known as STATUS_GUARD_PAGE_VIOLATION when accessed. However, if you do decide to read the documentations I linked, you will noticed an excerpt from MSDN mentioning:
“ If a program attempts to access an address within a guard page, the system raises a STATUS_GUARD_PAGE_VIOLATION (0x80000001) exception. The system also clears the PAGE_GUARD modifier, removing the memory page’s guard page status.”
This effectively mean, every time PAGE_GUARD_VIOLATION is caught, we need to reapply the PAGE_GUARD modifier to retain the hook.
The other method is to tag a memory page with the flag NO_ACCESS and that will triggers an exception known as STATUS_ACCESS_VIOLATION when accessed. Both are reliable methods to get where we need to go. However, regardless of which one you choose, there is a third necessarily “exception”.
Introducing STATUS_SINGLE_STEP exception.
From the name, it is unclear what kind of exception it is and if you are wondering why it does not have the word “VIOLATION” in it, you are on the right track. STATUS_SINGLE_STEP is actually not a violation, but instead a mechanism to detect a trace trap or other single instruction mechanism signals that one instruction is executed. This can be achieve by settings the ContextRecord’s EFlags with |= 0x100.
Still, why do we need it?
A page of memory is the smallest amount of memory you can physically allocated, which is usually 4096 bytes. When we use VirtualProtect to set protection flags on a page, we cannot selectively choose what part of the page to apply it to, but instead to the entire page altogether. This will be fine if our function is exactly align at the beginning of the page and also be the only piece of data inside this page. However, most of the time — a function shares the page they are on with multiple other functions/data, and does not generally begin at the base address of the page. Therefore, when we want to trigger the exception on the function we want to hook— the exception will triggers indiscriminately regardless of where we are at in the page. That is where STATUS_SINGLE_STEP comes into play. Setting the Eflags with the bitwise OR operator and 0x100, we can step 1 instruction at a time through the page until we get to the exact address we want to hook, then we will perform our EIP/RIP modification and achieve the hook we need.
To visualize, imagine the address in green is the one we want to hook, as that is the beginning of our target function. STATUS_SINGLE_STEP will allows us to step through the instructions until we get there, where we will do our EIP/RIP change. If the function we are on isn’t the one we want to hook and happen to be in the same page, STATUS_SINGLE_STEP will keep going until the function’s return is called, which then we will no longer be in the page — and we will never reach the green address, effectively allow us to avoid hooking the wrong function.
That is all you need to know to perform PAGE_GUARD/Vectored Exception Handling Hook!
The steps you will need to take to hook a function can be summarize like this:
- Find the address of the function you want to hook
- Register a vectored exception handle, changing the EIP/RIP to your own function
- Use VirtualProtect to add a PAGE_GUARD modifier to your target function’s address page.
- Wait for the target function to be called, triggering the PAGE_GUARD_VIOLATION exception.
- Your VEH will catch the exception, and redirect the flow to your function.
VEH Hooking in Action!
Please refer to main.cpp for the code I will be using.
As you can see, the first <Sleep(100000)> took no time at all due to the hook function returning immediately and after unhooking, the second <Sleep(1000)> took exactly 1000ms or 1s to run, behaving like normal again.
Thank you very much for reading, and again, if I made any mistake in this post — please let me know I will make the appropriate edit.