/*
* Credits:
*
* Octowolve - Mod menu: https://github.com/z3r0Sec/Substrate-Template-With-Mod-Menu
* And hooking: https://github.com/z3r0Sec/Substrate-Hooking-Example
* VanHoevenTR A.K.A Nixi: https://github.com/LGLTeam/VanHoevenTR_Android_Mod_Menu
* MrIkso - Mod menu: https://github.com/MrIkso/FloatingModMenu
* Rprop - https://github.com/Rprop/And64InlineHook
* MJx0 A.K.A Ruit - KittyMemory: https://github.com/MJx0/KittyMemory
* */
#include <list>
#include <vector>
#include <string.h>
#include <pthread.h>
#include <cstring>
#include <jni.h>
#include <unistd.h>
#include <fstream>
#include <iostream>
#include "Includes/obfuscate.h"
#include "KittyMemory/MemoryPatch.h"
#include "Includes/Logger.h"
#include "Includes/Utils.h"
#include "Menu.h"
#if defined(__aarch64__) //Compile for arm64 lib only
#include <And64InlineHook/And64InlineHook.hpp>
#else //Compile for armv7 lib only. Do not worry about greyed out highlighting code, it still works
#include <Substrate/SubstrateHook.h>
#include <Substrate/CydiaSubstrate.h>
#endif
struct My_Patches {
MemoryPatch Tutorial;
} hexPatches;
bool feature1 = false, feature2 = false, featureHookToggle = false;
//Target lib here
#define targetLibName OBFUSCATE("libil2cpp.so")
// Hooking example
//Обычный Хук
bool (*old_DefaultHook)(void *instance);
bool DefaultHook(void *instance) {
if (feature2) { //Привязка функции к кнопке
return true; //На что изменяется оффсет. Пример - true, false, 9999.
}
return old_DefaultHook(instance);
}
//Хук Поля
void (*old_Tutorial)(void *instance);
void Tutorial(void *instance) {
if (feature2) { //Подключение к кнопке
*(float *) ((uint64_t) instance + 0x54) = 150; // После = значение на которое изменяется поле
}
return old_Tutorial(instance);
}
//Хук Параметров
void (*old_Parameters)(void *instance, float health, float armor, bool isGod, float shieldDuration);
void Parameters(void *instance, float health, float armor, bool isGod, float shieldDuration) {
if (instance != NULL) {
if (feature2) { //Подключение к кнопке
armor = 9999.0f;
}
}
return old_Parameters(instance, health, armor, isGod, shieldDuration);
}
void *hack_thread(void *) {
LOGI(OBFUSCATE("pthread created"));
do {
sleep(1);
} while (!isLibraryLoaded(targetLibName));
LOGI(OBFUSCATE("%s has been loaded"), (const char *) targetLibName);
#if defined(__aarch64__) //Compile for arm64 lib only
#else //Compile for armv7 lib only. Do not worry about greyed out highlighting code, it still works
MSHookFunction((void *) getAbsoluteAddress(targetLibName, 0x1A33FD4), (void *) Parameters,
(void **) &old_Parameters);
MSHookFunction((void *) getAbsoluteAddress(targetLibName, 0x121E6B4), (void *) Tutorial,
(void **) &old_Tutorial);
MSHookFunction((void *) getAbsoluteAddress(targetLibName, 0x90D5D8), (void *) DefaultHook,
(void **) &old_DefaultHook);
// Имя старой переменной Библиотека Оффсет Переменная
LOGI(OBFUSCATE("Done"));
#endif
return NULL;
}
//JNI calls
extern "C" {
JNIEXPORT void JNICALL
Java_uk_lgl_MainActivity_Toast(JNIEnv *env, jclass obj, jobject context) {
MakeToast(env, context, OBFUSCATE("Hooking Tutorial"), Toast::LENGTH_LONG);
}
JNIEXPORT jobjectArray
JNICALL
Java_uk_lgl_modmenu_FloatingModMenuService_getFeatureList(JNIEnv *env, jobject activityObject) {
jobjectArray ret;
const char *features[] = {
OBFUSCATE("Category_Hook Tutorial"), //Not counted
OBFUSCATE("Toggle_KittyMemory Example"), //Starts with 0
OBFUSCATE("Toggle_MSHook Example"), //1
};
//Now you dont have to manually update the number everytime;
int Total_Feature = (sizeof features / sizeof features[0]);
ret = (jobjectArray)
env->NewObjectArray(Total_Feature, env->FindClass(OBFUSCATE("java/lang/String")),
env->NewStringUTF(""));
for (int i = 0; i < Total_Feature; i++)
env->SetObjectArrayElement(ret, i, env->NewStringUTF(features[i]));
pthread_t ptid;
pthread_create(&ptid, NULL, antiLeech, NULL);
return (ret);
}
JNIEXPORT void JNICALL
Java_uk_lgl_modmenu_Preferences_Changes(JNIEnv *env, jclass clazz, jobject obj,
jint featNum, jstring featName, jint value,
jboolean boolean, jstring str) {
//Convert java string to c++
const char *featureName = env->GetStringUTFChars(featName, 0);
const char *TextInput;
if (str != NULL)
TextInput = env->GetStringUTFChars(str, 0);
else
TextInput = "Empty";
LOGD(OBFUSCATE("Feature name: %d - %s | Value: = %d | Bool: = %d | Text: = %s"), featNum,
featureName, value,
boolean, TextInput);
switch (featNum) {
case 0:
feature1 = boolean;
break;
case 1:
feature2 = boolean;
break;
}
}
}
//No need to use JNI_OnLoad, since we don't use JNIEnv
//We do this to hide OnLoad from disassembler
__attribute__((constructor))
void lib_main() {
// Create a new thread so it does not block the main thread, means the game would not freeze
pthread_t ptid;
pthread_create(&ptid, NULL, hack_thread, NULL);
}
/*
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *globalEnv;
vm->GetEnv((void **) &globalEnv, JNI_VERSION_1_6);
return JNI_VERSION_1_6;
}
*/