Tutorial ARM64 Unity String Function Hooking LGL Menu

xxbatman9898

Rookie
Original poster
Apr 25, 2020
4
8
3
25
Australia
Hooking string functions for libil2cpp games is a little different than hooking int or bool functions because unity uses a different type of string.

Create a header file e.g. Strings.h

C++:
#include "Includes/Utils.h"
typedef struct _monoString {
    void *klass;
    void *monitor;
    int length;
    char chars[1];

    int getLength() {
        return length;
    }

    char *getChars() {
        return chars;
    }
} monoString;
Capture.PNG


Paste this code into it. This is a typedef so we can handle mono string types.

Now inside of your Main.cpp include this header

C++:
#include "Includes/Strings.h" // location relative to Main.cpp if its in a higher hiarchy use "../"

Now inside Main.cpp create your function pointers I put mine just below the My_Patches struct.

C++:
monoString *(*String_CreateString)(void *_this, const char *str);
void (*get_StringInstance);
Capture.PNG



Now inside your hackthread function assign your String_CreateString and get_StringInstance.

C++:
String_CreateString = (monoString*(*)(void *,const char *))getAbsoluteAddress(targetLibName, 0x1646CA0);
   get_StringInstance  = (void (*))getAbsoluteAddress(targetLibName,0x1646CA0);
To find the offsets Search in your dump.cs for a createstring method, which takes in only one variable called sbyte* value.
Capture.PNG


put that offset in both get_StringInstance and String_CreateString.


now you can hook string functions.

here is a hook for function.

First we hook the update function in the playercontroller class.
then inside that class is a function Debug_MoveToPointImmediate which takes a monostring parameter.

C++:
void (*Debug_MoveToPointImmediate)(void *instance, monoString * PointID);
bool MoveToCastle = false;
bool MoveToHome = false;
void(* old_UpdateMap)(void * instance);
void UpdateMap(void*instance) {
    if(instance != NULL ) {
       if(MoveToCastle) {
           MoveToCastle = false;
           Debug_MoveToPointImmediate(instance,String_CreateString(get_StringInstance,"castle"));
       }
        if(MoveToHome) {
            MoveToHome = false;
            Debug_MoveToPointImmediate(instance,String_CreateString(get_StringInstance,"home"));
        }

    }
    old_UpdateMap(instance);
}
when passing the string into the parameter use String_CreateString(get_StringInstance,"string you want to pass")

now we assign the pointer function and hook the player update inside the hackthread.
C++:
A64HookFunction((void*)getAbsoluteAddress(targetLibName, 0x19DDDD4),  (void*)UpdateMap, (void**)&old_UpdateMap);
Debug_MoveToPointImmediate = (void (*)(void *,monoString *))getAbsoluteAddress(targetLibName, 0x19E07A4);
Capture.PNG


and your done. You can use the String_CreateString(get_StringInstance,"string you want to pass") in any function which takes a string. If its a string returning function you could use
return String_CreateString(get_StringInstance,"string you want to return").

connecting to a button is simple.

add the features :
Capture.PNG



add the cases:
Capture.PNG


Because the function is in a update that is called 60 times per second, we set it to true when the button is clicked and then inside the update function set it to false once it is run. This is so it isn't called more than once. you would do this differently if it was a function you want to keep being called like a toggle function.
 
Last edited:

Meepoooo

Platinian
May 9, 2022
12
2
3
39
Viet Nam
Plz help me about hook string unity game
my code:

C++:
/* Dump::
    RVA: hixx Offset: 0x1060E00 VA: 0x1060E00
    private void room_update() { }

    // RVA: 0x10610B0 Offset: 0x10610B0 VA: 0x10610B0 Slot: 24
    protected override void OnEnterDoorBefore() { }

    // RVA: 0x1061310 Offset: 0x1061310 VA: 0x1061310 Slot: 25
    protected override void OnEnterDoorAfter() { }

    // RVA: 0x1061314 Offset: 0x1061314 VA: 0x1061314 Slot: 26
    protected override string OnGetTmxID(int roomid) { }
*/
monoString *(*String_CreateString)(void *_this, const char *str);
void (*get_StringInstance);

bool istele;
const char *TeleValue = NULL;
void (*Debug_MoveToPointImmediate)(void *instance, monoString * PointID);
void(* old_UpdateRoom)(void * instance);
void UpdateRoom(void*instance) {
    if(instance != NULL) {
        if(istele) {
            istele = false;
            Debug_MoveToPointImmediate(instance,String_CreateString(get_StringInstance, TeleValue));
        }
    }
    old_UpdateRoom(instance);
}

    String_CreateString = (monoString*(*)(void *,const char *))getAbsoluteAddress(targetLibName, 0x1DE7378);
    get_StringInstance  = (void (*))getAbsoluteAddress(targetLibName,0x1DE7378);
    
    MSHookFunction((void*)getAbsoluteAddress(targetLibName, 0x1113008),  (void*)UpdateRoom, (void**)&old_UpdateRoom);
    Debug_MoveToPointImmediate = (void (*)(void *,monoString *))getAbsoluteAddress(targetLibName, 0x111351C);
    
    OBFUSCATE("13_InputValue_Input Tele Number"),
    
    case 13:
    istele = true;
    TeleValue = reinterpret_cast<const char *>(value);
    break;
 

Kaorin333

Solid & Active Platinian
Jun 11, 2022
89
9
8
34
Germany
Could be there anything different now cause when im trying to print

C++:
[Address(RVA = "0x2612AA4", Offset = "0x2612AA4", VA = "0x2612AA4")]
public static string get_version()
{
    return null;
}
Mod_Menu: Version: ÇI^╝
 

Lop_A1254

Platinian
Oct 12, 2020
9
1
3
Belgium
Could be there anything different now cause when im trying to print

C++:
[Address(RVA = "0x2612AA4", Offset = "0x2612AA4", VA = "0x2612AA4")]
public static string get_version()
{
    return null;
}
Mod_Menu: Version: ÇI^╝
I believe that this is a case of inproper termination. Something is wrong with the way you inputted your string.
 

Wumble

Rookie
May 31, 2022
3
0
1
25
N/A
Previously I've learned to unlink
How can I change the string like below?

private string color; // 0xB0

Sorry I use google translate and thanks in advance
 

plengyt

Rookie
Dec 2, 2021
2
1
3
27
INDONESIA
Please help me how hooking this bro🙏🙏🙏

C++:
// Namespace:
public class CustomizeViewController : MonoBehaviour // TypeDefIndex: 7985
{
    // Fields
    private string skinID; // 0x18


    // RVA: 0x6A987C Offset: 0x6A987C VA: 0x6A987C
    public void OnSkinUseButton() { }
 
  • Like
Reactions: Aamin