Outdated C++ - Mid Function Hooking & Codecaving Tutorial

  • WARNING: You are viewing the Legacy Fleep section which contains old and badly explained tutorials. You should not use these old tutorials. Our best, new tutorials are posted here and here.
Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat
Status
Not open for further replies.

Rake

Cesspool Admin
Administrator
Jan 21, 2014
12,153
78,998
2,396


This tutorial is very old, use this one instead, it's better & shorter:
Video Tutorial - C++ Detour / Hooking Function Tutorial for Game Hacking



Hello guys, today I have a tutorial for you on Mid function hooking.
This can be extremely useful if used well, and makes our life extremely easier when creating your own hacks.

Think of this as an introduction into code caving, in future I will try to go further into this concept and do more advanced hooking.


Updated for 2019
Projects re-created & tested working in VS 2017
Tested working on Windows 10
Attachment updated
Code & Project cleaned up
Zipped using SolZipper
Offsets updated - You will need to update the offsets again if the game updates




All Fleep Tutorials require special compiler settings

If you make a new project from scratch, you must set these project properties:

-Switch from Unicode to Multi Byte Character Set
-Set C++ -> All Options -> Permissive Conformance Mode: NO
-Linker -> Manifest File -> Require Administrator
-C++-> Precompiled Header -> Not Using Precompiled Headers
-C++ -> Add Preprocessor directive: _CRT_SECURE_NO_WARNINGS

Alternatively, download the attachment and use the pre-made project.




Here is some example code from main.cpp:
C++:
#include <Windows.h>
#include <iostream>
#include "Hooks.h"
//https://guidedhacking.com/threads/c-mid-function-hooking-codecaving-tutorial-difficulty-6-10.4061/

void InitiateHooks()
{
    //Find the instruction that decrements our ammo
    DWORD ammoAddy = FindPattern("ac_client.exe", "\x89\x0A\x8B\x76\x14\xFF\x0E", "xxxxxxx");

    ammoAddy += 5; //5 bytes = jmp instruction + 4 bytes for a 4byte address

    //AmmoJmpback is where we jmp after our code executes
    AmmoJmpBack = ammoAddy + 0x7;

    //Write the jmp, 7 is the number of stolen bytes we overwrite
    PlaceJMP((BYTE*)ammoAddy, (DWORD)InfiniteAmmo, 7);

    //Fly Hack - Find the instruction that accesses our Y axis
    DWORD flyAddy = FindPattern("ac_client.exe", "\x8B\x4E\x3C\x89\x56\x08", "xxxxxx");

    //Where we jump back to after our code runs
    FlyingJmpBack = flyAddy + 0x6;

    //Write the jmp, 6 is the number of stolen bytes we overwrite
    PlaceJMP((BYTE*)flyAddy, (DWORD)GetPlayerYaxis, 6);
}

//This thread contains our hack loop and toggles the hacks based on key input
DWORD WINAPI OverwriteValues()
{
    /*Loop forever, with a 150 millisecond interval per loop*/
    for (;; Sleep(150))
    {
        //resolve address of the Y Axis again in case YaxisRegister changed
        YAxisPtr = YaxisRegister + 0x3C;

        //FLY if the space key is held
        if (GetAsyncKeyState(VK_SPACE))
        {
            //Increase our Y axis making us FLY
            *(float *)YAxisPtr += 8.0;
        }
        if (GetAsyncKeyState(VK_CONTROL))
        {
            //Bring us back down if we get stuck somewhere
            *(float *)YAxisPtr -= 8.0;
        }
    }
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
    // Perform actions based on the reason for calling.
    switch (fdwReason)
    {
    case DLL_PROCESS_ATTACH:
        //Should do InitiateHooks in the thread not in PROCESS_ATTACH...
        InitiateHooks();
        CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)OverwriteValues, NULL, NULL, NULL);
        break;
    }
    return TRUE;
}
If you have any questions make sure you watch the video all the way and that will probably answer them, otherwise post below.

Hope you liked the tutorial. Please drop a like on the Video if so.

Fleep
 

Attachments

Last edited:

till0sch

Respected Hacker
Dank Tier VIP
Dank Tier Donator
Oct 14, 2012
1,104
12,593
51
Thanks for sharing. You could also push the address on the stack and return by an _asm ret.. Then you don't need those JmpBack addresses..
 

TastyHorror

Coder
Dank Tier Donator
Nobleman
Oct 11, 2012
179
2,268
8
You might not know this fleep, but I have been waiting for this for a long time.
 
Last edited:

blinkapec

