~Read this tutorial first: Basic Hooking Tutorial
~Use this template to do this: LGLTeam/Android-Mod-Menu
~You need some knowledge of C++ to understand this (You can learn C++ on sites such as Geeks For Geeks, TutorialsPoint, Youtube etc. or from apps in the Play Store)
Before I start, what do I mean by "unlink"? Well, have you ever made a hack and the hack was also shared with the enemy (i.e. you gave yourself unlimited ammo or health, but the enemy also gets it) or the other way around (i.e. you made a hack to kill all enemies to auto-win but you also get killed). You will learn how to unlink them with various examples.
(While reading the tutorial, make sure to read the comments I put in the code as well)
1. Using bool functions
I dumped a game and saw this function to get unlimited health but it was shared:
which means if I hooked it and tried to give myself unlimited health like this:
IT WOULD NOT WORK AND ENEMIES WILL GET UNLIMITED HEALTH TOO SINCE IT'S SHARED!
So how do we unlink it? It's not the same for every game, but try to look for a function inside the same class which you can use to unlink. In my case, I found this function which I can use to unlink:
How would we do it? Well, we declare a function pointer to it and this is how you declare function pointers:
IMPORTANT: We split the function pointer like that because when your lib is loaded, sometimes the libil2cpp.so isn't loaded but your lib tries to read the offset anyways which results in a crash, splitting the function pointer like I did will fix this.
Here's the function pointer for get_isMine:
Now that we have a function pointer to get_isMine, we can make a variable to it and use it to unlink our hack like this:
2. Using int functions
So i dumped a game and in the dump.cs I saw this function in the class CharacterController which I used to get auto-win, but it was shared:
Which means If I hooked it and tried to make an auto-win hack like this:
IT WOULD NOT WORK AND I WOULD DIE TOO SINCE IT'S SHARED!!
So how do we unlink it? Well, just like in the first example, we look for a function in the CharacterController class which we can use to unlink our hack. BUT what if you don't have a bool function in your class to do it? What you need to do is look for other functions in your class which you can use to unlink if you don't have a bool function to do it. In my case, I found these two functions which aren't bools but can help me unlink my hack:
ownerIDNumber holds your ID number
playerIDNumber holds the ID number of every player
So how would I use these two to unlink my hack and make it kill all enemies only? Well we create function pointers to both of them like this:
Now that we have function pointers for both, we can declares variables to them and unlink our hack like this:
3. Using bool fields
Unlinking with fields is similar to unlinking with functions, but you don't use a function pointer.
I dumped a game and in the class Player, I saw this function and wanted to use it to kill all enemies:
BUT IT'S SHARED WHICH MEANS I WOULD DIE TOO. So how do I unlink it using a field? Well, just like in the examples above, you look for fields in the class which you can use to unlink instead of a function in the class. In my case, I found this field in the Player class which could help me unlink it:
In the Player class, I am gonna hook the LateUpdate function instead of killPlayer, and instead use a function pointer for killPlayer. Why do I hook the LateUpdate function? The LateUpdate and Update functions are called as many times in a second as your FPS is. So if your FPS is 60 FPS, then Update is called 60 times every second. Why is this useful? Think about it. We wouldn't want to get and set fields on an object that hasn't been updated for a while right? We need our most current object to modify, and what better way of getting it than hooking a function that is called 60 times every second?
Here's my LateUpdate function in the class Player:
Here's the hook for the LateUpdate function:
So how do we use the field isEnemy to unlink our hack? You declare a variable to it like this:
Now that we have a variable to access the field isEnemy, we can use it to unlink our hack and use a function pointer for killPlayer to do it:
4. Using int fields
I dumped a game and in the dump.cs inside of the class Weapon, I saw this function to get one-hit kill but it was shared:
What if you want to use a field that isn't a bool to unlink your hack? Well, as always, try to look for a field which could help you unlink your hack. In my case, I saw these fields which could help me unlink my hack:
this field contains the number of all teams. (Not how many teams there are but their assigned number, similar to how other games use an ID)
this one contains the number of your enemies team only.
This class has an Update function and I am gonna hook it:
Now I will declare variables to both of my fields:
Now that we have access to both of our fields, we can use the variables to unlink our hack and get one-hit kill like this:
5. Using fields from a different class
I dumped a game and saw this function inside the class CharacterAssets which was shared with the enemy:
I wanted to unlink it using a field but I could not find any field in the class CharacterAssets that would've helped me unlink it. But inside the class CharacterController I saw this field and I wanted to use it:
How would I use it if it's in a different class? Well in your class you try to find an instance to the other class. In my case, I found this field inside of the CharacterAssets class which I can use to get access to the CharacterController class:
I can use this instance to get to the field isBot inside of the CharacterController class like this:
now that we have access to the class CharacterController and have a variable for the isBot field in that class, we can finish our hack like this:
Edit: I forgot to show how to connect them to a toggle, but here's how:
(I am gonna do this on the 2nd example)
Make a bool for your hack in the bools section and set it to false (After the Memory Patches struct):
Make a toggle for it in the features section and I am gonna assign my own number to it:
Now in your hook just check for the hack using the bool you made:
Lastly, add this in the cases section using the bool you made:
Now your hack will only be on if you turn on the toggle!
That's it!
Credits:
~@SecretMyAss (His examples helped me a lot)
~Me (Used his examples and made ones suitable for Android)
~Check out Andnixsh's source codes
~Use this template to do this: LGLTeam/Android-Mod-Menu
~You need some knowledge of C++ to understand this (You can learn C++ on sites such as Geeks For Geeks, TutorialsPoint, Youtube etc. or from apps in the Play Store)
Before I start, what do I mean by "unlink"? Well, have you ever made a hack and the hack was also shared with the enemy (i.e. you gave yourself unlimited ammo or health, but the enemy also gets it) or the other way around (i.e. you made a hack to kill all enemies to auto-win but you also get killed). You will learn how to unlink them with various examples.
(While reading the tutorial, make sure to read the comments I put in the code as well)
1. Using bool functions
I dumped a game and saw this function to get unlimited health but it was shared:
C#:
private int healthPoints(); // 0x436BC7
C++:
int (*old_healthPoints)(void *instance);
int healthPoints(void *instance)
{
if(instance != NULL) // Check if instance isn't NULL to prevent crashes
{
return 999999; // If instance isn't NULL, then make my health 999999
}
return old_healthPoints(instance); // If instance is NULL, return original value
}
MsHookFunction((void*)getAbsoluteAddress(0x436BC7), (void*)healthPoints, (void**)&old_healthPoints); // Make sure to call your hooks with MSHook
So how do we unlink it? It's not the same for every game, but try to look for a function inside the same class which you can use to unlink. In my case, I found this function which I can use to unlink:
C#:
public bool get_isMine(); // 0x453C91
C++:
FunctionType(*FunctionName)(void *instance, AnyAdditionalParameters);
FunctionName = (FunctionType (*)(void*, TypesOfAdditionalParameters))getAbsoluteAddress(targetLibName, 0xOFFSET);
Here's the function pointer for get_isMine:
C++:
bool (*get_isMine)(void *instance); // get_isMine doesn't have any additional parameters
int (*old_healthPoints)(void *instance);
int healthPoints(void *instance)
{
if(instance != NULL) // Check if instance isn't NULL to prevent crashes
{
return 999999; // If instance isn't NULL, then make my health 999999
}
return old_healthPoints(instance); // If instance is NULL, return original value
}
MsHookFunction((void*)getAbsoluteAddress(0x436BC7), (void*)healthPoints, (void**)&old_healthPoints); // Make sure to call your hooks with MSHook
get_isMine = (bool (*)(void*))getAbsoluteAddress(targetLibName, 0x453C91); // Again, get_isMine doesn't take any additional parameters
C++:
bool (*get_isMine)(void *instance); // get_isMine doesn't have any additional parameters
int (*old_healthPoints)(void *instance);
int healthPoints(void *instance)
{
if(instance != NULL) // Check if instance isn't NULL to prevent crashes
{
bool isMine = get_isMine(instance); // Declare a variable to our function pointer
if(isMine) // Check if it's you
{
return 999999; // And if it's you, then make my health 999999 (Now only you get unlimited health)
}
}
return old_healthPoints(instance); // If instance is NULL OR IF IT'S NOT YOU, return original value
}
MsHookFunction((void*)getAbsoluteAddress(0x436BC7), (void*)healthPoints, (void**)&old_healthPoints); // Make sure to call your hooks with MSHook
get_isMine = (bool (*)(void*))getAbsoluteAddress(targetLibName, 0x453C91); // Again, get_isMine doesn't take any additional parameters
2. Using int functions
So i dumped a game and in the dump.cs I saw this function in the class CharacterController which I used to get auto-win, but it was shared:
C#:
private bool isDead(); // 0x832BC29
C++:
bool (*old_isDead)(void *instance);
bool isDead(void *instance)
{
if(instance != NULL) // Check if instance isn't NULL to prevent crashes
{
return true; // If instance isn't NULL, return true and kill everyone
}
return old_isDead(instance); // Return original value if instance is NULL
}
MsHookFunction((void*)getAbsoluteAddress(0x832BC29), (void*)isDead, (void**)&old_isDead); // Make sure to call your hooks with MSHook
So how do we unlink it? Well, just like in the first example, we look for a function in the CharacterController class which we can use to unlink our hack. BUT what if you don't have a bool function in your class to do it? What you need to do is look for other functions in your class which you can use to unlink if you don't have a bool function to do it. In my case, I found these two functions which aren't bools but can help me unlink my hack:
C#:
private int ownerIDNumber(); // 0x832C39
C#:
private int playerIDNumber(); // 0x3279BC
So how would I use these two to unlink my hack and make it kill all enemies only? Well we create function pointers to both of them like this:
C++:
int (*ownerIDNumber)(void *instance); // Function pointer for int ownerIDNumber (doesn't take any additional parameters)
int (*playerIDNumber)(void *instance); // Function pointer for int playerIDNumber (doesn't take any additional parameters)
bool (*old_isDead)(void *instance);
bool isDead(void *instance)
{
if(instance != NULL) // Check if instance isn't NULL to prevent crashes
{
return true; // If instance isn't NULL, return true and kill everyone
}
return old_isDead(instance); // Return original value if instance is NULL
}
MsHookFunction((void*)getAbsoluteAddress(0x832BC29), (void*)isDead, (void**)&old_isDead); // Make sure to call your hooks with MSHook
ownerIDNumber = (int (*)(void*))getAbsoluteAddress(targetLibName, 0x832C39); // Offset of ownerIDNumber
playerIDNumber = (int (*)(void*))getAbsoluteAddress(targetLibName, 0x3279BC); // Offset of playerIDNumber
C++:
int (*ownerIDNumber)(void *instance); // Function pointer for int ownerIDNumber (doesn't take any additional parameters)
int (*playerIDNumber)(void *instance); // Function pointer for int playerIDNumber (doesn't take any additional parameters)
bool (*old_isDead)(void *instance);
bool isDead(void *instance)
{
if(instance != NULL) // Check if instance isn't NULL to prevent crashes
{
int OwnerID = ownerIDNumber(instance); // Variables for both of our function pointers
int PlayerID = playerIDNumber(instance);
if(OwnerID != PlayerID) // Check If the player's ID does not equal to your ID
{
return true; // And if it doesn't equal to your ID, then kill them
}
}
return old_isDead(instance); // Return original value if instance is NULL OR IF PLAYER ID DOES EQUAL TO YOUR ID
}
MsHookFunction((void*)getAbsoluteAddress(0x832BC29), (void*)isDead, (void**)&old_isDead); // Make sure to call your hooks with MSHook
ownerIDNumber = (int (*)(void*))getAbsoluteAddress(targetLibName, 0x832C39); // Offset of ownerIDNumber
playerIDNumber = (int (*)(void*))getAbsoluteAddress(targetLibName, 0x3279BC); // Offset of playerIDNumber
3. Using bool fields
Unlinking with fields is similar to unlinking with functions, but you don't use a function pointer.
I dumped a game and in the class Player, I saw this function and wanted to use it to kill all enemies:
C#:
private void killPlayer(); // 0x2485B9
C#:
public bool isEnemy; // 0x8C
Here's my LateUpdate function in the class Player:
C#:
private void LateUpdate(); // 0x32720AB
C++:
void(*old_LateUpdate)(void *instance);
void LateUpdate(void *instance)
{
if(instance != NULL)
{
}
old_LateUpdate(instance); // We don't use return because we aren't returning anything to the LateUpdate function, we are using function pointer to call killPlayer
}
MsHookFunction((void*)getAbsoluteAddress(0x32720AB), (void*)LateUpdate, (void**)&old_LateUpdate);
C++:
void(*old_LateUpdate)(void *instance);
void LateUpdate(void *instance)
{
if(instance != NULL)
{
bool IsEnemy = *(bool*)((uint64_t)instance + 0x8C) // Declare a variable to isEnemy to access it
}
old_LateUpdate(instance);
}
MsHookFunction((void*)getAbsoluteAddress(0x32720AB), (void*)LateUpdate, (void**)&old_LateUpdate);
C++:
void (*killPlayer)(void *instance); // Doesn't take any additional parameters
void(*old_LateUpdate)(void *instance);
void LateUpdate(void *instance)
{
if(instance != NULL)
{
bool IsEnemy = *(bool*)((uint64_t)instance + 0x8C) // Declare a variable to isEnemy to access it
if(IsEnemy) // Check if it's enemies
{
killPlayer(instance); // And if they are then kill them
}
}
old_LateUpdate(instance); If they aren't enemies then return original value
}
MsHookFunction((void*)getAbsoluteAddress(0x32720AB), (void*)LateUpdate, (void**)&old_LateUpdate);
killPlayer = (void (*)(void *))getAbsoluteAddress(targetLibName, 0x2485B9);
4. Using int fields
I dumped a game and in the dump.cs inside of the class Weapon, I saw this function to get one-hit kill but it was shared:
C#:
private int Damage; // 0x18
C#:
private int teamNumber; // 0x50
C#:
private int enemyTeamNumber; // 0x54
This class has an Update function and I am gonna hook it:
C#:
private void Update(); // 0x7273A2
C++:
void (*old_Update)(void *instance);
void Update(void *instance)
{
if(instance != NULL)
{
}
old_Update(instance);
}
MsHookFunction((void*)getAbsoluteAddress(0x7273A2), (void*)Update, (void**)&old_Update);
C++:
void (*old_Update)(void *instance);
void Update(void *instance)
{
if(instance != NULL)
{
int TeamNumber = *(int*)((uint64_t)instance + 0x50);
int EnemyTeam = *(int*)((uint64_t)instance + 0x54);
}
old_Update(instance);
}
MsHookFunction((void*)getAbsoluteAddress(0x7273A2), (void*)Update, (void**)&old_Update);
C++:
void (*old_Update)(void *instance);
void Update(void *instance)
{
if(instance != NULL)
{
int TeamNumber = *(int*)((uint64_t)instance + 0x50); // Variables to our fields which we use to unlink our hack
int EnemyTeam = *(int*)((uint64_t)instance + 0x54);
if(TeamNumber != EnemyTeam) // Check if it's your team
{
*(int*)((uint64_t)instance + 0x18) = 999; // private int Damage; // 0x18 now only your team has one-hit kill
}
}
old_Update(instance); // If it's enemy team, then return original value
}
MsHookFunction((void*)getAbsoluteAddress(0x7273A2), (void*)Update, (void**)&old_Update);
5. Using fields from a different class
I dumped a game and saw this function inside the class CharacterAssets which was shared with the enemy:
C#:
public int get_ammoInClip(); // 0x34287
C#:
public bool isBot; // 0x24
C#:
public CharacterController characterController; // 0x32
C++:
int(*old_get_ammoInClip)(void *instance);
int get_ammoInClip(void *instance)
{
if(instance != NULL)
{
void *AccessCharacterController = *(void**)((uint64_t)instance + 0x32); // Use the field and make a pointer to get access to CharacterController
if(AccessCharacterController != NULL) // Since we use a pointer for the field 0x32 to get access to the CharacterController class, we have to check if it isn't null
{
bool IsBot = *(bool*)((uint64_t)AccessCharacterController + 0x24); // use it to access the field isBot in the class CharacterController
}
}
return old_get_ammoInClip(instance);
}
MsHookFunction((void*)getAbsoluteAddress(0x34287), (void*)get_ammoInClip, (void**)&old_get_ammoInClip);
C++:
int(*old_get_ammoInClip)(void *instance);
int get_ammoInClip(void *instance)
{
if(instance != NULL)
{
void *AccessCharacterController = *(void**)((uint64_t)instance + 0x32); // Use the field and make a pointer to get access to CharacterController
if(AccessCharacterController != NULL) // Since we use a pointer for the field 0x32 to get access to the CharacterController class, we have to check if it isn't null
{
bool IsBot = *(bool*)((uint64_t)AccessCharacterController + 0x24); // use it to access the field isBot in the class CharacterController
if(!IsBot) // Check if it's not a bot
{
return 99999; // Now only you get 99999 ammo
}
}
}
return old_get_ammoInClip(instance); // Return original value for bots
}
MsHookFunction((void*)getAbsoluteAddress(0x34287), (void*)get_ammoInClip, (void**)&old_get_ammoInClip);
Edit: I forgot to show how to connect them to a toggle, but here's how:
(I am gonna do this on the 2nd example)
Make a bool for your hack in the bools section and set it to false (After the Memory Patches struct):
C++:
bool autowin = false;
C++:
OBFUSCATE("24_Toggle_Auto Win"),
C++:
int (*ownerIDNumber)(void *instance);
int (*playerIDNumber)(void *instance);
bool (*old_isDead)(void *instance);
bool isDead(void *instance)
{
if(instance != NULL && autowin) // Only turn on the feature if the toggle is turned on
{
int OwnerID = ownerIDNumber(instance);
int PlayerID = playerIDNumber(instance);
if(OwnerID != PlayerID)
{
return true;
}
}
return old_isDead(instance);
}
MsHookFunction((void*)getAbsoluteAddress(0x832BC29), (void*)isDead, (void**)&old_isDead);
ownerIDNumber = (int (*)(void*))getAbsoluteAddress(targetLibName, 0x832C39);
playerIDNumber = (int (*)(void*))getAbsoluteAddress(targetLibName, 0x3279BC);
C++:
case 24: // The case number is based on the your feature's number, in my case, it was a toggle and I assigned 24 to it
autowin = !autowin;
break;
That's it!
Credits:
~@SecretMyAss (His examples helped me a lot)
~Me (Used his examples and made ones suitable for Android)
~Check out Andnixsh's source codes
Last edited: