Guide How to Hook Functions - Code Detouring Guide

Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat

Rake

Cesspool Admin
Administrator
Jan 21, 2014
11,539
78,998
2,312
Game Name
N/A
Anticheat
N/A
Coding Language
C++
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.

Before we go too far
We will attempt to be as thorough as possible in our guide, but there is someone who has already written an amazing tutorial which no one can compete with, let me introduce you to jbremer
x86 API Hooking Demystified | Development & Security

Mid Function Hooking
A detour is sometimes referred to as a mid function hook, the only caveat being that if you detour the first byte of a function, then this is not a mid function hook. Placing your detour at the first byte of a function is easily detectable by anti-cheats, which is why a mid function hook is less detectable. Anti-cheats can easily check the first byte, but it's not always likely that they check every byte in the function. If the anticheat you're working with reads the first byte of functions, then you should write your detour lower down in the assembly, this would be a mid function hook.

External Detouring / Hooking
Typically you will do this by using WriteProcessMemory to write your code into the target process, then you use WPM in the same way to change the existing code to jump into yours. External hooking / detouring is more complicated because you must write shellcode into the target process. Internally you can do it quite easy. But externally you have to turn your assembly into bytes and write it to the process as shellcode. When you're internal it's much easier and you don't need to play with assembly as much.

Stolen Bytes
The bytes you overwrite when writing your detour to memory are referred to as stolen bytes, it is important that you know how many bytes you overwrote and it's you must execute these after you perform your detour or else the stack/registers will be corrupted. The number of bytes will not always be the same, let's say you're overwriting an instruction which is 8 bytes, but your detour you're writing is only 5 bytes. In this case, you want to copy all 8 bytes for the stolen bytes. You can't execute 75% of an instruction.

You must copy the stolen bytes and execute them after your own code executes to ensure you don't crash the program.

If your stolen bytes contain a jmp to a relative address or some other relative addressing it will fail because they are not executing at a different location. Relative addresses are relative to the EIP, because we pasted the bytes into a different memory address the EIP is no longer the same.

Code Caves
A code cave is a portion of the target processes memory which is not used by the process. Typically we are referring to memory which is allocated but contains nothing that the process requires to execute. When using a detour, you can write your code into this memory without having to allocate memory. By not having to allocate memory you are being less "noisy". If you're using a codecave, the memory page must have execute permissions. You can modify these memory protection constants with VirtualProtect or VirtualProtectEx.

In the early days, a code cave was memory which was not used by the process, that was already allocated. Nowadays people will allocate their own memory and call this a codecave for whatever reason, I don't know. In most cases, it really doesn't matter, just allocate your own memory because it's easier. If you've created a process handle with permissions to write, then you probably don't have an anticheat problem so you don't need to be worried about being "noisy".

What is a hook?

Hooking is often used interchangeably with the word detouring. In my mind, hooking is specifically the art of hooking into the code and redirecting the flow of execution to your own code. In my mind, detouring doesn't necessarily have to detour to your own code, you can simply be detouring to a different part of the process memory. For instance if you're just jumping over some code you don't want to execute I would describe this as a detour.