Newbie
Nov 13, 2013
2
102
0
Hi Fleep!
Forgive me for my English.
First of all I want to thank you for your tutorials! They are really helpful and accessible for beginners like me.
I wanted to ask you in this series - is "codecaving" right termin for what you are describing in this tutorials? I thought this is when there are "holes" with (for example) 0x00-s in some code, that was there already. Or "caving" means "making caves"? :)
And second question: can you please do a tutorial on how to use hitboxes for aimbot (in cs:s for example) or something about hitboxes in general? It is really interesting (at least for me), because from what I've seen it is something that makes aiming more accurate and somehow related to model's animation or something, because hitboxes are moving with body parts (am I right?).
 
Last edited:

till0sch

Respected Hacker
Dank Tier VIP
Dank Tier Donator
Oct 14, 2012
1,104
12,593
51
I wanted to ask you in this series - is "codecaving" right termin for what you are describing in this tutorials? I thought this is when there are "holes" with (for example) 0x00-s in some code, that was there already. Or "caving" means "making caves"? :)
Well you can either do it with unused code (bytes) in the executable or allocate your own space.. Check out CheatEngine's code cave scanner..
 

c5

Kim Kong Trasher
Dank Tier VIP
Dank Tier Donator
Jul 19, 2012
1,187
12,638
76
Find shitloads of int3's (added by msvc compilers).. fill with your code
 

Szaka

Coder
Full Member
Nobleman
Mar 14, 2013
161
718
3
wow. 6 videos on one type of hooking. Must be really indepth
 

A200K

Newbie
Full Member
Sep 11, 2012
9
1,088
0
Really nice tutorial, but I have one question..


C++:
__asm{
	   mov ecx, [esi+0x3C]
	   mov YAxisPtr, esi; this here
	   add YAxisPtr, 0x3C; <- and this here
	   mov [esi+0x08],edx
	   jmp [FlyingJmpBack]
}
this works aswell, but I dont need the
C++:
YAxisPtr = YaxisRegister + 0x3C;
Now, I just wanted to know, wouldn't that be easier?
Or is there a difference?
 
Last edited:

A200K

Newbie
Full Member
Sep 11, 2012
9
1,088
0
And second question: can you please do a tutorial on how to use hitboxes for aimbot (in cs:s for example) or something about hitboxes in general? It is really interesting (at least for me), because from what I've seen it is something that makes aiming more accurate and somehow related to model's animation or something, because hitboxes are moving with body parts (am I right?).
Yeah, you are right... Use a kind of reversed 'GetBonePos' function, get the head (or other bone) index and aim on that pos, its a bit more accurate...
But that part is really really in-depth, so I had to use others' codes for that... (yet)
Would be happy for a Tutorial on that too :D
 
Last edited:

pet29

Newbie
Full Member
Oct 26, 2013
42
308
0
have been waiting for this for a long, long time some couple of years back
i have been on some game hacking forum a come to know about Super jump
and was very desperate to learn it ask around on some couple of forums but
nobody really gave me the real ideas tuts but finally the holy grill of game
hacking has been reviled:) i am out of words sir(words dont come easy:D)

Thanks a million sir, your hard work and time for a layman like me means a lot to me:):):)
 

crx123

Jr.Coder
Silenced
Nobleman
Apr 16, 2014
59
598
2
Im just wondering why would you do this in c++ if its so much faster and easier to do the same thing in CE Autoassembler?
 

Alsafa7

Newbie
Aug 6, 2012
4
988
0
First of all, thanks for the amazing tut Fleep. Just as always :)
Secondly, I just wanted to mention a minor modification to your code...
I was trying to apply what I learnt from the tutorial to PvZ. It's pretty easy, I already had the code from the previous tut ready, and all I had to do was to add the hooks header and all the easy replacements. I got everything up, and everything compiled fine, the address was found when the dll was injected to the app, but when I closed the message box, the app crashed with no errors. It just disappeared. Every single time. I had no use for the OverwriteValues function and creating the thread was pretty useless, so I commented the code out, and when I injected, it worked (or so I saw in the CE memory viewer). The issue was, when I closed the message box this time, the dll would unload, and the jmp that was working would then point to the address where the dll's codecave was once loaded. So, when this address gets called, the app would crash due to the app jumping to an empty address. So, I figured out a solution and that's what I wanted to share.
The solution was to increment the FreeLibrary's counter by one so that the DLL wouldn't get unloaded by itself. It would only unload if the app terminates or if you free the library memory manually. (Thus decrementing the counter) The way you would, increment the counter would be by calling LoadLibrary(), and so here is the new code I used in DllMain()
C++:
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
	switch (fdwReason)
	{
	case DLL_PROCESS_ATTACH:
		InitiateHooks();
		LoadLibrary(DLLNAME);
		//CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)OverwriteValues, NULL, NULL, NULL);
		break;
	}
}
Where DLLNAME is a definition at the top of the file of a string that contains the dll's name. (#define DLLNAME "X.dll")
This time, when I injected, the hack worked, and when I closed the message box, the dll remained loaded in the app's memory and the hack continued working successfully :D

Edit:
After even further fiddling with this method, I tried creating a hack for Need for Speed Rivals, which is a 64bit app. The sig/pattern (nop'ing) process worked pretty well with it. However the code doesn't want to compile using this method as inline arm instructions aren't allowed in 64bit dlls, applications, etc. You can only use intrinsic functions. So, saying that, can you please help me know how to convert a simple inline assembly function such as this:
C++:
unsigned long long SpJmpBack = 0;
__declspec(naked) void InfiniteSP()
{
	__asm
       {
               mov[rbx + 0x24], 999999999
	       add [rbx + 0x28], edi
	       jmp[SpJmpBack]
        }
}
Thanks a bunch for your help in advance. :)

Edit 2:
I found a way to run the assembly instructions, by creating a .asm file and placing this code in it:
C++:
.code
InfiniteSP proc
	mov esi, 999999999
	mov[edi + 00005578h], esi	
InfiniteSP endp
end
I couldn't add the jmp[SpJmpBack] instruction as I found no way to access the global variable (SpJmpBack), from within the assembly file. To solve this issue (I hope it worked out...), I added another PlaceJMP call after the initial and created a global variable in the functions header which stores the offset the codecave is at. So now the new PlaceJMP call looks like so:
C++:
PlaceJMP((BYTE*)ammoAddy, (unsigned long long)InfiniteSP, 6); //Original jmp

//Newly added jmp to codecave
PlaceJMP((BYTE*)(calcAdd+0x6),  /* address to place jmp instruction at. Added 6 because of the two instructions */
      SpJmpBack,  /* Instruction to jmp to */
      5 ); /* Size of jmp. No nop'ss */
Now I only face one problem... the original jmp doesn't point to the codecave. It points to a random position in the process, where the dll is not loaded at, thus causing the app to crash when the instruction gets called.
This is the project: https://www.dropbox.com/s/vbm7kl9smavlgdz/NFS14 Rivals Hack.zip (I hope there is no problem with sharing a url to a dropbox link)
Feel free to check out the code and the modifications I did, and please reply with the solution if found. Thanks in advance again. :)
PS: Don't be fooled by the solution/project's name. This is not a BF4 hack, its a NFS Rivals hack. (although both have 64 bit executables :p )
 
Last edited:

Alsafa7

