📖 Tutorial Hooking Tutorial For Beginners

Sbenny.com is trusted by 1,312,751 happy users since 2014.
Register

PixelYT

Apprentice Lv2️⃣
Member for 5 years
I know a great hooking tutorial already exists here, but this tutorial is more in-depth and in my opinion is more helpful for beginners.

Disclaimer: I found this tutorial somewhere else and I decided to share it here because it is really helpful! I DID NOT WRITE THIS TUTORIAL, THIS TUTORIAL WAS ORIGINALLY WRITTEN BY cryoatomizer



Game Name: Bullet Force
Coding Language: C++

Things you need to follow this Android Function Hooking Tutorial:

• Knowledge of C++
• Basic Knowledge on making mod menus for android.
• Must already know how to patch functions with hex codes. If you don't, come back when you can.
DnSpy
Android Studio

Octowolves template
Or
LGLS TEMPLATE

(if you prefer another template that's also fine of course)

• A brain


Assuming you have these, you can keep on reading. If not, this tutorial is too advanced for you to understand and be able to apply the principles to other games.

Please don't ask me questions unrelated to this tutorial in the comments. If you want to learn about making menus for android, read the other threads in this section.

I will provide a finished copy of the hooking tutorial with Octowolves template. It is your responsibility to update the offsets when needed, as I provide the function names already in this tutorial.

In this Android function hooking tutorial I will be using Octowolves template to demonstrate.

So, you know how to patch, but you want to take things to the next level. But what's the next level? Where do you begin?

Well, this tutorial IS the next level.

What is it?

Hooking.

What is hooking?


Hooking is a more efficient and better way of modding functions.

It allows us to return anything we want to a function, by creating a function and hooking it, by calling it in our main thread with the offset.

Why should I use it instead of patching?

• More efficient

• Can return anything you want

• Can set up functions to call pointers in update

• Any patching used in menus is easy to get leeched, and your offsets are at risk when patching.

• Hooking is harder to leech than patches and less likely to in the first place.


Now, that you know what hooking is and why you should use it, lets get on with the tutorial.

I will split this thread into 5 sections, one for each basic datatype you can hook, as well as an extra section.

Section 1: Android Hooking Basics

So, Hooking goes a little as follows:

First, we make a function and return what we want on it following the template below:
C++:
(datatype) (*old_function)(void *instance);
(datatype) function(void *instance) {
    if (instance != NULL) {
        if (boolean) {
            return (whatever suitable for datatype);
        }
    }
    return old_function(instance);
}
Then, we need to call it in our hack_thread with the offset like this:
C++:
octo_hook((void*)getAbsoluteAddress(0xOFFSET), (void*)Function, (void**)&old_Function);
Your full hack_thread would look something like this:
C++:
void* hack_thread(void*) {
    LOGI("I have been loaded. Mwuahahahaha");
    do {
        sleep(1);
    } while (!isLibraryLoaded(libName));
    LOGI("I found the il2cpp lib. Address is: %p", (void*)findLibrary(libName));
    octo_hook((void*)getAbsoluteAddress(0xOFFSET), (void*)Function, (void**)&old_Function);
    return NULL;
}
Thats it!


Section 2: Hooking Boolean functions.

In Bullet Force, there is an interesting function that we can find pretty easily.

If we search in dnspy for CanShoot, we can see that it is a function in class PlayerScript, which I mentioned in previous tutorials that it is your player class. All the good stuff is in it.
C++:
private bool CanShoot(bool checkRPM = true)
This function seems to check if we can shoot or not.

We could easily patch this to true and move on, but we are here for hooking right?

You can only return the datatype of the functions datatype. (duh), So we can only return true or false.

All we need to do is to return true, and it will allow us to shoot, even if we are out of ammo or reloading.

Strangely enough, when you modify this function, it also stops the bullet delay, making you able to shoot more bullets, so this function is also a firerate cheat.

Following the template I mentioned in section 1 above, we can create our hooking function and return true.
C++:
bool (*old_CanShoot)(void *instance);
bool CanShoot(void *instance) {
    if (instance != NULL) {
        if (isAmmoandFirerate) {
            return true;
        }
    }
    return old_CanShoot(instance);
}
Now, we need to call it in your hack thread and input an offset with getabsoluteaddress.
C++:
octo_hook((void*)getAbsoluteAddress(0x4ED460), (void*)CanShoot, (void**)&old_CanShoot);
Your hack thread should look like this now:
C++:
void* hack_thread(void*) {
    LOGI("I have been loaded. Mwuahahahaha");
    do {
        sleep(1);
    } while (!isLibraryLoaded(libName));
    LOGI("I found the il2cpp lib. Address is: %p", (void*)findLibrary(libName));
    octo_hook((void*)getAbsoluteAddress(0x4ED460), (void*)CanShoot, (void**)&old_CanShoot);
    return NULL;
}
Now, we need to make a new toggle for the feature. Find the const char *features in the jobject array getListFT.

Once you've found it Remove everything inside the { };

Your feature list should now look like this:
C++:
const char *features[]= {};
Then, add " " and put your feature name of your toggle inside of it. We are doing fire rate and unlimited ammo, So call the toggle what you want. Im going to call it "Firerate and Unlimited Ammo".

Your features list should now look like this:
C++:
const char *features[]= {"Unlimited Ammo And Firerate"};
Then, go to the changeSeekBar, changeSpinner, changeEditText functions, and remove the cases in there, as we don't need them, because we are only using toggles.

The functions should now look like this:
C++:
void changeSeekBar(JNIEnv *env, jclass clazz, jint i, jint seekbarValue) {
    int li = (int) i;
    switch (li) {
        default:
            break;
    }
    return;
}

void changeSpinner(JNIEnv *env, jclass clazz, jint i, jstring value) {
    int li = (int) i;
    switch (li) {
        default:
            break;
    }
}

void changeEditText(JNIEnv *env, jclass clazz, jint i, jstring value){
    int li = (int) i;
    switch (li){
        default:
            break;
    }
    return;
}
In your changetoggles function, delete the cases, and add case 0: and then break; at the end. (make sure to break after every case you make)

After that, do, isAmmoandFirerate = ! isAmmoandFirerate; inside of your case.

This is what it should look like now:
C++:
void changeToggle(JNIEnv *env, jclass thisObj, jint number) {
    int i = (int) number;
    switch (i) {
        case 0:
            isAmmoandFirerate = ! isAmmoandFirerate;
            break;
        default:
            break;
    }
    return;
}
We count from case 0 as the first feature, our second feature will be case 1, and so on.

That's it, you're done!

You just successfully hooked your first function! Give yourself a pat on the back.

Lets not get too cocky, we still don't know how to hook other basic datatypes.



Section 3: Hooking Android Integer Functions.

So, I've found a very interesting integer function.
C++:
public int getGrenadesLeft();
First, make a boolean.
C++:
bool isUnlimitedGrenades = false;
To hook this, we need to return an integer back. Following the template in section one, lets make our function.
C++:
int (*old_getGrenadesLeft)(void *instance);
int getGrenadesLeft(void *instance) {
    if(instance!=NULL) {
        if (isUnlimitedGrenades) {
            return 3;
        }
    }
    return old_getGrenadesLeft(instance);
}
Why did you only return 3? Don't we want more grenades than that, like 999?

Simple enough. When I first attempted using this function, the game checks if your grenades exceed the max number of grenades.

Instead of looking for the check and disabling it, we can just hook it to a low number. It will always stay at 3 grenades, giving us unlimited grenades.

Tip: If you are still getting kicked from the game, hook function GetMaxGrenades to 3 as well.

Now, call our hook in our hack thread with the offset.
C++:
octo_hook((void*)getAbsoluteAddress(0x8FD818), (void*)getGrenadesLeft, (void**)&old_getGrenadesLeft);
Your hack_thread should now look like this:
C++:
void* hack_thread(void*) {
    LOGI("I have been loaded. Mwuahahahaha");
    // loop until our target library is found
    do {
        sleep(1);
    } while (!isLibraryLoaded(libName));
    LOGI("I found the il2cpp lib. Address is: %p", (void*)findLibrary(libName));

    octo_hook((void*)getAbsoluteAddress(0x8FD818), (void*)getGrenadesLeft, (void**)&old_getGrenadesLeft);
    octo_hook((void*)getAbsoluteAddress(0x4ED460), (void*)CanShoot, (void**)&old_CanShoot);
    return NULL;
}
Then, add "Unlimited Grenades" as a feature in your feature list.

Add this inside ChangeToggles after case 0:
C++:
case 1:
   isUnlimitedGrenades = ! isUnlimitedGrenades;
break;
Done! You just successfully hooked your first int function.



Section 4: Hooking Float Functions.

So, Once again, we see another function that stands out.
C++:
public extern float get_fieldOfView();
This function controls your in-game Field Of View (fov).

We should return 100 to it, as we want a high fov right?

First, lets make our boolean.
C++:
bool isFov = false;
Then, lets make our function.
C++:
float (*old_get_fieldOfView)(void *instance);
float get_fieldOfView(void *instance) {
    if(instance!=NULL) {
        if (isFov) {
            return 100.0f;
        }
    }
    return old_get_fieldOfView(instance);
}
}
Why did we return 100.0f instead of just 100.0?

