API Hooking - Trampoline
Hooking WinAPIs using Trampolines
Theory
API hooking is a technique used to intercept and alter the behavior of different API calls. This can be done to monitor or modify the function of an application (used a lot in Game Hacking), etc. AV Vendors / EDR's also use it to monitor suspicious API calls and look at the parameters being passed to them, thereby detecting them before they get a chance to run. There are many different ways to do this, infact there are public libraries which can be used to do the same (Detours, Minhook) but using them will clearly indicate that we are trying to hook the API calls, hence we write a manual code to do the same.
What we will basically do is update the target's function prologue (initial instructions) before saving the real instructions and tell it to do an unconditional jump to our new function, in which we will verify/print the args, restore the original code for the targeted function, and run the actual function with the args. To keep things simple, I will try hooking the MessageBoxA API.
Read the function prologue for
MessageBoxAModify the perms to RWX, since we have to write + execute
Update it with unconditional jump to our
HookedMessageBoxAPrint Args, Run
MessageBoxWinsteadReset the perms back for
MessageBoxAUnhook
MessageBoxA
We need to keep track of a few things like actual instructions, target function, function to run instead, perms on the actual instructions, so it's better to define a struct to handle all of these.
Trampolines
The shellcode which will be updated could also be called a trampoline. We need to have different trampoline based on the system architecture. We could also do this in a way how Detours implements this, more on this below. On x64, it would look something like this.
mov rax, 0x1122334411223344 ; update rax with function val then jmp
jmp raxand on x86, we could do something like
push 0xa0b1c2d3 ; push the function address to stack and ret
retBut when we read the first instructions from the target function, they are going to be in hex (opcodes). Hence, we need to update our trampolines to opcodes as well. I'll use godbolt to achieve the same.

for x86, I had some trouble working with godbolt, so i switched to defuse for the same.

Implementation
Alright, We have our trampolines ready. I'll start with defining functions to install and remove the hook.
Hook Struct
I'll create a structure for my ease
Now I'll have to Initialize the hook, I will have to copy the original opcodes first, then update the perms for that memory, and finally write my trampoline.
InitializeHook
InstallHook
After we have initialized our hook, now we need to have 2 more functions for installing and removing the hook. I'll make sure of the architecture and update the trampoline accordingly. Here, there's also another way to do the trampoline like how it's implemented in Detours. I'll show that later on.
RemoveHook
We will first reset the function prologue and then reset the updated perms on the function, and then we set the other variables to NULL.
main
Now all that's left is to implement it and hook the MessageBoxA.
Again there many ways to implement this. If i want to remove the hook when I call my custom messagebox, I would want to use a global Hook object, else I would have to rely on calling the MessageBoxW instead. This might be handy just for showcasing hooking, but not the best way imo. I'll update and introduce a different way to hook the apis, but that's for some other day.

Looking at x64dbg, we can confirm the function prologue being updated to our trampoline.

Visiting the function, we can see that the particular address is pointing to our detour function


Detours way
Looking at the src for Detours, we can see how they have implemented the trampoline.
The Trampoline uses the instruction jmp qword ptr [rip+0] (FF 25 00 00 00 00), which tells the CPU to read a 64-bit pointer from memory located at the current instruction pointer (RIP) plus a displacement. When the instruction is executed, the CPU first advances RIP to the next instruction (6 bytes ahead), then calculates the effective address RIP + 0, reads the 8-byte value stored there, and jumps to that address. By placing the target function’s address immediately after the instruction, the trampoline creates an absolute jump without using any registers.
I'll use godbolt and get the opcodes, I'll only have to update the memcpy function to adjust the address accordingly, rest everything is the same.
Conclusion
This was me using trampoline to hook winapis. As usual I have uploaded the full source on github, and you can reach out to me on twitter (@ZzN1NJ4) if you find any mistakes (I have this weird feeling that I made some mistake which I'll find after reading this thrice). Thanks again. There are soo many things to do, but maybe I'll talk about IAT Hooking next.
References
Last updated