Newbie
Aug 6, 2012
4
988
0
Update: I finally figured out the solution. It was very tiring to reach the end result but it works now. The issue was that since the game is 64 bits, the addresses are longer. So a 5 byte jmp isn't enough. Thus, I used a jmp qword ptr which points to the following address, where the jumpTo address is stored. So, if I wanted to jump to: 07FBC55A1A90 (true live example), I have to write the following on the spAddy:
C++:
NFS14.SetPlatform+21B0EB - FF 25 00000000        - jmp qword ptr [NFS14.SetPlatform+21B0F1]
NFS14.SetPlatform+21B0F1 - 90                    - nop 
NFS14.SetPlatform+21B0F2 - 1A 5A C5              - sbb bl,byte ptr [rdx-3B]
NFS14.SetPlatform+21B0F5 - FB                    - sti 
NFS14.SetPlatform+21B0F6 - 07                    - pop es
Note that the bytes that follow the jmp instruction are 07FBC55A1A90 in reverse. I had to edit the placejmp function a lot and here is the final result of the work:
C++:
void PlaceJMP(BYTE *Address, unsigned long long jumpTo, unsigned long long length = 5, bool relativeAddress = true)
{
	unsigned long dwOldProtect, dwBkup;
	unsigned long long dwRelAddr;

	//give that address read and write permissions and store the old permissions at oldProtection
	VirtualProtect(Address, length, PAGE_EXECUTE_READWRITE, &dwOldProtect);

	// Calculate the "distance" we're gonna have to jump - the size of the JMP instruction
	if (relativeAddress)
	{
#ifndef _WIN64
		dwRelAddr = (unsigned long long)(jumpTo - (unsigned long long)Address) - 5;
#else
		dwRelAddr = (unsigned long long)(jumpTo - (unsigned long long)Address) - 14;
#endif
	}
	else
		dwRelAddr = (unsigned long long)jumpTo; //the address is equal to the address of the function in the injected dll. No calculations needed.
	
	codecaveAddy = dwRelAddr; //Sets the address of the codecave to the address calculated

	// Write the JMP opcode @ our jump position...
#ifndef _WIN64
	*Address = 0xE9;

	// Write the offset to where we're gonna jump
	//The instruction will then become JMP ff002123 for example
	*((unsigned long long *)(Address + 0x1)) = dwRelAddr;
#else
	*Address = 0xFF;
	*(Address+0x1) = 0x25;
	*(Address + 0x2) = 0x0;
	*(Address + 0x3) = 0x0;
	*(Address + 0x4) = 0x0;
	*(Address + 0x5) = 0x0;// //FF 25 00 00 00 00 is the code for jmp qword ptr
	*((unsigned long long *)(Address + 0x6)) = dwRelAddr; //Set the next bytes after the first 6 to the jmpto address
#endif

	// Overwrite the rest of the bytes with NOPs
	//ensuring no instruction is Half overwritten(To prevent any crashes)
#ifndef _WIN64
	for (unsigned long long x = 0x5; x < length; x++)
		*(Address + x) = 0x90;
#else
	int bytesUsed = 0x0; //Obtaining the bytes used out of the unsigned long long addy
	if (dwRelAddr <= 0xFF)
		bytesUsed = 0x1;
	else if (dwRelAddr <= 0xFFFF)
		bytesUsed = 0x2;
	else if (dwRelAddr <= 0xFFFFFF)
		bytesUsed = 0x3;
	else if (dwRelAddr <= 0xFFFFFFFF)
		bytesUsed = 0x4;
	else if (dwRelAddr <= 0xFFFFFFFFFF)
		bytesUsed = 0x5;
	else if (dwRelAddr <= 0xFFFFFFFFFFFF)
		bytesUsed = 0x6;
	else if (dwRelAddr <= 0xFFFFFFFFFFFFFF)
		bytesUsed = 0x7;
	else if (dwRelAddr <= 0xFFFFFFFFFFFFFFFF)
		bytesUsed = 0x8;

	for (unsigned long long x = (0x6 + bytesUsed); x < length; x++)
		*(Address + x) = 0x90;
#endif

	// Restore the default permissions
	VirtualProtect(Address, length, dwOldProtect, &dwBkup);
}
I still don't get why you performed calculations to obtain the dwRelAddr? If you just set it to the function's address (jumpTo), it is set to the correct address which is found inside the injected dll's memory space. Can you explain why you did this Fleep ?

Here is the new source code for whomever wishes to fiddle with it: https://www.dropbox.com/s/jojgt471fh7hxr3/NFS14 Rivals Hack Update.zip
 

boyenn

