diff --git a/main.cpp b/main.cpp index 57dba1b3f..cd3f5df47 100644 --- a/main.cpp +++ b/main.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include "dobby.h" #include "imgui.h" #include "imgui_impl_android.h" @@ -17,59 +16,45 @@ static bool g_Initialized = false; static bool g_ShowMenu = true; -// 状态追踪日志,用于在 UI 上显示 -static char g_HookStatus[256] = "Waiting..."; +// 触摸状态全局变量 +struct { + float x; + float y; + bool down; + int count; +} g_TouchData = {0, 0, false, 0}; typedef EGLBoolean (*p_eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface); static p_eglSwapBuffers old_eglSwapBuffers = nullptr; -// --- 触摸数据结构 --- -struct TouchState { - float x; - float y; - bool down; - int event_count; // 记录收到了多少次事件 -} g_Touch; +// --- 针对 Unity 绕过导出的最强 Hook 方案 --- -// --- 核心 Hook 逻辑 --- +typedef int32_t (*p_AInputQueue_getEvent)(AInputQueue* queue, AInputEvent** outEvent); +static p_AInputQueue_getEvent old_getEvent = nullptr; -typedef float (*p_AMotionEvent_getRawX)(const AInputEvent* motion_event, size_t pointer_index); -static p_AMotionEvent_getRawX old_getRawX = nullptr; - -typedef float (*p_AMotionEvent_getRawY)(const AInputEvent* motion_event, size_t pointer_index); -static p_AMotionEvent_getRawY old_getRawY = nullptr; - -typedef int32_t (*p_AMotionEvent_getAction)(const AInputEvent* motion_event); -static p_AMotionEvent_getAction old_getAction = nullptr; - -float hook_AMotionEvent_getRawX(const AInputEvent* motion_event, size_t pointer_index) { - float x = old_getRawX(motion_event, pointer_index); - if (g_ShowMenu && g_Initialized && pointer_index == 0) { - g_Touch.x = x; - g_Touch.event_count++; - } - return x; -} - -float hook_AMotionEvent_getRawY(const AInputEvent* motion_event, size_t pointer_index) { - float y = old_getRawY(motion_event, pointer_index); - if (g_ShowMenu && g_Initialized && pointer_index == 0) { - g_Touch.y = y; - } - return y; -} - -int32_t hook_AMotionEvent_getAction(const AInputEvent* motion_event) { - int32_t action = old_getAction(motion_event); - if (g_ShowMenu && g_Initialized) { - int32_t code = action & AMOTION_EVENT_ACTION_MASK; - if (code == AMOTION_EVENT_ACTION_DOWN || code == AMOTION_EVENT_ACTION_POINTER_DOWN) { - g_Touch.down = true; - } else if (code == AMOTION_EVENT_ACTION_UP || code == AMOTION_EVENT_ACTION_POINTER_UP || code == AMOTION_EVENT_ACTION_CANCEL) { - g_Touch.down = false; +int32_t hook_AInputQueue_getEvent(AInputQueue* queue, AInputEvent** outEvent) { + int32_t res = old_getEvent(queue, outEvent); + if (res >= 0 && outEvent && *outEvent) { + AInputEvent* event = *outEvent; + int32_t type = AInputEvent_getType(event); + + if (type == AINPUT_EVENT_TYPE_MOTION) { + int32_t action = AMotionEvent_getAction(event); + int32_t code = action & AMOTION_EVENT_ACTION_MASK; + + // 直接在这里调用系统函数读取(即使 Unity 自己不调用,我们可以在 Hook 里主动读) + g_TouchData.x = AMotionEvent_getX(event, 0); + g_TouchData.y = AMotionEvent_getY(event, 0); + + if (code == AMOTION_EVENT_ACTION_DOWN || code == AMOTION_EVENT_ACTION_POINTER_DOWN) { + g_TouchData.down = true; + } else if (code == AMOTION_EVENT_ACTION_UP || code == AMOTION_EVENT_ACTION_POINTER_UP || code == AMOTION_EVENT_ACTION_CANCEL) { + g_TouchData.down = false; + } + g_TouchData.count++; } } - return action; + return res; } // 渲染钩子 @@ -88,33 +73,31 @@ EGLBoolean hook_eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { ImGui_ImplOpenGL3_Init("#version 300 es"); g_Initialized = true; - LOGI("ImGui Initialized successfully."); + LOGI("ImGui Initialized: %d x %d", width, height); } if (g_ShowMenu) { + // 【核心】在渲染前强行同步触摸状态 ImGuiIO& io = ImGui::GetIO(); - io.MousePos = ImVec2(g_Touch.x, g_Touch.y); - io.MouseDown[0] = g_Touch.down; + io.MousePos = ImVec2(g_TouchData.x, g_TouchData.y); + io.MouseDown[0] = g_TouchData.down; ImGui_ImplOpenGL3_NewFrame(); ImGui::NewFrame(); ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver); - ImGui::SetNextWindowSize(ImVec2(600, 450), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver); if (ImGui::Begin("AndKitty SGame Debugger", &g_ShowMenu)) { - ImGui::TextColored(ImVec4(1, 1, 0, 1), "Hook Status: %s", g_HookStatus); - ImGui::Text("Touch Data: %s (%.1f, %.1f)", g_Touch.down ? "DOWN" : "UP", g_Touch.x, g_Touch.y); - ImGui::Text("Total Events Captured: %d", g_Touch.event_count); - + ImGui::Text("Captured: %d", g_TouchData.count); + ImGui::Text("Pos: %.1f, %.1f", g_TouchData.x, g_TouchData.y); + ImGui::Text("Status: %s", g_TouchData.down ? "DOWN" : "UP"); ImGui::Separator(); - if (ImGui::Button("Reset Touch State")) { - g_Touch.down = false; - g_Touch.event_count = 0; - } - - ImGui::Checkbox("Menu Visible", &g_ShowMenu); + static bool test = false; + ImGui::Checkbox("Test Feature", &test); + + if (ImGui::Button("Close Menu")) g_ShowMenu = false; } ImGui::End(); @@ -126,44 +109,27 @@ EGLBoolean hook_eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { } void* init_thread(void*) { - LOGI("Init thread started. Target: libunity.so"); - - // 持续检查模块加载情况 - int retry = 0; - while (retry < 60) { // 最多等待 30 秒 - if (dlopen("libunity.so", RTLD_NOLOAD)) { - LOGI("libunity.so found!"); - break; - } - usleep(500000); - retry++; - } + // 既然日志显示 08:57 已经加载了 libunity.so,我们缩短等待 + sleep(5); // 1. Hook 渲染 void* swap_addr = dlsym(RTLD_DEFAULT, "eglSwapBuffers"); - if (swap_addr) { - DobbyHook(swap_addr, (void*)hook_eglSwapBuffers, (void**)&old_eglSwapBuffers); - LOGI("eglSwapBuffers Hooked."); - } else { - LOGI("FAILED to find eglSwapBuffers"); + if (swap_addr) DobbyHook(swap_addr, (void*)hook_eglSwapBuffers, (void**)&old_eglSwapBuffers); + + // 2. Hook AInputQueue_getEvent + // 它是 Unity 拿事件的总阀门,不管 Unity 内部怎么读,只要它拿了,我们就拦 + void* getEvent_addr = dlsym(RTLD_DEFAULT, "AInputQueue_getEvent"); + if (!getEvent_addr) { + void* h_android = dlopen("libandroid.so", RTLD_NOW); + if (h_android) getEvent_addr = dlsym(h_android, "AInputQueue_getEvent"); } - // 2. Hook 触摸 - void* getRawX_addr = dlsym(RTLD_DEFAULT, "AMotionEvent_getRawX"); - void* getRawY_addr = dlsym(RTLD_DEFAULT, "AMotionEvent_getRawY"); - void* getAction_addr = dlsym(RTLD_DEFAULT, "AMotionEvent_getAction"); - - if (getRawX_addr && getRawY_addr && getAction_addr) { - DobbyHook(getRawX_addr, (void*)hook_AMotionEvent_getRawX, (void**)&old_getRawX); - DobbyHook(getRawY_addr, (void*)hook_AMotionEvent_getRawY, (void**)&old_getRawY); - DobbyHook(getAction_addr, (void*)hook_AMotionEvent_getAction, (void**)&old_getAction); - snprintf(g_HookStatus, sizeof(g_HookStatus), "All Hooks OK (Unity Mode)"); - LOGI("AMotionEvent Hooks applied successfully."); - } else { - snprintf(g_HookStatus, sizeof(g_HookStatus), "Hook FAILED: %p %p %p", getRawX_addr, getRawY_addr, getAction_addr); - LOGI("FAILED to find AMotionEvent symbols."); + if (getEvent_addr) { + LOGI("Hooking AInputQueue_getEvent..."); + DobbyHook(getEvent_addr, (void*)hook_AInputQueue_getEvent, (void**)&old_getEvent); } + LOGI("New Hook Strategy Applied."); return nullptr; }