Tutorial How To Hook Functions

Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat

Solaire

Respected Hacker
Dank Tier VIP
Dec 15, 2013
1,051
16,353
62
Before you read this, you should know of a few key concepts that are needed to really understand the hooking process.

  1. X86 assembly, and x86 assembly opcodes. This is a great page to view the x86 opcodes coder32 edition | X86 Opcode and Instruction Reference 1.11
  2. A solid understanding of how things work internally for a program, as well as how to reverse functions to get a better understanding of what they do. If you’ve never looked into the Cheat Engine memory viewer, or OllyDBG, or IDA, you probably need to spend some time working with those tools.
  3. An ability to learn, and an ability to RTFM (Read the F***ing manual). I will be putting the MSDN page for a function above it when I use it so that you can read up on it and better understand what is going on. I pray that whoever reads this doesn’t blindly C&P, that gets you nowhere.

I’ll be using the plain hook from my hooking class as an example for this tutorial.

Let’s go over some theory. Essentially, hooking is changing a program’s flow so that it executes your code at a certain spot in memory. To dive further in-depth, we place a jump to our code at a certain spot inside of a program, which then jumps back to after the jump we originally placed.
Let’s start by writing the skeleton of our hooking function. We want it to place a hook at the address that jumps to our function. So, there should probably be two parameters here.

  1. The spot we’re hooking
  2. The function it’s jumping to.

So let’s write a bit of code.
C++:
bool placeHook(void * hookSpot, void * ourFunct);
Now that we have that, let’s go over why there needs to be a third parameter. Length. When hooking, we put a jump on the hook spot. A jump takes 5 bytes of space. You might be wondering why that even matters. Well, if there are three instructions, the first two taking up a total of 4 bytes, the next one taking up 4 itself, we would end up cutting straight through that last instruction, leaving stray bytes which in turn could cause undefined behavior, and in most cases, a nasty crash. So if in total we have to take up 8 bytes to prevent from causing a nasty crash, we need to tell the function that.
C++:
bool placeHook(void * hookSpot, void * ourFunct, int len);
Great! The next step is to understand what goes on inside of the hook function.

  1. We use VirtualProtect to make sure that we have access to the bytes we’re overwriting.
  2. We calculate the relative address between our function, and the hooking spot.
  3. We place a jump on the first byte of the hooking spot
  4. We place the relative address on the next four bytes of the hooking spot
  5. We restore the original protection on the function.

It’s as simple as that. Let’s go ahead and write step one.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa366898(v=vs.85).aspx
C++:
bool placeHook(void * hookSpot, void * ourFunct, int len)
{
                 DWORD oldProtect;

                if (len < 5)
                {
                                return false;
                }

                 if (!VirtualProtect(hookSpot, len, PAGE_EXECUTE_READWRITE, &oldProtect))
                {
                                return false;
                }
}
if (len < 5)
So, first we check that the length of the hook is at least 5 bytes. If it wasn’t, we would have some trouble placing the jump there.
Next, we make sure VirtualProtect doesn’t return 0. If it does, that means it failed and we would have to return false. VirtualProtect makes sure we have the correct rights to mess with the memory at the specified address. Please read the MSDN on it.

The next step is to calculate the relative address between the our function and the hook spot
DWORD relativeAddy = ((DWORD)ourFunct - (DWORD)hookSpot) - 5;
We subtract five for the size of the jump. Relative addresses allow us to make short jumps around memory without using exact addresses.

Adding that to the function:
C++:
bool placeHook(void * hookSpot, void * ourFunct, int len)
{
                DWORD oldProtect;

                if (len < 5)
                {
                                return false;
                }

                 if (!VirtualProtect(hookSpot, len, PAGE_EXECUTE_READWRITE, &oldProtect))
                {
                                return false;
                }

                DWORD relativeAddy = ((DWORD)ourFunct - (DWORD)hookSpot) – 5;
}
The next step is to place a jump on the first byte of the hooking spot. In x86 assembly, the opcode for jmp is 0xE9.
*(BYTE*)hookSpot = 0xE9;
We need the byte at that point in memory, so we cast it into a byte and dereference it. This will place 0xE9 on the first byte.

The next step is to place the relative address on the next four bytes.
*(DWORD*)((DWORD)hookSpot + 0x1) = relativeAddy;
Let’s break this down a bit. (DWORD)hookSpot + 0x1 This makes sure that we’re placing the hook one byte after the jump. *(DWORD*) this dereferences the spot into a DWORD so that we can place the last four bytes onto the hooking spot.

