case 5:
if(playerDataManager) {
AddGem(playerDataManager, 1000, nullptr, nullptr);
}
break;
void(*old_PlayerDataManager_Initialize)(void *instance);
void PlayerDataManager_Initialize(void *instance) {
old_PlayerDataManager_Initialize(instance);
playerDataManager = instance;
//AddGem(instance, 100000, nullptr, nullptr);
}
HOOK("0xE0A634", PlayerDataManager_Initialize, old_PlayerDataManager_Initialize);
AddGem = (void(*)(void*, u_long, void*, void*))getAbsoluteAddress(targetLibName, 0xE0D2DC);
Strangely, this also exactly happened to me. Seems like the object is protected from read / write when the initialization is finished
Maybe u can read this, he explained somewhere thereARM64 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 #include "Includes/Utils.h" typedef struct _monoString { void *klass; void *monitor; int length...platinmods.com
#include <cstdint>
void* playerDataManager = nullptr;
uint32_t playerDataManager_gcHandle = -1;
// Make sure to get the addresses or offsets of these functions.
void* (*il2cpp_domain_get)(); // Gets the current IL2CPP domain and returns it. Use it for il2cpp_thread_attach.
void* (*il2cpp_thread_attach)(void* domain); // Attaches the current thread to the IL2CPP domain and returns the thread object. Use it for il2cpp_thread_detach. Do not call in a hooked function.
void (*il2cpp_thread_detach)(void* thread); // Detaches the current thread from the IL2CPP domain. Do not call in a hooked function.
uint32_t (*il2cpp_gchandle_new)(void* object, bool weak); // Prevents the object from being garbage collected and returns the handle for it. Use the return value for il2cpp_gchandle_free.
void (*il2cpp_gchandle_free)(uint32_t gchandle); // Allows the object to be garbage collected. Call with the gchandle received from il2cpp_gchandle_new
void (*old_PlayerDataManager_Initialize)(void* instance);
void PlayerDataManager_Initialize(void* instance) {
old_PlayerDataManager_Initialize(instance);
if (instance) { // check for nullptr
if (playerDataManager_gchandle != -1) // make sure the handle is valid
il2cpp_gchandle_free(playerDataManager_gchandle); // a new PlayerDataManager is being initialized, get rid of the old one.
playerDataManager_gchandle = il2cpp_gchandle_new(instance, false); // create a new handle so that the object doesn't get deleted
playerDataManager = instance;
}
}
void ButtonClicked() {
void* thread = il2cpp_thread_attach(il2cpp_domain_get());
AddGem(playerDataManager, 1000, nullptr, nullptr);
il2cpp_thread_detach(thread);
}
It's probably due to IL2CPP garbage collecting the object and deleting it if it detects that no Managed code is using it. You can use the IL2CPP API functions il2cpp_gchandle_new and il2cpp_gchandle_free to make sure it doesn't get garbage collected. Here's an example:
If possible, try to post a link to the game so I can try to help.C++:#include <cstdint> void* playerDataManager = nullptr; uint32_t playerDataManager_gcHandle = -1; // Make sure to get the addresses or offsets of these functions. void* (*il2cpp_domain_get)(); // Gets the current IL2CPP domain and returns it. Use it for il2cpp_thread_attach. void* (*il2cpp_thread_attach)(void* domain); // Attaches the current thread to the IL2CPP domain and returns the thread object. Use it for il2cpp_thread_detach. Do not call in a hooked function. void (*il2cpp_thread_detach)(void* thread); // Detaches the current thread from the IL2CPP domain. Do not call in a hooked function. uint32_t (*il2cpp_gchandle_new)(void* object, bool weak); // Prevents the object from being garbage collected and returns the handle for it. Use the return value for il2cpp_gchandle_free. void (*il2cpp_gchandle_free)(uint32_t gchandle); // Allows the object to be garbage collected. Call with the gchandle received from il2cpp_gchandle_new void (*old_PlayerDataManager_Initialize)(void* instance); void PlayerDataManager_Initialize(void* instance) { old_PlayerDataManager_Initialize(instance); if (instance) { // check for nullptr if (playerDataManager_gchandle != -1) // make sure the handle is valid il2cpp_gchandle_free(playerDataManager_gchandle); // a new PlayerDataManager is being initialized, get rid of the old one. playerDataManager_gchandle = il2cpp_gchandle_new(instance, false); // create a new handle so that the object doesn't get deleted playerDataManager = instance; } } void ButtonClicked() { void* thread = il2cpp_thread_attach(il2cpp_domain_get()); AddGem(playerDataManager, 1000, nullptr, nullptr); il2cpp_thread_detach(thread); }
It's probably due to IL2CPP garbage collecting the object and deleting it if it detects that no Managed code is using it. You can use the IL2CPP API functions il2cpp_gchandle_new and il2cpp_gchandle_free to make sure it doesn't get garbage collected. Here's an example:
If possible, try to post a link to the game so I can try to help.C++:#include <cstdint> void* playerDataManager = nullptr; uint32_t playerDataManager_gcHandle = -1; // Make sure to get the addresses or offsets of these functions. void* (*il2cpp_domain_get)(); // Gets the current IL2CPP domain and returns it. Use it for il2cpp_thread_attach. void* (*il2cpp_thread_attach)(void* domain); // Attaches the current thread to the IL2CPP domain and returns the thread object. Use it for il2cpp_thread_detach. Do not call in a hooked function. void (*il2cpp_thread_detach)(void* thread); // Detaches the current thread from the IL2CPP domain. Do not call in a hooked function. uint32_t (*il2cpp_gchandle_new)(void* object, bool weak); // Prevents the object from being garbage collected and returns the handle for it. Use the return value for il2cpp_gchandle_free. void (*il2cpp_gchandle_free)(uint32_t gchandle); // Allows the object to be garbage collected. Call with the gchandle received from il2cpp_gchandle_new void (*old_PlayerDataManager_Initialize)(void* instance); void PlayerDataManager_Initialize(void* instance) { old_PlayerDataManager_Initialize(instance); if (instance) { // check for nullptr if (playerDataManager_gchandle != -1) // make sure the handle is valid il2cpp_gchandle_free(playerDataManager_gchandle); // a new PlayerDataManager is being initialized, get rid of the old one. playerDataManager_gchandle = il2cpp_gchandle_new(instance, false); // create a new handle so that the object doesn't get deleted playerDataManager = instance; } } void ButtonClicked() { void* thread = il2cpp_thread_attach(il2cpp_domain_get()); AddGem(playerDataManager, 1000, nullptr, nullptr); il2cpp_thread_detach(thread); }
We use cookies to personalize content and ads, to provide social media features and to analyse our traffic. We also share necessary information with our advertising and analytics partners to optimize your experience on our site.
Learn more about cookies
We use cookies to personalize content and ads, to provide social media features and to analyse our traffic. We also share necessary information with our advertising and analytics partners to optimize your experience on our site.
Learn more about cookies