This is the AMP version of this page.
If you want to load the real page instead, click this text.

Tutorial ARM64 Unity String Function Hooking LGL Menu

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;



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);




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.


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);



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 :



add the cases:


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:
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;
 
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.
 
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
 
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() { }
 
ezz bro

C++:
monoString *(*old_function)(void *instance);
monoString *new_function(void *instance) {
  if (ins != NULL) {
    return CreateMonoString("Text Here");
  }
}
Will that hook type work for this?

// RVA: 0x1C36E84 Offset: 0x1C36E84 VA: 0x1C36E84
private string GetTrackSceneName() { }