Basic x86 Internal Detour Code
C++:
bool Detour32(void * src, void * dst, int len)
{
    if (len < 5) return false;

    DWORD curProtection;
    VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &curProtection);

    memset(src, 0x90, len);

    uintptr_t relativeAddress = ((uintptr_t)dst - (uintptr_t)src) - 5;

    *(BYTE*)src = 0xE9;
    *(uintptr_t*)((uintptr_t)src + 1) = relativeAddress;

    DWORD temp;
    VirtualProtect(src, len, curProtection, &temp);

    return true;
}
src argument = the memory address where you want to place your jmp
dst argument = the memory address you want to jump to (probably where you've written your code)
len argument = the number of bytes used by the instruction you're overwriting

The length argument is typically 5 but depending what you overwrite it may be more.

We check the length to be at least 5 bytes because this is the smallest relative jmp in x86. The instructions you will be destroying by overwriting will be at least 5 bytes.

We use VirtualProtect to take permissions of the memory we are overwriting.

We set the memory we're ovewriting with 0x90 which is the NOP (no operationg) instruction, this is not 100% necessary but is a nice failsafe measure. While you're debugging it's also nice to watch the 0x90 get written so you know you're doing the right thing in the right spot. We NOP the entire instruction by giving it the len argument.

Then we calculate the relative address between the destination and src address by subtracting them, we subtract len. The result of this calculation is the relative offset from the last byte we overwrote to the address of our function we are jumping to. Keep in mind, we are using a relative jump, not an absolute jump so this must be calculated at runtime.

Then we write 0xE9 which is the relative jmp instruction, then we add 1 byte so we can write the relative offset.

Then we use VirtualProtect to reset the page permissions to what they were before we modified them.

So now we've jumped to our code which we wrote to memory.

But what about our code?
You have to execute your code inside a declspec naked function, you must preserve the registers and the stack so you don't corrupt the stack of registers and you must execute the stolen bytes. Then you have to jump back to the src+len address.

At this point I will refer you to our video tutorial (thread here)


x86 Trampoline Hook

Our complete Trampoline Hook Tutorial is available here, you will find a brief explanation of it below as well.


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 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.

This is best explained by an image from jbremer
1577641733056.png


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;
}
When using a trampoline function you just create your own function with the same function prototype and detour into his function, then you do whatever you want. Learn about how that works in these 2 threads:
Source Code - D3D9 EndScene Hook Template Using Dummy Device
Source Code - Simple x86 C++ Trampoline Hook

vTable Hook / Virtual Method Table Hooking
A vTable or virtual function table is an array of pointers to virtual methods. Any class that uses virtual functions will have a virtual method table. Every object of these classes will contain a pointer to the vTable at offset 0x0. The array of virtual functions is just an array of pointers. The object calls these functions by finding their pointer in the vTable. To do a vTable hook all you have to do is overwrite the pointer with a pointer to your own function. At the end of your function, just call the original function.

This is what a vTable looks like, just an array of function pointers
1577640534410.png


No tutorial is necessary for a VMT hook, all you do is overwrite a 4 or 8 byte pointer. If you can't figure that out, you're an idiot and you should be doing the Start Here Guide.

Tutorial - VTables and Hooking Them

Tutorial - vTable Hooking / VMT hooking

@timber's vTable Hook Function
Hook VTable function:
void* HookVTableFunction(void* pVTable, void *fnHookFunc, int nOffset) {
    intptr_t ptrVtable = *((intptr_t*)pVTable); // Pointer to our chosen vtable
    intptr_t ptrFunction = ptrVtable + sizeof(intptr_t) * nOffset; // The offset to the function (remember it's a zero indexed array with a size of four bytes)
    intptr_t ptrOriginal =  *((intptr_t*)ptrFunction); // Save original address

    // Edit the memory protection so we can modify it
    MEMORY_BASIC_INFORMATION mbi;
    VirtualQuery((LPCVOID)ptrFunction, &mbi, sizeof(mbi));
    VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect);

     // Overwrite the old function with our new one
     *((intptr_t*)ptrFunction) = (intptr_t)fnHookFunc;

    // Restore the protection
    VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &mbi.Protect);

    // Return the original function address incase we want to call it
    return (void*)ptrOriginal;
}
Another vtable hook source code here - Source Code - Simple internal VFTManager - ( vTable Hook )

__thiscall Function Hooking
This is the one calling convention which is tricky to hook and call. This calling convention is used for member functions, the this pointer (the address of the object calling the function) is passed in ECX so it can sometimes be tricky to hook & call

Tutorial - Thiscall (member function) hooking
Video Tutorial - How To Call __thiscall Game Functions C++ x64dbg #3

Import Address Table Hook
The import address table is part of the PE Header, it contains all the functions from other PE files which this binary imports. Similar to the vTable hook, all you have to do is overwrite the pointer to the imported function with a pointer to your function, then at the end of your function, call the original function.

@timb3r has an excellent tutorial here
Tutorial - How to Hook Import Address Table - IAT Hooking
and another from ntValk
Tutorial - IAT hook Import Address Table Hooking Explained

x64 Hooking
When you move on to hooking in x64 processes you will notice it's not quite so easy as before. a relative jmp on x86 has a length of 5 bytes but in x64 you need a bit more space. The reason a 5 byte jmp will not always work is because it's a relative jump and this 5 byte jump only takes a 4 byte relative offset. The 5 byte relative jump can only jump to addresses within 4,294,967,295 bytes if it's unsigned or 2,147,483,647 if it's signed. So you can only jump within 2-4GB of the instruction pointer. If the address you want to jump to is outside of this range then the 5 byte relative jump won't work.

I actually haven't written my own x64 hook so I will share one from @A200K which I have used before
C++:
void* DetourFunction64(void* pSource, void* pDestination, int dwLen)
{
    DWORD MinLen = 14;

    if (dwLen < MinLen) return NULL;

    BYTE stub[] = {
    0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [$+6]
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // ptr
    };

    void* pTrampoline = VirtualAlloc(0, dwLen + sizeof(stub), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

    DWORD dwOld = 0;
    VirtualProtect(pSource, dwLen, PAGE_EXECUTE_READWRITE, &dwOld);

    DWORD64 retto = (DWORD64)pSource + dwLen;

    // trampoline
    memcpy(stub + 6, &retto, 8);
    memcpy((void*)((DWORD_PTR)pTrampoline), pSource, dwLen);
    memcpy((void*)((DWORD_PTR)pTrampoline + dwLen), stub, sizeof(stub));

    // orig
    memcpy(stub + 6, &pDestination, 8);
    memcpy(pSource, stub, sizeof(stub));

    for (int i = MinLen; i < dwLen; i++)
    {
        *(BYTE*)((DWORD_PTR)pSource + i) = 0x90;
    }

    VirtualProtect(pSource, dwLen, dwOld, &dwOld);
    return (void*)((DWORD_PTR)pTrampoline);
}
Additional resources for x64 Hooks
Source Code - Simple x64 External C Trampoline Hook
Solved - x64 hook
Source Code - D3D11 Barebones hook PoC

If x64 hooking is too confusing for you, maybe just use MS Detours or another lib listed below

C# Hooking

Microsoft Detours 4.0
MS Detours is a very good hooking library but for most people it is too bloated and they write their own. If you just want to hook something and don't want to learn a bunch of stuff, them maybe using Detours is a good idea. It is especially useful if you need a x64 hook but don't know how to do it. Microsoft Detours 3 used to require a license to use the x64 version, they have since made it available for free for everyone.

Download from
microsoft/Detours

MS Detours Tutorial
Tutorial - How to use MS Detours - Microsoft Detours Tutorial

MS Detours x64 Hook example from @timb3r
https://guidedhacking.com/threads/ion-fury-health-regen-mod.13649/

@mambda's Hooking Lib
Bitbucket

Other Popular Hooking Libs
stevemk14ebr/PolyHook
TsudaKageyu/minhook

Considerations of using large, public Hooking Libs
MS Detours can easily be detected by anticheat, that doesn't mean it's detected, you should just be aware of this fact. Using any public hooking library will increase the possibility of you being detected. If you use MS Detours instead of writing your own hooking functions you will never learn how to hook. Hooking is a core hacking technique that you can't just skip over and not learn. MS Detour is big, most people like small binaries and not big bloated libraries so they write their own libs.

Here's a hooking lib from @mambda
It supports x86 and x64. Different from most other things here because it gives raw register (and flags, and SSE register) access, which makes the hooking process 10x simpler and more streamlined
Bitbucket


Other Popular GH Hooking Tutorials & Source Codes
 
Last edited:

Rake

Cesspool Admin
Administrator
Jan 21, 2014
11,539
78,998
2,312
Please share any corrections, links & tips to contribute to this guide! Especially if you have x64 hooking advice cuz I don't know much about it tbh
 

Ctrl+Alt+1337

Dank Tier Donator
Sep 2, 2018
34
688
0
I have two questions;

1) What are the advantages of using a trampoline hook intead of the detour/hooking method showed in Solitare's tutorial? As said in the beginning of the trampoline video, with a trampoline hook you avoid writing the shellcode yourself - but are there any other advantages? Just wondering.

2) The trampoline technique showed here (but also Solitare's) would work for any function one wants to hook, I believe. Isn't this also a downside with the MS Detour lib then? As MS Detour only hooks the Windows API not any function like with the trampoline approach showed here?

Great content, Rake. You really explain these techniques far better than any book I've came across about malware analysis.
 
Last edited:

mambda

headass
Escobar Tier VIP
Trump Tier Donator
Jun 25, 2014
2,275
37,938
268
1) What are the advantages of using a trampoline hook intead of the detour/hooking method showed in Solitare's tutorial? As said in the beginning of the trampoline video, with a trampoline hook you avoid writing the shellcode yourself - but are there any other advantages? Just wondering.
Trampoline will write the bytes in for you and depending on how yours is programmed will setup a nice register state for use in your hook function, just the next step of evolution really

2) The trampoline technique showed here (but also Solitare's) would work for any function one wants to hook, I believe. Isn't this also a downside with the MS Detour lib then? As MS Detour only hooks the Windows API not any function like with the trampoline approach showed here?
What do you mean isnt this also a downside with msdetours? Im pretty sure it works on any place you want to hook
 
  • Like
Reactions: Ctrl+Alt+1337

Rake

Cesspool Admin
Administrator
Jan 21, 2014
11,539
78,998
2,312
@Ctrl+Alt+1337 Trampoline hook is easy because you don't have to use any assembly, it's just super easy

Solaire's mid function hook is just a detour, if you don't want to hook the beginning of a function, but want to grab something out of a register, you use a regular detour like this

You can trampoline or detour any type of function, doesn't matter. MS Detours can also hook any type of function

You use a different function for x64 and if you're hooking a __thiscall function you must hook it as if it's a __fastcall
 
  • Like
Reactions: Ctrl+Alt+1337

KF1337

Dank Tier Donator
Full Member
Nobleman
Jan 30, 2020
81
2,773
0
I've implemented this code successfully! Thank you for this tutorial! :BillTheTiger:

One thing I'm wondering though: this code does not seem to work with a mid-function hook.
Original Code (working for hooking the first byte of a func):
typedef void(__fastcall* tFPSupdate)(int param_1);
tFPSupdate oFPSupdate;

void __fastcall hkFPSupdate(int i)
{
    std::cout << "Hooked!\n";

    oFPSupdate(i);
}
My idea was to alter the calling convention of my function, so it preserves the registers and the stack (basically total self-cleanup)
C++:
void __somecallingconventionthatcleansuptheregisterscall hkFPSupdate(int i)
{
    std::cout << "Hooked!\n";

    oFPSupdate(i);
}
Since there are just a few, i just tested them. Without success ofc.

Question: how do i preserve all the registers/the stack, so i can do a mid-function call?
 

mambda

headass
Escobar Tier VIP
Trump Tier Donator
Jun 25, 2014
2,275
37,938
268
I've implemented this code successfully! Thank you for this tutorial! :BillTheTiger:

One thing I'm wondering though: this code does not seem to work with a mid-function hook.
Original Code (working for hooking the first byte of a func):
typedef void(__fastcall* tFPSupdate)(int param_1);
tFPSupdate oFPSupdate;

void __fastcall hkFPSupdate(int i)
{
    std::cout << "Hooked!\n";

    oFPSupdate(i);
}
My idea was to alter the calling convention of my function, so it preserves the registers and the stack (basically total self-cleanup)
C++:
void __somecallingconventionthatcleansuptheregisterscall hkFPSupdate(int i)
{
    std::cout << "Hooked!\n";

    oFPSupdate(i);
}
Since there are just a few, i just tested them. Without success ofc.

Question: how do i preserve all the registers/the stack, so i can do a mid-function call?
pushad/popad assembly instructions
 
  • Like
Reactions: obdr
Attention! Before you post:

Read the How to Ask Questions Guide
99% of questions are answered in the Beginner's Guide, do it before asking a question.

No Hack Requests. Post in the correct section.  Search the forum first. Read the rules.

How to make a good post:

  • Fill out the form correctly
  • Tell us the game name & coding language
  • Post everything we need to know to help you
  • Ask specific questions, be descriptive
  • Post errors, line numbers & screenshots
  • Post code snippets using code tags
  • If it's a large project, zip it up and attach it

If you do not comply, your post may be deleted.  We want to help, please make a good post and we will do our best to help you.

Community Mods League of Legends Accounts