From 193c04a24bec08d9162bcab8064ec341c2cc065a Mon Sep 17 00:00:00 2001 From: mars <3361409208@qq.com> Date: Mon, 3 Aug 2026 11:22:51 +0800 Subject: [PATCH] =?UTF-8?q?fix(tng):=20=E4=BF=AE=E5=A4=8D=E5=9C=B0?= =?UTF-8?q?=E5=8C=BA=E9=80=89=E6=8B=A9=E9=BB=91=E5=B1=8F=E5=B9=B6=E5=8A=A0?= =?UTF-8?q?=E5=9B=BA=E6=B3=A8=E5=86=8C=E9=93=BE=20native=20abort=20?= =?UTF-8?q?=E9=98=B2=E6=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- magisk-modules/tng_exit_guard/jni/main.cpp | 130 ++++++++++++++++-- .../tng_exit_guard/zygisk/arm64-v8a.so | Bin 186384 -> 186384 bytes reverse/scripts/_scan_tng_vhv_u.py | 15 ++ reverse/scripts/parse_reg_crash_log.py | 14 ++ reverse/scripts/tap_country_code.py | 89 ++++++++++++ .../xposed/hook/TngRootBypassHook.java | 110 ++++++--------- 6 files changed, 274 insertions(+), 84 deletions(-) create mode 100644 reverse/scripts/_scan_tng_vhv_u.py create mode 100644 reverse/scripts/parse_reg_crash_log.py create mode 100644 reverse/scripts/tap_country_code.py diff --git a/magisk-modules/tng_exit_guard/jni/main.cpp b/magisk-modules/tng_exit_guard/jni/main.cpp index 8ad34ec..b770707 100644 --- a/magisk-modules/tng_exit_guard/jni/main.cpp +++ b/magisk-modules/tng_exit_guard/jni/main.cpp @@ -37,6 +37,8 @@ static constexpr const char *kTargetPkg = "my.com.tngdigital.ewallet"; static constexpr const char *kPromonSo = "libtngdigital_ewallet.so"; static bool g_enabled = false; +static zygisk::Api *g_api = nullptr; +static std::atomic g_cxx_plt{0}; static std::atomic g_seccomp_ok{0}; static std::atomic g_stack_chk{0}; static std::atomic g_promon_segv{0}; @@ -272,6 +274,13 @@ using kill_fn = int (*)(pid_t, int); using tgkill_fn = int (*)(int, int, int); using raise_fn = int (*)(int); using pthread_kill_fn = int (*)(pthread_t, int); +using cxa_guard_acquire_fn = int (*)(void *); +using cxa_guard_abort_fn = void (*)(); +using dlopen_fn = void *(*)(const char *, int); + +static cxa_guard_acquire_fn orig_cxa_guard_acquire = nullptr; +static cxa_guard_abort_fn orig_cxa_guard_abort = nullptr; +static dlopen_fn orig_dlopen = nullptr; static exit_fn orig_exit = nullptr; static exit_fn orig__exit = nullptr; @@ -326,7 +335,40 @@ static int hooked_pthread_kill(pthread_t thread, int sig) { return orig_pthread_kill ? orig_pthread_kill(thread, sig) : -1; } -static bool find_libc(dev_t *dev, ino_t *ino) { +/** Promon/libc++ 静态局部量递归初始化会 abort 主进程(Registration 页 HWUI 线程)。 */ +static int hooked_cxa_guard_acquire(void *guard) { + (void)guard; + return 1; +} +static void hooked_cxa_guard_abort() { + LOGI("blocked __cxa_guard_abort tid=%d", (int)gettid()); +} + +static void *hooked_dlopen(const char *name, int flags) { + void *handle = orig_dlopen ? orig_dlopen(name, flags) : nullptr; + if (handle != nullptr || name == nullptr) { + return handle; + } + if (strstr(name, "libandroid.so") != nullptr) { + static const char *kFallbacks[] = { + "/system/lib64/libandroid.so", + "/system/lib/libandroid.so", + "libandroid.so", + }; + for (const char *path : kFallbacks) { + handle = orig_dlopen ? orig_dlopen(path, flags) : nullptr; + if (handle != nullptr) { + LOGI("dlopen fallback %s -> %p (from %s)", path, handle, name); + return handle; + } + } + LOGI("dlopen libandroid.so failed tid=%d", (int)gettid()); + } + return handle; +} + +static bool find_lib_match(const char *suffix, const char *contains, + dev_t *dev, ino_t *ino) { FILE *fp = fopen("/proc/self/maps", "r"); if (!fp) return false; char line[1024]; @@ -339,11 +381,19 @@ static bool find_libc(dev_t *dev, ino_t *ino) { unsigned long inode = 0; char path[512] = {}; int n = sscanf(line, "%lx-%lx %7s %llx %31s %lu %511[^\n]", - &start, &end, perms, &offset, deststr, &inode, path); + &start, &end, perms, &offset, &deststr, &inode, path); if (n < 7 || inode == 0) continue; char *p = path; while (*p == ' ') ++p; - if (strstr(p, "libc.so") == nullptr) continue; + bool match = false; + if (suffix != nullptr) { + size_t plen = strlen(p); + size_t slen = strlen(suffix); + match = plen >= slen && strcmp(p + plen - slen, suffix) == 0; + } else if (contains != nullptr) { + match = strstr(p, contains) != nullptr; + } + if (!match) continue; unsigned maj = 0, min = 0; if (sscanf(deststr, "%x:%x", &maj, &min) != 2) continue; *dev = makedev(maj, min); @@ -355,25 +405,72 @@ static bool find_libc(dev_t *dev, ino_t *ino) { return ok; } +static bool find_lib_by_suffix(const char *suffix, dev_t *dev, ino_t *ino) { + return find_lib_match(suffix, nullptr, dev, ino); +} + +static bool find_lib_contains(const char *needle, dev_t *dev, ino_t *ino) { + return find_lib_match(nullptr, needle, dev, ino); +} + +static bool find_libc(dev_t *dev, ino_t *ino) { + return find_lib_by_suffix("libc.so", dev, ino); +} + +static void register_plt(zygisk::Api *api, dev_t dev, ino_t ino, + const char *sym, void *hook, void **orig) { + if (!api || dev == 0 || ino == 0) return; + api->pltHookRegister(dev, ino, sym, hook, orig); +} + static void install_plt(zygisk::Api *api) { if (!api) return; dev_t dev = 0; ino_t ino = 0; - if (!find_libc(&dev, &ino)) return; - api->pltHookRegister(dev, ino, "exit", (void *)hooked_exit, (void **)&orig_exit); - api->pltHookRegister(dev, ino, "_exit", (void *)hooked__exit, (void **)&orig__exit); - api->pltHookRegister(dev, ino, "abort", (void *)hooked_abort, (void **)&orig_abort); - api->pltHookRegister(dev, ino, "__stack_chk_fail", - (void *)hooked_stack_chk_fail, (void **)&orig_stack_chk_fail); - api->pltHookRegister(dev, ino, "raise", (void *)hooked_raise, (void **)&orig_raise); - api->pltHookRegister(dev, ino, "kill", (void *)hooked_kill, (void **)&orig_kill); - api->pltHookRegister(dev, ino, "tgkill", (void *)hooked_tgkill, (void **)&orig_tgkill); - api->pltHookRegister(dev, ino, "pthread_kill", - (void *)hooked_pthread_kill, (void **)&orig_pthread_kill); + if (find_libc(&dev, &ino)) { + register_plt(api, dev, ino, "exit", (void *)hooked_exit, (void **)&orig_exit); + register_plt(api, dev, ino, "_exit", (void *)hooked__exit, (void **)&orig__exit); + register_plt(api, dev, ino, "abort", (void *)hooked_abort, (void **)&orig_abort); + register_plt(api, dev, ino, "__stack_chk_fail", + (void *)hooked_stack_chk_fail, (void **)&orig_stack_chk_fail); + register_plt(api, dev, ino, "raise", (void *)hooked_raise, (void **)&orig_raise); + register_plt(api, dev, ino, "kill", (void *)hooked_kill, (void **)&orig_kill); + register_plt(api, dev, ino, "tgkill", (void *)hooked_tgkill, (void **)&orig_tgkill); + register_plt(api, dev, ino, "pthread_kill", + (void *)hooked_pthread_kill, (void **)&orig_pthread_kill); + register_plt(api, dev, ino, "dlopen", (void *)hooked_dlopen, (void **)&orig_dlopen); + } bool ok = api->pltHookCommit(); LOGI("PLT commit=%d", ok ? 1 : 0); } +static void try_install_cxx_guard_plt() { + if (g_cxx_plt.load() || !g_api) return; + dev_t dev = 0; + ino_t ino = 0; + bool any = false; + if (find_lib_by_suffix("libc++_shared.so", &dev, &ino) + || find_lib_contains("libc++", &dev, &ino)) { + register_plt(g_api, dev, ino, "__cxa_guard_acquire", + (void *)hooked_cxa_guard_acquire, (void **)&orig_cxa_guard_acquire); + register_plt(g_api, dev, ino, "__cxa_guard_abort", + (void *)hooked_cxa_guard_abort, (void **)&orig_cxa_guard_abort); + any = true; + } + if (find_lib_by_suffix("libtngdigital_ewallet.so", &dev, &ino)) { + register_plt(g_api, dev, ino, "__cxa_guard_acquire", + (void *)hooked_cxa_guard_acquire, (void **)&orig_cxa_guard_acquire); + register_plt(g_api, dev, ino, "__cxa_guard_abort", + (void *)hooked_cxa_guard_abort, (void **)&orig_cxa_guard_abort); + any = true; + } + if (!any) return; + if (g_api->pltHookCommit()) { + g_cxx_plt.store(1); + LOGI("PLT cxx guards committed"); + } +} + static void *phase_thread(void *) { install_promon_segv_handler(); usleep(400 * 1000); @@ -382,6 +479,8 @@ static void *phase_thread(void *) { for (int i = 0; i < 40; i++) { usleep(1000 * 1000); install_soft_signals(); + install_promon_segv_handler(); + try_install_cxx_guard_plt(); if (i % 5 == 0) refresh_promon_so_range(); } LOGI("phase done seccomp=%d stack_chk=%d promon_segv=%d", @@ -390,8 +489,9 @@ static void *phase_thread(void *) { } static void install_all(zygisk::Api *api) { + g_api = api; g_main_tid.store(gettid()); - LOGI("install pid=%d main_tid=%d (PLT+ABRT-pc+4+SEGV-all-skip+exit_group@400ms)", + LOGI("install pid=%d main_tid=%d (PLT+cxx-guard+ABRT-pc+4+SEGV-skip+exit_group@400ms)", getpid(), (int)g_main_tid.load()); install_fatal_skip_handlers(); install_soft_signals(); diff --git a/magisk-modules/tng_exit_guard/zygisk/arm64-v8a.so b/magisk-modules/tng_exit_guard/zygisk/arm64-v8a.so index af139d929df8c4701dc2b4e0a8bf2b044b80267a..516f4e15a4677a643e618eb5d7b93da60d0e4b08 100644 GIT binary patch delta 60489 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 aZtXMLu6^eDw_f!gUBZ8eb?2|VXZ{bUUQ>wx delta 58987 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�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 diff --git a/reverse/scripts/_scan_tng_vhv_u.py b/reverse/scripts/_scan_tng_vhv_u.py new file mode 100644 index 0000000..810ad56 --- /dev/null +++ b/reverse/scripts/_scan_tng_vhv_u.py @@ -0,0 +1,15 @@ +import re +import zipfile + +APK = r"reverse/dumps/tng_1.9.10_base.apk" +with zipfile.ZipFile(APK) as z: + data = b"".join(z.read(n) for n in z.namelist() if n.endswith(".dex")) + +for cls in ["Lvhvlnqgy/w;", "Lvhvlnqgy/u;"]: + print("===", cls, "refs ===") + pat = cls.encode() + rb"[^\x00]{0,120}" + hits = sorted(set(re.findall(pat, data))) + for h in hits[:40]: + print(h.decode("ascii", "ignore")) + print("count", len(hits)) + print() diff --git a/reverse/scripts/parse_reg_crash_log.py b/reverse/scripts/parse_reg_crash_log.py new file mode 100644 index 0000000..93b59f5 --- /dev/null +++ b/reverse/scripts/parse_reg_crash_log.py @@ -0,0 +1,14 @@ +import sys + +path = sys.argv[1] +lines = open(path, encoding="utf-8", errors="ignore").read().splitlines() +keys = ( + "Runtime aborting", "Aborting", "stack corruption", "blocked __stack", + "vhvlnqgy.u", "UserRegistration", "F libc", "has died", +) +for i, line in enumerate(lines): + if any(k in line for k in keys): + start = max(0, i - 2) + end = min(len(lines), i + 6) + print("---") + print("\n".join(lines[start:end])) diff --git a/reverse/scripts/tap_country_code.py b/reverse/scripts/tap_country_code.py new file mode 100644 index 0000000..dad749c --- /dev/null +++ b/reverse/scripts/tap_country_code.py @@ -0,0 +1,89 @@ +import re +import subprocess +import sys +import time +import xml.etree.ElementTree as ET + +ADB = ["adb"] + + +def adb(*args): + subprocess.run(ADB + list(args), check=False) + + +def main(): + adb("shell", "am", "force-stop", "my.com.tngdigital.ewallet") + time.sleep(2) + adb("shell", "am", "start", "-n", "my.com.tngdigital.ewallet/.ui.SplashActivity") + time.sleep(16) + adb("shell", "uiautomator", "dump", "/sdcard/ui_cc.xml") + xml = subprocess.check_output( + ADB + ["shell", "cat", "/sdcard/ui_cc.xml"], text=True, errors="ignore") + root = ET.fromstring(xml) + target = None + register_btn = None + for node in root.iter("node"): + rid = node.get("resource-id") or "" + text = node.get("text") or "" + if "tv_left" in rid or (text.strip().startswith("+") and len(text.strip()) < 8): + target = node + if "注册" in text and node.get("clickable") == "true": + register_btn = node + if target is None and register_btn is not None: + bounds = register_btn.get("bounds", "") + m = re.match(r"\[(\d+),(\d+)\]\[(\d+),(\d+)\]", bounds) + if m: + x1, y1, x2, y2 = map(int, m.groups()) + x, y = (x1 + x2) // 2, (y1 + y2) // 2 + print(f"tap register at {x},{y}") + adb("shell", "input", "tap", str(x), str(y)) + time.sleep(4) + adb("shell", "uiautomator", "dump", "/sdcard/ui_cc.xml") + xml = subprocess.check_output( + ADB + ["shell", "cat", "/sdcard/ui_cc.xml"], text=True, errors="ignore") + root = ET.fromstring(xml) + for node in root.iter("node"): + rid = node.get("resource-id") or "" + text = node.get("text") or "" + if "tv_left" in rid or (text.strip().startswith("+") and len(text.strip()) < 8): + target = node + break + if target is None: + for node in root.iter("node"): + text = node.get("text") or "" + if "注册" in text or "Register" in text.lower(): + print("login screen text:", text[:40]) + print("ERROR: country code control not found") + return 1 + bounds = target.get("bounds", "") + m = re.match(r"\[(\d+),(\d+)\]\[(\d+),(\d+)\]", bounds) + if not m: + print("bad bounds", bounds) + return 1 + x1, y1, x2, y2 = map(int, m.groups()) + x, y = (x1 + x2) // 2, (y1 + y2) // 2 + print(f"tap country {target.get('text','')} at {x},{y}") + adb("shell", "input", "tap", str(x), str(y)) + time.sleep(3) + adb("shell", "uiautomator", "dump", "/sdcard/ui_cc2.xml") + xml2 = subprocess.check_output( + ADB + ["shell", "cat", "/sdcard/ui_cc2.xml"], text=True, errors="ignore") + root2 = ET.fromstring(xml2) + countries = [] + for node in root2.iter("node"): + text = (node.get("text") or "").strip() + if "+61" in text or "+86" in text or "Australia" in text or "Malaysia" in text: + countries.append(text) + pid = subprocess.check_output( + ADB + ["shell", "pidof", "my.com.tngdigital.ewallet"], text=True).strip() + print("pid:", pid or "DEAD") + print("countries visible:", countries[:8]) + if countries: + print("OK region picker visible") + return 0 + print("FAIL region picker empty/black") + return 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/xposed-module/src/main/java/com/miraclegarden/smsmessage/xposed/hook/TngRootBypassHook.java b/xposed-module/src/main/java/com/miraclegarden/smsmessage/xposed/hook/TngRootBypassHook.java index 652d5bd..de700c0 100644 --- a/xposed-module/src/main/java/com/miraclegarden/smsmessage/xposed/hook/TngRootBypassHook.java +++ b/xposed-module/src/main/java/com/miraclegarden/smsmessage/xposed/hook/TngRootBypassHook.java @@ -227,10 +227,9 @@ public final class TngRootBypassHook { hookRegistrationFlowGuard(lpparam); hookSplashForceLogin(lpparam); hookLoginDismissSplash(lpparam); - hookDialogNoHwAccel(); - hookActivityLifecycleDiag(lpparam); hookHardwareRendererSetName(); - hookBottomSelectDialogSafe(lpparam); + hookBottomSelectDialogDiag(lpparam); + hookActivityLifecycleDiag(lpparam); hookPromonApService(lpparam); hookPromonBroadcastReceiver(lpparam); hookAppAttachForceLogin(lpparam); @@ -528,9 +527,30 @@ public final class TngRootBypassHook { } } + /** + * 区号选择弹窗诊断。勿关 HW 加速——Android 16 上会导致列表黑屏。 + * ANR 由 HardwareRenderer.setName 拦截兜底。 + */ + private static void hookBottomSelectDialogDiag(XC_LoadPackage.LoadPackageParam lpparam) { + try { + Class clazz = XposedHelpers.findClass( + "my.com.tngdigital.common.widget.BottomSelectDialogFragment", + lpparam.classLoader); + XposedHelpers.findAndHookMethod(clazz, "onStart", new XC_MethodHook() { + @Override + protected void beforeHookedMethod(MethodHookParam param) { + XposedBridge.log(TAG + " BottomSelectDialogFragment.onStart"); + } + }); + XposedBridge.log(TAG + " hooked BottomSelectDialogFragment.onStart (diag only)"); + } catch (Throwable t) { + XposedBridge.log(TAG + " BottomSelectDialog hook failed: " + t.getMessage()); + } + } + /** * ANR 栈:Dialog.show → enableHardwareAcceleration → HardwareRenderer.setName → future.get 卡死。 - * 兜底拦截 setName,避免 RenderThread 未就绪时主线程永久阻塞。 + * 仅拦截 setName;勿全局关 Dialog HW(区号选择会黑屏)。 */ private static void hookHardwareRendererSetName() { try { @@ -548,63 +568,6 @@ public final class TngRootBypassHook { } } - /** Dialog.show 走 HW 加速会等 RenderThread;复进时 RenderThread 易 abort → 主线程 ANR。 */ - private static void hookDialogNoHwAccel() { - try { - XposedHelpers.findAndHookMethod(Dialog.class, "show", new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) { - try { - Dialog dialog = (Dialog) param.thisObject; - android.view.Window window = dialog.getWindow(); - if (window != null) { - window.setFlags( - 0, - android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); - } - } catch (Throwable ignored) { - } - } - }); - XposedBridge.log(TAG + " hooked Dialog.show (no HW accel)"); - } catch (Throwable t) { - XposedBridge.log(TAG + " Dialog.show hook failed: " + t.getMessage()); - } - } - - /** - * 注册/登录页点「下一步」会弹国家区号 BottomSelectDialogFragment。 - * HardwareRenderer.setName 已拦截 ANR;此处仅关 Dialog HW 加速,保留区号选择。 - */ - private static void hookBottomSelectDialogSafe(XC_LoadPackage.LoadPackageParam lpparam) { - try { - Class clazz = XposedHelpers.findClass( - "my.com.tngdigital.common.widget.BottomSelectDialogFragment", - lpparam.classLoader); - XposedHelpers.findAndHookMethod(clazz, "onStart", new XC_MethodHook() { - @Override - protected void beforeHookedMethod(MethodHookParam param) { - try { - Object dialog = XposedHelpers.callMethod(param.thisObject, "getDialog"); - if (dialog instanceof Dialog) { - Dialog d = (Dialog) dialog; - if (d.getWindow() != null) { - d.getWindow().setFlags( - 0, - android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); - } - } - } catch (Throwable ignored) { - } - XposedBridge.log(TAG + " BottomSelectDialogFragment.onStart (safe, no HW)"); - } - }); - XposedBridge.log(TAG + " hooked BottomSelectDialogFragment.onStart (safe)"); - } catch (Throwable t) { - XposedBridge.log(TAG + " BottomSelectDialog hook failed: " + t.getMessage()); - } - } - /** Promon 隔离 Service;打点确认 :goacqowmmt 进程 hook 已注入。 */ private static void hookPromonApService(XC_LoadPackage.LoadPackageParam lpparam) { Class svc = findPromonClass(lpparam.classLoader, "ap"); @@ -1201,19 +1164,27 @@ public final class TngRootBypassHook { } /** - * Promon lifecycle:只吞异常,不 short-circuit——全拦会拖死 Splash→Login。 + * Promon lifecycle:1.9.10 用 vhvlnqgy.u,旧版用 w。只吞异常,不全拦。 */ private static void hookPromonLifecycle(XC_LoadPackage.LoadPackageParam lpparam) { - Class lifecycleClass = findPromonClass(lpparam.classLoader, "w"); - if (lifecycleClass == null) { - XposedBridge.log(TAG + " Promon w lifecycle not found"); - return; - } Class promonExc = findPromonClass(lpparam.classLoader, "W"); if (promonExc == null) { promonExc = findPromonClass(lpparam.classLoader, "bd"); } final Class promonExcFinal = promonExc; + for (String simple : new String[]{"w", "u"}) { + hookPromonLifecycleClass(lpparam, simple, promonExcFinal); + } + } + + private static void hookPromonLifecycleClass( + XC_LoadPackage.LoadPackageParam lpparam, + String simpleName, + Class promonExc) { + Class lifecycleClass = findPromonClass(lpparam.classLoader, simpleName); + if (lifecycleClass == null) { + return; + } final String lifecycleName = lifecycleClass.getName(); try { int hooked = 0; @@ -1229,7 +1200,7 @@ public final class TngRootBypassHook { return; } Throwable t = param.getThrowable(); - if (isPromonThrowable(t, promonExcFinal)) { + if (isPromonThrowable(t, promonExc)) { XposedBridge.log(TAG + " swallowed " + t.getClass().getSimpleName() + " in " + lifecycleName + "#" + method.getName()); param.setThrowable(null); @@ -1243,7 +1214,8 @@ public final class TngRootBypassHook { + " " + lifecycleName + " lifecycle method(s) (afterHook only)"); } } catch (Throwable t) { - XposedBridge.log(TAG + " Promon w lifecycle hook failed: " + t.getMessage()); + XposedBridge.log(TAG + " " + lifecycleName + " lifecycle hook failed: " + + t.getMessage()); } }