#include <cstdint>
#include <cstdio>
#include <cstring>
#include <pthread.h>
#include <dlfcn.h>
#include <unistd.h>
#include <sys/mman.h>
#include <android/log.h>
#define LOG_TAG "ToramHook"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
// And64InlineHook header - include in project folder
#include "And64InlineHook.hpp"
// ========== RESOLVE OFFSETS ==========
uintptr_t getLibBase(const char* libName) {
FILE* maps = fopen("/proc/self/maps", "r");
if (!maps) return 0;
char line[512];
uintptr_t base = 0;
while (fgets(line, sizeof(line), maps)) {
if (strstr(line, libName) && strstr(line, "r-xp")) {
base = strtoul(line, nullptr, 16);
break;
}
}
fclose(maps);
return base;
}
uintptr_t resolveRVA(uintptr_t base, uint32_t rva) {
return base + rva;
}
// ========== ORIGINAL FUNCTION POINTERS ==========
typedef void (*OnHackDetected_t)(void* instance, int32_t code, void* info);
static OnHackDetected_t original_OnHackDetected = nullptr;
typedef void* (*onHackDetectedCoroutine_t)(void* instance);
static onHackDetectedCoroutine_t original_onHackDetected = nullptr;
typedef void (*PopHackWindow_t)(void* instance);
static PopHackWindow_t original_PopHackWindow = nullptr;
typedef void (*UncheaterHackAppQuit_t)(void* instance);
static UncheaterHackAppQuit_t original_UncheaterHackAppQuit = nullptr;
// ========== HOOK FUNCTIONS ==========
void hook_OnHackDetected(void* instance, int32_t code, void* info) {
LOGD("[BLOCKED] OnHackDetected called - code: %d", code);
// Does NOT call original - blocks detection
}
void* hook_onHackDetectedCoroutine(void* instance) {
LOGD("[BLOCKED] onHackDetected coroutine blocked");
return nullptr;
}
void hook_PopHackWindow(void* instance) {
LOGD("[BLOCKED] PopHackWindow blocked");
}
void hook_UncheaterHackAppQuit(void* instance) {
LOGD("[BLOCKED] UncheaterHackAppQuit blocked");
}
// ========== SCAN XIGNCODE PROCESS ==========
void killXigncode() {
DIR* dir;
struct dirent* entry;
char path[512];
dir = opendir("/proc");
if (!dir) return;
while ((entry = readdir(dir))) {
if (entry->d_type == DT_DIR) {
int pid = atoi(entry->d_name);
if (pid <= 0) continue;
char cmdline[256];
snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", pid);
FILE* f = fopen(cmdline, "r");
if (f) {
char name[256] = {0};
fgets(name, sizeof(name), f);
fclose(f);
if (strstr(name, "xigncode") || strstr(name, "Xigncode") ||
strstr(name, "XIGNCODE") || strstr(name, "x3")) {
LOGD("Found Xigncode process: %s (PID: %d)", name, pid);
kill(pid, SIGSTOP); // Pauses the process (doesn't kill, just freezes)
LOGD("Xigncode process frozen: %d", pid);
}
}
}
}
closedir(dir);
}
// ========== INIT ==========
void* thread_main(void*) {
sleep(5); // Wait for game to load
uintptr_t libBase = getLibBase("libil2cpp.so");
if (!libBase) {
LOGD("Failed to find libil2cpp.so");
return nullptr;
}
LOGD("libil2cpp base: 0x%lx", libBase);
// Freeze Xigncode first
killXigncode();
// Apply hooks at runtime (binary is not modified)
A64HookFunction(
(void*)resolveRVA(libBase, 0x15d786c),
(void*)hook_PopHackWindow,
(void**)&original_PopHackWindow
);
A64HookFunction(
(void*)resolveRVA(libBase, 0xed3afc),
(void*)hook_UncheaterHackAppQuit,
(void**)&original_UncheaterHackAppQuit
);
A64HookFunction(
(void*)resolveRVA(libBase, 0x8eef5c),
(void*)hook_OnHackDetected,
(void**)&original_OnHackDetected
);
A64HookFunction(
(void*)resolveRVA(libBase, 0x8edfa0),
(void*)hook_onHackDetectedCoroutine,
(void**)&original_onHackDetected
);
LOGD("All hooks applied successfully!");
return nullptr;
}
__attribute__((constructor))
void init() {
pthread_t t;
pthread_create(&t, nullptr, thread_main, nullptr);
pthread_detach(t);
}[/CÓDIGO]
Android.mk:
[CODE]LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := toramhook
LOCAL_SRC_FILES := main.cpp
LOCAL_CFLAGS := -std=c++11 -Ofast
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)