- How long you been coding/hacking?
- 5 years
What is a detour?
The word detour describes the act of changing the assembly instructions to jump to a different location, essentially re-directing the flow of execution. Typically you are doing this to detour the code into a memory region where your own code exists. Thus you're forcing the game to execute your code.
The key to doing this is to make sure you do not corrupt the stack, you execute the bytes that you overwrote and you jump back to the proper position after your code executes.
Basic x86 Internal Detour Code
x86 Trampoline Hook
A detour can be placed anywhere and all it does is jump. In my mind, hooking better describes the art of hooking an entire function and directing it to your own function. What I have just described is what I think is best referred to as a trampoline hook. First off, a trampoline hook is typically internal. You inject your DLL which contains a function with the same declaration as the function you're hooking. It has the same arguments, return type and calling convention. In this function you have your own code you want to execute and at the end of your function, you call the original function.
But if you execute the original function, it just jumps to your own function again, so you get an infinite loop from hell.
Thus, the trampoline hook was born. Instead of jumping back to the original function after your function executes, you jump to a trampoline or gateway. The is gateway then jumps back to the original function, but it jumps at the byte after your jump occurs, thus evading the infinite loop.
To do a trampoline hook, you create a regular detour which detours the target function to your function. In your function you execute your code, and then instead of returning to the original function, you jump to the gateway, execute your stolen bytes and then proceed to jump to the original function, a few bytes later after your detour, thus skipping the original detour.
The secret to using this function is you must set the original function pointer to point at the address of the gateway, which this function returns. Then in your hook, at the end, call the original function pointer, which now points at the gateway.
How to use it
You don't need any inline ASM or any declspec naked functions, define your function prototypes, create function pointers, create your function, then use your trampoline hook function to hook the original function and detour or to your own function. The TrampHook function will handle the creation of the gateway for you.
Here's the basic concept:
Complete Example Project
The simplest example we have a trampoline hook in action that is 100% ready to compile and inject is this one:
https://guidedhacking.com/threads/d3d9-endscene-hook-template-using-dummy-device.14008/
This is what you want to be doing when hooking anything internally, it's just too easy.
For more information, stay tuned for our complete detouring / hooking guide. Shoutout to Solaire, he is the original creator of this code and he is an OG.
The word detour describes the act of changing the assembly instructions to jump to a different location, essentially re-directing the flow of execution. Typically you are doing this to detour the code into a memory region where your own code exists. Thus you're forcing the game to execute your code.
The key to doing this is to make sure you do not corrupt the stack, you execute the bytes that you overwrote and you jump back to the proper position after your code executes.
Basic x86 Internal Detour Code
C++:
bool Detour32(char* src, char* dst, const intptr_t len)
{
if (len < 5) return false;
DWORD curProtection;
VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &curProtection);
intptr_t relativeAddress = (intptr_t)(dst - (intptr_t)src) - 5;
*src = (char)'\xE9';
*(intptr_t*)((intptr_t)src + 1) = relativeAddress;
VirtualProtect(src, len, curProtection, &curProtection);
return true;
}
A detour can be placed anywhere and all it does is jump. In my mind, hooking better describes the art of hooking an entire function and directing it to your own function. What I have just described is what I think is best referred to as a trampoline hook. First off, a trampoline hook is typically internal. You inject your DLL which contains a function with the same declaration as the function you're hooking. It has the same arguments, return type and calling convention. In this function you have your own code you want to execute and at the end of your function, you call the original function.
But if you execute the original function, it just jumps to your own function again, so you get an infinite loop from hell.
Thus, the trampoline hook was born. Instead of jumping back to the original function after your function executes, you jump to a trampoline or gateway. The is gateway then jumps back to the original function, but it jumps at the byte after your jump occurs, thus evading the infinite loop.
To do a trampoline hook, you create a regular detour which detours the target function to your function. In your function you execute your code, and then instead of returning to the original function, you jump to the gateway, execute your stolen bytes and then proceed to jump to the original function, a few bytes later after your detour, thus skipping the original detour.
C++:
char* TrampHook32(char* src, char* dst, const intptr_t len)
{
// Make sure the length is greater than 5
if (len < 5) return 0;
// Create the gateway (len + 5 for the overwritten bytes + the jmp)
void* gateway = VirtualAlloc(0, len + 5, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
//Write the stolen bytes into the gateway
memcpy(gateway, src, len);
// Get the gateway to destination addy
intptr_t gatewayRelativeAddr = ((intptr_t)src - (intptr_t)gateway) - 5;
// Add the jmp opcode to the end of the gateway
*(char*)((intptr_t)gateway + len) = 0xE9;
// Add the address to the jmp
*(intptr_t*)((intptr_t)gateway + len + 1) = gatewayRelativeAddr;
// Perform the detour
Detour32(src, dst, len);
return (char*)gateway;
}
How to use it
You don't need any inline ASM or any declspec naked functions, define your function prototypes, create function pointers, create your function, then use your trampoline hook function to hook the original function and detour or to your own function. The TrampHook function will handle the creation of the gateway for you.
Here's the basic concept:
C++:
typedef HRESULT(APIENTRY* tEndScene)(LPDIRECT3DDEVICE9 pDevice);
tEndScene oEndScene = nullptr;
HRESULT APIENTRY hkEndScene(LPDIRECT3DDEVICE9 pDevice)
{
//do stuff in here
return oEndScene(pDevice);
}
//just an example
int main()
{
oEndScene = (tEndScene)TrampHook((char*)d3d9Device[42], (char*)hkEndScene, 7);
}
The simplest example we have a trampoline hook in action that is 100% ready to compile and inject is this one:
https://guidedhacking.com/threads/d3d9-endscene-hook-template-using-dummy-device.14008/
This is what you want to be doing when hooking anything internally, it's just too easy.
For more information, stay tuned for our complete detouring / hooking guide. Shoutout to Solaire, he is the original creator of this code and he is an OG.
Last edited: