diff --git a/main.cpp b/main.cpp index 5fa2e4fca..8edb7d44d 100644 --- a/main.cpp +++ b/main.cpp @@ -1,129 +1,77 @@ #include -#include #include #include #include -#include -#include - -#include "dobby.h" -#include "imgui.h" -#include "imgui_impl_android.h" -#include "imgui_impl_opengl3.h" +#include +#include +#include "dobby.h" // 确保项目中有 dobby.h #define TAG "JKMenu_SGame" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) -static bool g_Initialized = false; -static int g_Width = 0; -static int g_Height = 0; - -typedef EGLBoolean (*eglSwapBuffers_t)(EGLDisplay, EGLSurface); -static eglSwapBuffers_t old_eglSwapBuffers = nullptr; - -// 绘制菜单 -void DrawJKMenu() { - if (!ImGui::GetCurrentContext()) return; - - // 设置默认位置和大小(仅第一次) - ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver); - ImGui::SetNextWindowSize(ImVec2(400, 300), ImGuiCond_FirstUseEver); - - ImGui::Begin("JKMenu for SGame", nullptr, ImGuiWindowFlags_None); - ImGui::Text("Build Date: 2026-04-06"); - ImGui::Text("Viewport: %dx%d", g_Width, g_Height); - ImGui::Separator(); - - static bool hack_enabled = false; - if (ImGui::Button("功能开关示例")) { - hack_enabled = !hack_enabled; - } - - ImGui::Text("状态: %s", hack_enabled ? "已开启" : "已关闭"); - - if (ImGui::Button("卸载插件")) { - // 可以在这里写卸载逻辑 - } - - ImGui::End(); -} - -EGLBoolean hook_eglSwapBuffers(EGLDisplay dpy, EGLSurface surf) { - // 获取屏幕分辨率 - eglQuerySurface(dpy, surf, EGL_WIDTH, &g_Width); - eglQuerySurface(dpy, surf, EGL_HEIGHT, &g_Height); - - if (!g_Initialized) { - if (g_Width > 0 && g_Height > 0) { - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); - - // 字体缩放自适应手机高分屏 - io.FontGlobalScale = 2.0f; - - // 初始化渲染后端 - // 注意:在 Hook 环境下不需要调用 ImGui_ImplAndroid_Init - // 因为我们没有 NativeWindow,通常只用 OpenGL3 后端 - ImGui_ImplOpenGL3_Init("#version 300 es"); - - g_Initialized = true; - LOGI("ImGui Initialized! Screen: %dx%d", g_Width, g_Height); +// 模拟你的 Hook 目标(请根据实际偏移修改) +// 假设你要 Hook libUnity.so 或 libGameCore.so +uintptr_t get_module_base(const char* name) { + FILE* fp = fopen("/proc/self/maps", "r"); + char line[1024]; + uintptr_t base = 0; + while (fp && fgets(line, sizeof(line), fp)) { + if (strstr(line, name)) { + base = strtoull(line, NULL, 16); + break; } } - - if (g_Initialized) { - ImGui_ImplOpenGL3_NewFrame(); - ImGuiIO& io = ImGui::GetIO(); - io.DisplaySize = ImVec2((float)g_Width, (float)g_Height); - io.DeltaTime = 1.0f / 60.0f; - - ImGui::NewFrame(); - DrawJKMenu(); - ImGui::Render(); - - // 渲染 ImGui - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - } - - return old_eglSwapBuffers(dpy, surf); + if (fp) fclose(fp); + return base; } void* init_thread(void*) { - LOGI("Thread started, waiting for game load..."); - // 增加延迟确保 libEGL.so 已经完全加载到内存 - sleep(15); - - // 尝试寻找 eglSwapBuffers 地址 - void* egl_addr = dlsym(RTLD_DEFAULT, "eglSwapBuffers"); - if (!egl_addr) { - egl_addr = DobbySymbolResolver("libEGL.so", "eglSwapBuffers"); + LOGI("Thread started, entering monitoring loop..."); + + uintptr_t game_base = 0; + int retry = 0; + + // 1. 等待游戏主核心库加载(王者荣耀通常是 libGameCore.so 或 libunity.so) + while (game_base == 0 && retry < 60) { + game_base = get_module_base("libGameCore.so"); // 尝试获取核心库 + if (game_base == 0) { + if (retry % 5 == 0) LOGI("Waiting for libGameCore.so... (retry %d)", retry); + sleep(1); + retry++; + } } - if (egl_addr) { - LOGI("Found eglSwapBuffers at %p, hooking...", egl_addr); - DobbyHook(egl_addr, (void*)hook_eglSwapBuffers, (void**)&old_eglSwapBuffers); - if (old_eglSwapBuffers) { - LOGI("Hook eglSwapBuffers Success!"); - } else { - LOGE("DobbyHook failed to return original function."); - } - } else { - LOGE("Failed to find eglSwapBuffers!"); + if (game_base == 0) { + LOGE("Error: libGameCore.so not found after 60s, exiting thread."); + return nullptr; } + + LOGI("Found libGameCore.so at: %p", (void*)game_base); + + // 2. 执行 Hook 逻辑 + // 建议先只 Hook 一个最简单的函数测试稳定性 + /* + uintptr_t target_offset = 0x123456; // 你的偏移 + void* target_addr = (void*)(game_base + target_offset); + LOGI("Attempting to Hook at %p", target_addr); + + // DobbyHook(target_addr, (void*)my_fake_func, (void**)&orig_func); + */ + + LOGI("All initialization steps completed."); return nullptr; } -// 当 SO 被 dlopen 加载时自动调用 __attribute__((constructor)) void _init() { pthread_t tid; + // 创建分离线程,防止阻塞导致游戏启动黑屏 pthread_create(&tid, nullptr, init_thread, nullptr); + pthread_detach(tid); } -// 也可以保留 JNI_OnLoad 作为双重保险 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { return JNI_VERSION_1_6; }