Let’s put it all together.
C++:
bool placeHook(void * hookSpot, void * ourFunct, int len)
{
                DWORD oldProtect;

                if (len < 5)
                {
                                return false;
                }

                  if (!VirtualProtect(hookSpot, len, PAGE_EXECUTE_READWRITE, &oldProtect))
                {
                                return false;
                }

                DWORD relativeAddy = ((DWORD)ourFunct - (DWORD)hookSpot) – 5;
                *(BYTE*)hookSpot = 0xE9;
                *(DWORD*)((DWORD)hookSpot + 0x1) = relativeAddy;
}
If the hook length is greater than five, we still have some left over bytes. We need to NOP those to prevent a crash.
C++:
bool placeHook(void * hookSpot, void * ourFunct, int len)
{
                DWORD oldProtect;

                if (len < 5)
                {
                                return false;
                }

               
                 if (!VirtualProtect(hookSpot, len, PAGE_EXECUTE_READWRITE, &oldProtect))
                {
                                return false;
                }

                DWORD relativeAddy = ((DWORD)ourFunct - (DWORD)hookSpot) – 5;
                *(BYTE*)hookSpot = 0xE9;
                *(DWORD*)((DWORD)hookSpot + 0x1) = relativeAddy;
              
                for (int i = 0; i < len – 5; i++)
                {
                                *(BYTE*)((DWORD)hookSpot + 0x5 + i) = 0x90;
                }
}

We’re almost done. The last step is to restore the original protection.
C++:
bool placeHook(void * hookSpot, void * ourFunct, int len)
{
                DWORD oldProtect;

                if (len < 5)
                {
                                return false;
                }

                  if (!VirtualProtect(hookSpot, len, PAGE_EXECUTE_READWRITE, &oldProtect))
                {
                                return false;
                }

                DWORD relativeAddy = ((DWORD)ourFunct - (DWORD)hookSpot) – 5;
                *(BYTE*)hookSpot = 0xE9;
                *(DWORD*)((DWORD)hookSpot + 0x1) = relativeAddy;

                for (int i = 0; i < len – 5; i++)
                {
                                *(BYTE*)((DWORD)hookSpot + 0x5 + i) = 0x90;
                }

         DWORD backup;
                if (!VirtualProtect(hookSpot, len, oldProtect, &backup))
                {
                                return false;
                }

                return true;
}
To use the function, you need to have a hook function that will be used when the program runs to your jump.

C++:
__declspec(naked) void ourFunct()
{
                __asm
                {
                                //Make sure to put the bytes that were overwritten at the hook spot here
                                //After that, you can do whatever you want with it.
                                //Make sure to have a jmp at the end that goes back to after the hookspot.
                }
}
It’s literally that simple! I’ll go over trampoline hooking in the next tutorial. After that, I’ll probably go over some not so common methods.
 
Last edited by a moderator:

mPulse

Coder
Full Member
Nobleman
Jun 19, 2013
106
733
0
Thank you for awesome Tutorial :p,Can you make video version too? =)
 

Solaire

Respected Hacker
Dank Tier VIP
Dec 15, 2013
1,051
16,353
62
Thank you for awesome Tutorial :p,Can you make video version too? =)
I won't be doing any video tutorials, just written ones :p.

If anyone has any questions regarding how to hook, don't afraid to ask!
 

konsowa

Coder
Full Member
Nobleman
May 24, 2012
178
753
2
So what i understand is that in the inline asm at the end i would need to place a jump to hookspot+0x5 so that it goes back after the jmp we placed right?
 

mambda

headass
Escobar Tier VIP
Trump Tier Donator
Jun 25, 2014
2,294
37,938
269
Yep. __asm jmp [hookLocation + #OfBytesOverwritten]
 

khanisgr8

Newbie
Jul 31, 2016
1
32
0
I just register only for this tut. One of the best Thread of my day :)

Thanks buddy

@off topic :
do we have such beautifull tutorial for trampoline hook ?
 

manpower

They call me the noob coder 😎
Dank Tier Donator
Jun 9, 2019
45
2,443
1
Thanks for this amazing text tutorial, this combined with the video tutorial made me understand everything. +rep:BillTheTiger: keep up the good work
 
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