Since we are dealing with float functions, we need to return a float (duh) right?

Well, if we return 100.0, the game thinks its a double, which may or may not cause crash or feature issues.

When we put f at the end, it lets the game know its a float.

Better be safe than sorry!

Now, we can call our function in our hack thread with the offset.
C++:
octo_hook((void*)getAbsoluteAddress(0x1133710), (void*)get_fieldOfView, (void**)&old_get_fieldOfView);
Your finalized hack thread should look like something similar to this:
C++:
void* hack_thread(void*) {
    LOGI("I have been loaded. Mwuahahahaha");
    // loop until our target library is found
    do {
        sleep(1);
    } while (!isLibraryLoaded(libName));
    LOGI("I found the il2cpp lib. Address is: %p", (void*)findLibrary(libName));

    octo_hook((void*)getAbsoluteAddress(0x8FD818), (void*)getGrenadesLeft, (void**)&old_getGrenadesLeft);
    octo_hook((void*)getAbsoluteAddress(0x4ED460), (void*)CanShoot, (void**)&old_CanShoot);
    octo_hook((void*)getAbsoluteAddress(0x8FD818), (void*)get_fieldOfView, (void**)&old_get_fieldOfView);
    return NULL;
}
Then, go to your features, and add "Fov" as a feature.

Your final Features should look something like this:
C++:
const char *features[]= {"Ammo And Firerate", "Unlimited Grenades", "Fov Changer"};
Go to your changetoggles function and add:
C++:
case 2:
   isFov = ! isFov;
   break;