Newbie
Full Member
Jul 20, 2014
5
122
0
Update: I finally figured out the solution. It was very tiring to reach the end result but it works now. The issue was that since the game is 64 bits, the addresses are longer. So a 5 byte jmp isn't enough. Thus, I used a jmp qword ptr which points to the following address, where the jumpTo address is stored. So, if I wanted to jump to: 07FBC55A1A90 (true live example), I have to write the following on the spAddy:
C++:
NFS14.SetPlatform+21B0EB - FF 25 00000000        - jmp qword ptr [NFS14.SetPlatform+21B0F1]
NFS14.SetPlatform+21B0F1 - 90                    - nop 
NFS14.SetPlatform+21B0F2 - 1A 5A C5              - sbb bl,byte ptr [rdx-3B]
NFS14.SetPlatform+21B0F5 - FB                    - sti 
NFS14.SetPlatform+21B0F6 - 07                    - pop es
Note that the bytes that follow the jmp instruction are 07FBC55A1A90 in reverse. I had to edit the placejmp function a lot and here is the final result of the work:
C++:
void PlaceJMP(BYTE *Address, unsigned long long jumpTo, unsigned long long length = 5, bool relativeAddress = true)
{
	unsigned long dwOldProtect, dwBkup;
	unsigned long long dwRelAddr;

	//give that address read and write permissions and store the old permissions at oldProtection
	VirtualProtect(Address, length, PAGE_EXECUTE_READWRITE, &dwOldProtect);

	// Calculate the "distance" we're gonna have to jump - the size of the JMP instruction
	if (relativeAddress)
	{
#ifndef _WIN64
		dwRelAddr = (unsigned long long)(jumpTo - (unsigned long long)Address) - 5;
#else
		dwRelAddr = (unsigned long long)(jumpTo - (unsigned long long)Address) - 14;
#endif
	}
	else
		dwRelAddr = (unsigned long long)jumpTo; //the address is equal to the address of the function in the injected dll. No calculations needed.
	
	codecaveAddy = dwRelAddr; //Sets the address of the codecave to the address calculated

	// Write the JMP opcode @ our jump position...
#ifndef _WIN64
	*Address = 0xE9;

	// Write the offset to where we're gonna jump
	//The instruction will then become JMP ff002123 for example
	*((unsigned long long *)(Address + 0x1)) = dwRelAddr;
#else
	*Address = 0xFF;
	*(Address+0x1) = 0x25;
	*(Address + 0x2) = 0x0;
	*(Address + 0x3) = 0x0;
	*(Address + 0x4) = 0x0;
	*(Address + 0x5) = 0x0;// //FF 25 00 00 00 00 is the code for jmp qword ptr
	*((unsigned long long *)(Address + 0x6)) = dwRelAddr; //Set the next bytes after the first 6 to the jmpto address
#endif

	// Overwrite the rest of the bytes with NOPs
	//ensuring no instruction is Half overwritten(To prevent any crashes)
#ifndef _WIN64
	for (unsigned long long x = 0x5; x < length; x++)
		*(Address + x) = 0x90;
#else
	int bytesUsed = 0x0; //Obtaining the bytes used out of the unsigned long long addy
	if (dwRelAddr <= 0xFF)
		bytesUsed = 0x1;
	else if (dwRelAddr <= 0xFFFF)
		bytesUsed = 0x2;
	else if (dwRelAddr <= 0xFFFFFF)
		bytesUsed = 0x3;
	else if (dwRelAddr <= 0xFFFFFFFF)
		bytesUsed = 0x4;
	else if (dwRelAddr <= 0xFFFFFFFFFF)
		bytesUsed = 0x5;
	else if (dwRelAddr <= 0xFFFFFFFFFFFF)
		bytesUsed = 0x6;
	else if (dwRelAddr <= 0xFFFFFFFFFFFFFF)
		bytesUsed = 0x7;
	else if (dwRelAddr <= 0xFFFFFFFFFFFFFFFF)
		bytesUsed = 0x8;

	for (unsigned long long x = (0x6 + bytesUsed); x < length; x++)
		*(Address + x) = 0x90;
#endif

	// Restore the default permissions
	VirtualProtect(Address, length, dwOldProtect, &dwBkup);
}
I still don't get why you performed calculations to obtain the dwRelAddr? If you just set it to the function's address (jumpTo), it is set to the correct address which is found inside the injected dll's memory space. Can you explain why you did this Fleep ?

Here is the new source code for whomever wishes to fiddle with it: https://www.dropbox.com/s/jojgt471fh7hxr3/NFS14 Rivals Hack Update.zip
as you seem to know what you're talking about , is there any way you could add me on skype(boyenn-x3) because I have some questions / trouble understanding some small stuff
 

x1jester

Newbie
Full Member
Jul 30, 2014
5
124
0
Thanks for the awesome site and tutorial > hey i need a bit of help with mine please!!!! :( i cant get the y access to work out properly idk what to use for my code instead of yours mine doesnt use esi the top is my start and the top to bottom is where i have the signature set so i think the offset would be -12 kgllib.sqstd_register_bloblib+1C5C45 - D9 40 04 - fld dword ptr [eax+04]
1C5C48 - D9 59 04 - fstp dword ptr [ecx+04]
1C5C4B - D9 40 08 - fld dword ptr [eax+08]
1C5C4E - D9 59 08 - fstp dword ptr [ecx+08]
1C5C51 - EB 2D - jmp kgllib.sqstd_register_bloblib+1C5C80


\xD9\x40\x04\xD9\x59\x04\xD9\x40\x08\xD9\x59\x08\xEB\x2D
xxxxxxxxxxxxxx
 

HalfWayToHell333

Jr.Coder
Silenced
Full Member
Nobleman
Jun 23, 2014
80
783
3
Fleep ,

first thanks for this Tutorial(s).

I have a suggestion for binding in multiple Header´s in Visual C++ wich You mentioned in one of Your Videos.

If you get an error , You can do this:

#ifndef BLABLA_H
#define BLABLA_H

//Your Code here//

#endif

or

#pragma once

//Your Code here//

or what i do:

create a Globals.h and put every used include´s into this.

That solves the Problem (at least in my cases :D)
 
Status
Not open for further replies.
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