From 7c5152685c990c321cee7911fde60d4c33ba2cb7 Mon Sep 17 00:00:00 2001 From: guoh064 <50830808+guoh064@users.noreply.github.com> Date: Wed, 28 Jan 2026 11:53:21 +0800 Subject: [PATCH] Fix: crack ui on tencent.blhx (#3) --- blcrack/cracker/il2cpp.hpp | 1 + blcrack/cracker/server.hpp | 1 + blcrack/cracker/ui/hook.cpp | 119 ++++++++++++++++-------------------- 3 files changed, 55 insertions(+), 66 deletions(-) diff --git a/blcrack/cracker/il2cpp.hpp b/blcrack/cracker/il2cpp.hpp index 289930132..1d147de2b 100644 --- a/blcrack/cracker/il2cpp.hpp +++ b/blcrack/cracker/il2cpp.hpp @@ -174,6 +174,7 @@ extern "C" { Il2CppImage* il2cpp_assembly_get_image(Il2CppAssembly *assembly); Il2CppClass* il2cpp_class_from_name(Il2CppImage* image, const char* namespaze, const char *name); MethodInfo* il2cpp_class_get_method_from_name(Il2CppClass *klass, const char* name, int argsCount); + void* il2cpp_resolve_icall(const char* name); } #endif //IL2CPPSTRUCT_HPP diff --git a/blcrack/cracker/server.hpp b/blcrack/cracker/server.hpp index 2b8d9b004..e1faa05ed 100644 --- a/blcrack/cracker/server.hpp +++ b/blcrack/cracker/server.hpp @@ -1,6 +1,7 @@ #ifndef SERVER_HPP #define SERVER_HPP +#include #include #include #include diff --git a/blcrack/cracker/ui/hook.cpp b/blcrack/cracker/ui/hook.cpp index 6364a10a2..c095a218c 100644 --- a/blcrack/cracker/ui/hook.cpp +++ b/blcrack/cracker/ui/hook.cpp @@ -133,11 +133,15 @@ bool has_hooked = false; #define TOUCH_PHASE_ENDED 3 #define TOUCH_PHASE_CANCELED 4 +#define IMGUI_EVT_NONE 0 +#define IMGUI_EVT_POS_ONLY 1 +#define IMGUI_EVT_CLICK_HANDLED 2 + int My_ImGui_ImplAndroid_HandleInputEvent(const UnityEngine_Touch_o& touch) { auto x = touch.fields.m_Position.fields.x; auto y = g_height - touch.fields.m_Position.fields.y; if (!ImGui_IsPosInWnd(x, y)) { - return 1; + return IMGUI_EVT_NONE; } auto& io = ImGui::GetIO(); @@ -156,33 +160,38 @@ int My_ImGui_ImplAndroid_HandleInputEvent(const UnityEngine_Touch_o& touch) { io.AddMouseButtonEvent(0, true); io.AddMouseButtonEvent(1, true); io.AddMouseButtonEvent(2, true); - break; + return IMGUI_EVT_CLICK_HANDLED; case TOUCH_PHASE_MOVED: case TOUCH_PHASE_STATIONARY: io.AddMousePosEvent(x, y); - break; + return IMGUI_EVT_POS_ONLY; case TOUCH_PHASE_ENDED: case TOUCH_PHASE_CANCELED: io.AddMousePosEvent(x, y); io.AddMouseButtonEvent(0, false); io.AddMouseButtonEvent(1, false); io.AddMouseButtonEvent(2, false); - break; + return IMGUI_EVT_CLICK_HANDLED; default: - break; + return IMGUI_EVT_NONE; } - return 0; } using GlobalClickEventMgr_HandlePinchOnTouch_fnT = void(void* thiz, UnityEngine_Touch_array* touches); GlobalClickEventMgr_HandlePinchOnTouch_fnT* old_GlobalClickEventMgr_HandlePinchOnTouch = nullptr; void my_GlobalClickEventMgr_HandlePinchOnTouch(void* thiz, UnityEngine_Touch_array* touches) { + bool my_imgui_handled = false; if (touches != nullptr && !g_use_native_input.load() && g_imgui_started.load() && CrackerUI::get_instance().is_ui_showed() && g_need_ui_penetration) { for(int i = 0; i < touches->max_length; i++) { - My_ImGui_ImplAndroid_HandleInputEvent(touches->m_Items[i]); + int r = My_ImGui_ImplAndroid_HandleInputEvent(touches->m_Items[i]); + if (r != IMGUI_EVT_NONE) { + my_imgui_handled = true; + } } } - old_GlobalClickEventMgr_HandlePinchOnTouch(thiz, touches); + if (!my_imgui_handled) { + old_GlobalClickEventMgr_HandlePinchOnTouch(thiz, touches); + } } static GlobalClickEventMgr_HandlePinchOnTouch_fnT* get_GlobalClickEventMgr_HandlePinchOnTouch() { @@ -215,48 +224,29 @@ static GlobalClickEventMgr_HandlePinchOnTouch_fnT* get_GlobalClickEventMgr_Handl return fn; } -using UnityEngine_Input_GetTouch_fnT = UnityEngine_Touch_o*(UnityEngine_Touch_o* ret, int32_t index, void* info); -static UnityEngine_Input_GetTouch_fnT* get_UnityEngine_Input_GetTouch() { - static UnityEngine_Input_GetTouch_fnT* fn = []() { - Il2CppDomain* domain = il2cpp_domain_get(); - size_t assembly_count = 0; - Il2CppAssembly** assemblies = il2cpp_domain_get_assemblies(domain, &assembly_count); - - Il2CppClass* cls = nullptr; - for (size_t i = 0; i < assembly_count; ++i) { - Il2CppImage* image = il2cpp_assembly_get_image(assemblies[i]); - Il2CppClass* klass = il2cpp_class_from_name(image, "UnityEngine", "Input"); - if (klass != nullptr) { - cls = klass; - break; - } +using UnityEngine_Input_GetTouch_Injected_fnT = void(int32_t index, UnityEngine_Touch_o* ret); +static UnityEngine_Input_GetTouch_Injected_fnT* get_UnityEngine_Input_GetTouch_Injected() { + static UnityEngine_Input_GetTouch_Injected_fnT* fn = []() { + auto p = il2cpp_resolve_icall("UnityEngine.Input::GetTouch_Injected(System.Int32,UnityEngine.Touch&)"); + if (p != nullptr) { + SPDLOG_INFO("Found UnityEngine.Input::GetTouch_Injected at {}", p); + return reinterpret_cast(p); } - if (cls != nullptr) { - MethodInfo* method_info = il2cpp_class_get_method_from_name(cls, "GetTouch", 1); - if (method_info != nullptr) { - auto method = reinterpret_cast(method_info->methodPointer); - - SPDLOG_INFO("Found UnityEngine.Input.GetTouch at {}", (void*)method_info->methodPointer); - return method; - } - } - SPDLOG_ERROR("Failed to get UnityEngine.Input.GetTouch"); - throw std::runtime_error("Failed to get UnityEngine.Input.GetTouch"); + SPDLOG_ERROR("Failed to get UnityEngine.Input.GetTouch_Injected"); + throw std::runtime_error("Failed to get UnityEngine.Input.GetTouch_Injected"); }(); return fn; } -UnityEngine_Input_GetTouch_fnT* old_UnityEngine_Input_GetTouch = nullptr; -UnityEngine_Touch_o* my_UnityEngine_Input_GetTouch(UnityEngine_Touch_o* ret, int32_t index, void* info) { - auto touch = old_UnityEngine_Input_GetTouch(ret, index, info); +UnityEngine_Input_GetTouch_Injected_fnT* old_UnityEngine_Input_GetTouch_Injected = nullptr; +void my_UnityEngine_Input_GetTouch_Injected(int32_t index, UnityEngine_Touch_o* ret) { + old_UnityEngine_Input_GetTouch_Injected(index, ret); - if (g_imgui_started.load() && !g_need_ui_penetration && CrackerUI::get_instance().is_ui_showed() && touch != nullptr) { - if (My_ImGui_ImplAndroid_HandleInputEvent(*touch) == 0) { - touch->fields.m_Phase = TOUCH_PHASE_CANCELED; + if (g_imgui_started.load() && !g_need_ui_penetration && CrackerUI::get_instance().is_ui_showed() && ret != nullptr) { + if (My_ImGui_ImplAndroid_HandleInputEvent(*ret) != IMGUI_EVT_NONE) { + ret->fields.m_Phase = TOUCH_PHASE_CANCELED; } } - - return touch; } void do_ui_hook() { @@ -276,12 +266,12 @@ void do_ui_hook() { } dobby_hook_status = DobbyHook( - reinterpret_cast(get_UnityEngine_Input_GetTouch()), - reinterpret_cast(my_UnityEngine_Input_GetTouch), - reinterpret_cast(&old_UnityEngine_Input_GetTouch) + reinterpret_cast(get_UnityEngine_Input_GetTouch_Injected()), + reinterpret_cast(my_UnityEngine_Input_GetTouch_Injected), + reinterpret_cast(&old_UnityEngine_Input_GetTouch_Injected) ); if (dobby_hook_status != 0) { - SPDLOG_INFO("Hook UnityEngine.Input.GetTouch failed: {}", dobby_hook_status); + SPDLOG_INFO("Hook UnityEngine.Input::GetTouch_Injected failed: {}", dobby_hook_status); } has_hooked = true; @@ -343,36 +333,33 @@ int my_lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { } void hook_game_lua_for_ingame_ui() { - int xhook_status = 0; + int dobby_hook_status = 0; - xhook_status = xhook_register( - "libunity", - "eglSwapBuffers", + dobby_hook_status = DobbyHook( + reinterpret_cast(eglSwapBuffers), reinterpret_cast(my_eglSwapBuffers), reinterpret_cast(&old_eglSwapBuffers) ); - if (xhook_status != 0) { - SPDLOG_INFO("Hook eglSwapBuffers failed: {}", xhook_status); + if (dobby_hook_status != 0) { + SPDLOG_INFO("Hook eglSwapBuffers failed: {}", dobby_hook_status); } - xhook_status = xhook_register( - "libtolua", - "luaL_loadbuffer", + dobby_hook_status = DobbyHook( + reinterpret_cast(luaL_loadbuffer), reinterpret_cast(my_luaL_loadbuffer), reinterpret_cast(&old_luaL_loadbuffer) ); - if (xhook_status != 0) { - SPDLOG_INFO("Hook luaL_loadbuffer failed: {}", xhook_status); + if (dobby_hook_status != 0) { + SPDLOG_INFO("Hook luaL_loadbuffer failed: {}", dobby_hook_status); } - xhook_status = xhook_register( - "libtolua", - "lua_pcall", + dobby_hook_status = DobbyHook( + reinterpret_cast(lua_pcall), reinterpret_cast(my_lua_pcall), reinterpret_cast(&old_lua_pcall) ); - if (xhook_status != 0) { - SPDLOG_INFO("Hook lua_pcall failed: {}", xhook_status); + if (dobby_hook_status != 0) { + SPDLOG_INFO("Hook lua_pcall failed: {}", dobby_hook_status); } // xhook_status = xhook_register( @@ -395,8 +382,8 @@ void hook_game_lua_for_ingame_ui() { // SPDLOG_INFO("Hook android::InputConsumer::consume failed: {}", xhook_status); // } - xhook_status = xhook_refresh(1); - if (xhook_status != 0) { - SPDLOG_INFO("XHook commit failed: {}", xhook_status); - } + // xhook_status = xhook_refresh(1); + // if (xhook_status != 0) { + // SPDLOG_INFO("XHook commit failed: {}", xhook_status); + // } } \ No newline at end of file