Your final changetoggle function should look like this:
C++:
void changeToggle(JNIEnv *env, jclass thisObj, jint number) {
    int i = (int) number;
    switch (i) {
        case 0:
            isAmmoandFirerate = ! isAmmoandFirerate;
            break;
        case 1:
            isUnlimitedGrenades = ! isUnlimitedGrenades;
            break;
        case 2:
            isFov = ! isFov;
            break;
        default:
            break;
    }
    return;
}
And that's it! Those are the 3 datatypes you will mostly see, and now you know how to hook all of them! Give yourself a pat on the back (again).

Section 5: Hooking update to use function pointers and other stuff

I've kind of already gone over this in many of my other tutorials, but ill recap it here for educational purposes.

What is update?

A short recap:

Update is called 60 times a second and is needed if you are using things like function pointers. It is useful for things like getting players positions, as you want the most current position of the player.

Right?

The best way is just hooking update.

So, lets make an update function.
C++:
void(*old_PlayerScript_UpdateFast)(void *player);
void PlayerScript_UpdateFast(void *player) {
    if(player != nullptr){
        //your stuff goes here
    }
    old_PlayerScript_UpdateFast(player);
}
Now, just hook it in our hack thread.
C++:
octo_hook((void*)getAbsoluteAddress(0x507AE8), (void*)PlayerScript_UpdateFast, (void**)&old_PlayerScript_UpdateFast);
That's it! You can now call whatever you desire in your update function. Have Fun! (ill leave the update function in the source code I provide, just in case anyone is going to use it).

Section 6: Using Headers for Offsets and Hook Android Functions (optional)

Using headers for things such as offsets or hook functions is mainly just for maintaining clean code in your main.cpp.

Lets make an offset header. It generally makes it easier to update offsets if they are in one file only in order.
C++:
#ifndef OFFSETS_H
#define OFFSETS_H

namespace Offsets {
    enum Offsets {
   
        CanShootOffset = 0x4ED460,
        getGrenadesLeftOffset = 0x8FD818,
        get_fieldOfViewOffset = 0x8FD818,
        PlayerScriptUpdateFastOffset = 0x507AE8

    };
}

#endif
Now, we can include our header, and replace our hook offsets with those in the header.

Your hooks should now look like this:
C++:
octo_hook((void*)getAbsoluteAddress(Offsets::getGrenadesLeftOffset), (void*)getGrenadesLeft, (void**)&old_getGrenadesLeft);
octo_hook((void*)getAbsoluteAddress(Offsets::CanShootOffset), (void*)CanShoot, (void**)&old_CanShoot);
octo_hook((void*)getAbsoluteAddress(Offsets::get_fieldOfViewOffset), (void*)get_fieldOfView, (void**)&old_get_fieldOfView);
octo_hook((void*)getAbsoluteAddress(Offsets::PlayerScriptUpdateFastOffset), (void*)PlayerScript_UpdateFast, (void**)&old_PlayerScript_UpdateFast);
Now, lets put our hook functions in a different header to make our main.cpp a bit cleaner.

We can put our booleans, hook functions, and more into the header.

We can also make a function that calls all of our hooks into the hack thread from the header, cleaning up the main.cpp even further.

This is what your hook header should look like:
C++:
bool isAmmoandFirerate = false;
bool isUnlimitedGrenades = false;
bool isFov = false;



bool (*old_CanShoot)(void *instance);
bool CanShoot(void *instance) {
    if (instance != NULL) {
        if (isAmmoandFirerate) {
            return true;
        }
    }
    return old_CanShoot(instance);
}

int (*old_getGrenadesLeft)(void *instance);
int getGrenadesLeft(void *instance) {
    if(instance!=NULL) {
        if (isUnlimitedGrenades) {
            return 3;
        }
    }
    return old_getGrenadesLeft(instance);
}

float (*old_get_fieldOfView)(void *instance);
float get_fieldOfView(void *instance) {
    if (instance != NULL) {
        if (isFov) {
            return 100.0f;
        }
    }
    return old_get_fieldOfView(instance);
}

void(*old_PlayerScript_UpdateFast)(void *player);
void PlayerScript_UpdateFast(void *player) {
    if(player != nullptr){
        //your stuff goes here
    }
    old_PlayerScript_UpdateFast(player);
}

void CallHooks() {
    octo_hook((void*)getAbsoluteAddress(Offsets::getGrenadesLeftOffset), (void*)getGrenadesLeft, (void**)&old_getGrenadesLeft);
    octo_hook((void*)getAbsoluteAddress(Offsets::CanShootOffset), (void*)CanShoot, (void**)&old_CanShoot);
    octo_hook((void*)getAbsoluteAddress(Offsets::get_fieldOfViewOffset), (void*)get_fieldOfView, (void**)&old_get_fieldOfView);
    octo_hook((void*)getAbsoluteAddress(Offsets::PlayerScriptUpdateFastOffset), (void*)PlayerScript_UpdateFast, (void**)&old_PlayerScript_UpdateFast);
}
Dont forget to call CallHooks(); in your hack_thread, otherwise it wont work.

Well, thats pretty much all the basics of hooking, and its quite simple once you get the hang of it. You shouldnt have to patch anything every again! (except maybe nopping anticheat functions).

I highly advise you to learn to hook as soon as possible. It is a very powerful skillset, and will broaden the things you can do.
 
Last edited:

Gourov

Dimitri Petrenko
✌️ Community Team
Member for 5 years
Thanks a lot for these valuable information 😊
 

PixelYT

Apprentice Lv2️⃣
Member for 5 years
Thanks for reading the tutorial :)
If you need help just ask me and I will help you or if you need another example of hacking like this then I will provide you one :)
 

Gourov

Dimitri Petrenko
✌️ Community Team
Member for 5 years
Thanks for reading the tutorial :)
If you need help just ask me and I will help you or if you need another example of hacking like this then I will provide you one :)
Thanks a lot mate . This is a great help for newbies like us. I will ofc knock you if I need any help :love:
 

PixelYT

Apprentice Lv2️⃣
Member for 5 years
@Gourov Awesome! :)
Post automatically merged:

@RockingRivu I could do a video tutorial but really it would be the same thing just ask me what you are having problems with. and I don't have a mic so I don't know if it would help to make a video without my voice?

I will look into it and If I do make a video tutorial I will make sure to remind you and to also link the video tutorial here as soon as i post it
 

xXxmanoxXx

Apprentice Lv2️⃣
Member for 4 years
PixelYT
please I didn`t get it and I saw this tut before in a lot of sites but it really needs a video to explain more details and become easier so if you will make a video that would be nice thanks man
 

PixelYT

Apprentice Lv2️⃣
Member for 5 years
maybe I will make video tutorial or write a more explanatory tutorial myself (although this tutorial by Shmoo explains everything much better than I can)
 

PixelYT

Apprentice Lv2️⃣
Member for 5 years
Tutorial is a little bit outdated and not very helpful for those who are new to hooking, so maybe i'll try to create a better (if I can ;p) tutorial that shows how to modify fields and hack using function pointers!
 

PolarBear

Novice Lv1️⃣
Member for 2 years
PixelYT
why we`re adding these booleans
isAmmoandFirerate
isUnlimitedGrenades
i mean these functions exist in the game or we`re making them???
where did you get them from??????
and what should i use
Octowolves template or LGLS TEMPLATE or MSHookFunction???? i mean what`s the most easiest?
 
Top