fix(tng): 适配 Promon 1.9.10 vhvlnqgy 包名并加固 Zygisk 信号跳过

1.9.10 将 xwwqazamx 重命名为 vhvlnqgy,Login 闪退为 vhvlnqgy.bd:16;Xposed 双包名解析并 short-circuit R/bl、拦截 bd 异常。Zygisk 扩展 non-promon SEGV pc+4 与 ABRT/TRAP 一律 pc+4,修复 Login 稳定;注册页 stack_chk abort 待续攻。
This commit is contained in:
mars
2026-08-03 11:02:46 +08:00
parent 818b2f4f51
commit 18ae42ec63
8 changed files with 329 additions and 95 deletions

View File

@@ -36,6 +36,9 @@ public final class TngRootBypassHook {
public static final String PACKAGE = "my.com.tngdigital.ewallet";
private static final String TAG = "notiMessageHook/TngRoot";
/** Promon 混淆包名1.9.10 为 vhvlnqgy旧版为 xwwqazamx。 */
private static final String[] PROMON_PKG_PREFIXES = {"vhvlnqgy", "xwwqazamx"};
private static final String SECURITY_ERROR_ACTIVITY =
"my.com.tngdigital.common.security.ui.SecurityErrorActivity";
@@ -604,12 +607,17 @@ public final class TngRootBypassHook {
/** Promon 隔离 Service打点确认 :goacqowmmt 进程 hook 已注入。 */
private static void hookPromonApService(XC_LoadPackage.LoadPackageParam lpparam) {
Class<?> svc = findPromonClass(lpparam.classLoader, "ap");
if (svc == null) {
XposedBridge.log(TAG + " Promon ap Service not found");
return;
}
try {
Class<?> svc = XposedHelpers.findClass("xwwqazamx.ap", lpparam.classLoader);
final String svcName = svc.getName();
XposedHelpers.findAndHookMethod(svc, "onCreate", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) {
XposedBridge.log(TAG + " xwwqazamx.ap onCreate pid=" + Process.myPid()
XposedBridge.log(TAG + " " + svcName + " onCreate pid=" + Process.myPid()
+ " proc=" + getProcessName());
}
});
@@ -620,14 +628,14 @@ public final class TngRootBypassHook {
XposedBridge.hookMethod(method, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) {
XposedBridge.log(TAG + " xwwqazamx.ap onStartCommand pid="
XposedBridge.log(TAG + " " + svcName + " onStartCommand pid="
+ Process.myPid());
}
});
}
XposedBridge.log(TAG + " hooked xwwqazamx.ap Service");
XposedBridge.log(TAG + " hooked " + svcName + " Service");
} catch (Throwable t) {
XposedBridge.log(TAG + " xwwqazamx.ap hook failed: " + t.getMessage());
XposedBridge.log(TAG + " Promon ap Service hook failed: " + t.getMessage());
}
}
@@ -746,10 +754,14 @@ public final class TngRootBypassHook {
return false;
}
/** Promon USB 广播 xwwqazamx.N 跑在主线程,复进时拖死 Looper。 */
/** Promon USB 广播 N 跑在主线程,复进时拖死 Looper。 */
private static void hookPromonBroadcastReceiver(XC_LoadPackage.LoadPackageParam lpparam) {
Class<?> clazz = findPromonClass(lpparam.classLoader, "N");
if (clazz == null) {
XposedBridge.log(TAG + " Promon N receiver not found");
return;
}
try {
Class<?> clazz = XposedHelpers.findClass("xwwqazamx.N", lpparam.classLoader);
int hooked = 0;
for (Method method : clazz.getDeclaredMethods()) {
if (!"onReceive".equals(method.getName())) {
@@ -764,10 +776,10 @@ public final class TngRootBypassHook {
hooked++;
}
if (hooked > 0) {
XposedBridge.log(TAG + " hooked xwwqazamx.N onReceive x" + hooked);
XposedBridge.log(TAG + " hooked " + clazz.getName() + " onReceive x" + hooked);
}
} catch (Throwable t) {
XposedBridge.log(TAG + " xwwqazamx.N hook failed: " + t.getMessage());
XposedBridge.log(TAG + " Promon N hook failed: " + t.getMessage());
}
}
@@ -1179,11 +1191,12 @@ public final class TngRootBypassHook {
|| lower.contains("emulator") || lower.contains("malware");
}
/** 阻止 Promon 混淆层抛出 W:16 并触发浏览器 fallback。 */
/** 阻止 Promon 混淆层抛出 W/bd:16 并触发浏览器 fallback。 */
private static void hookPromonNativeGuard(XC_LoadPackage.LoadPackageParam lpparam) {
hookPromonBlSwallowExceptions(lpparam);
hookPromonExceptionClass(lpparam, "xwwqazamx.W");
hookPromonExceptionClass(lpparam, "xwwqazamx.A");
for (String simple : new String[]{"W", "A", "bd"}) {
hookPromonExceptionClass(lpparam, simple);
}
hookPromonRunnable(lpparam);
}
@@ -1191,14 +1204,18 @@ public final class TngRootBypassHook {
* Promon lifecycle只吞异常不 short-circuit——全拦会拖死 Splash→Login。
*/
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;
final String lifecycleName = lifecycleClass.getName();
try {
Class<?> lifecycleClass = XposedHelpers.findClass("xwwqazamx.w", lpparam.classLoader);
Class<?> promonExc = null;
try {
promonExc = XposedHelpers.findClass("xwwqazamx.W", lpparam.classLoader);
} catch (Throwable ignored) {
}
final Class<?> promonExcFinal = promonExc;
int hooked = 0;
for (Method method : lifecycleClass.getDeclaredMethods()) {
String name = method.getName();
@@ -1214,7 +1231,7 @@ public final class TngRootBypassHook {
Throwable t = param.getThrowable();
if (isPromonThrowable(t, promonExcFinal)) {
XposedBridge.log(TAG + " swallowed " + t.getClass().getSimpleName()
+ " in xwwqazamx.w#" + method.getName());
+ " in " + lifecycleName + "#" + method.getName());
param.setThrowable(null);
}
}
@@ -1223,10 +1240,10 @@ public final class TngRootBypassHook {
}
if (hooked > 0) {
XposedBridge.log(TAG + " hooked " + hooked
+ " xwwqazamx.w lifecycle method(s) (afterHook only)");
+ " " + lifecycleName + " lifecycle method(s) (afterHook only)");
}
} catch (Throwable t) {
XposedBridge.log(TAG + " xwwqazamx.w lifecycle hook failed: " + t.getMessage());
XposedBridge.log(TAG + " Promon w lifecycle hook failed: " + t.getMessage());
}
}
@@ -1256,15 +1273,24 @@ public final class TngRootBypassHook {
}
/**
* bl 全方法 short-circuita/b 之外的方法仍会跑 native~40s 后 stack_chk/SEGV。
* xwwqazamx.a.run 是 bl#b 后台 Runnable必须 beforeHook 直接 return。
* bl/R 全方法 short-circuita/b 之外的方法仍会跑 native~40s 后 stack_chk/SEGV。
* a.run 是 bl#b 后台 Runnable必须 beforeHook 直接 return。
*/
private static void hookPromonBlSwallowExceptions(XC_LoadPackage.LoadPackageParam lpparam) {
for (String simple : new String[]{"bl", "R"}) {
hookPromonClassShortCircuit(lpparam, simple);
}
}
private static void hookPromonClassShortCircuit(
XC_LoadPackage.LoadPackageParam lpparam, String simpleName) {
Class<?> clazz = findPromonClass(lpparam.classLoader, simpleName);
if (clazz == null) {
return;
}
try {
Class<?> blClass = XposedHelpers.findClass("xwwqazamx.bl", lpparam.classLoader);
int hooked = 0;
for (Method method : blClass.getDeclaredMethods()) {
String name = method.getName();
for (Method method : clazz.getDeclaredMethods()) {
XposedBridge.hookMethod(method, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) {
@@ -1274,10 +1300,12 @@ public final class TngRootBypassHook {
hooked++;
}
if (hooked > 0) {
XposedBridge.log(TAG + " hooked " + hooked + " bl method(s), all short-circuit");
XposedBridge.log(TAG + " hooked " + hooked + " " + clazz.getName()
+ " method(s), all short-circuit");
}
} catch (Throwable t) {
XposedBridge.log(TAG + " xwwqazamx.bl hook failed: " + t.getMessage());
XposedBridge.log(TAG + " " + clazz.getName() + " short-circuit failed: "
+ t.getMessage());
}
}
@@ -1294,24 +1322,32 @@ public final class TngRootBypassHook {
/** Promon 后台 Runnablebl#b 检测线程beforeHook 直接 noop禁止跑 native。 */
private static void hookPromonRunnable(XC_LoadPackage.LoadPackageParam lpparam) {
Class<?> runnableClass = findPromonClass(lpparam.classLoader, "a");
if (runnableClass == null) {
XposedBridge.log(TAG + " Promon a runnable not found");
return;
}
try {
Class<?> runnableClass = XposedHelpers.findClass("xwwqazamx.a", lpparam.classLoader);
XposedHelpers.findAndHookMethod(runnableClass, "run", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) {
param.setResult(null);
}
});
XposedBridge.log(TAG + " hooked xwwqazamx.a.run (short-circuit)");
XposedBridge.log(TAG + " hooked " + runnableClass.getName() + ".run (short-circuit)");
} catch (Throwable t) {
XposedBridge.log(TAG + " xwwqazamx.a.run hook failed: " + t.getMessage());
XposedBridge.log(TAG + " Promon a.run hook failed: " + t.getMessage());
}
}
private static void hookPromonExceptionClass(
XC_LoadPackage.LoadPackageParam lpparam, String className) {
XC_LoadPackage.LoadPackageParam lpparam, String simpleName) {
Class<?> promonExc = findPromonClass(lpparam.classLoader, simpleName);
if (promonExc == null) {
return;
}
final String className = promonExc.getName();
try {
Class<?> promonExc = XposedHelpers.findClass(className, lpparam.classLoader);
for (Method method : promonExc.getDeclaredMethods()) {
XposedBridge.hookMethod(method, new XC_MethodHook() {
@Override
@@ -1332,6 +1368,7 @@ public final class TngRootBypassHook {
} catch (Throwable ignored) {
// constructor overload may differ
}
XposedBridge.log(TAG + " hooked Promon exception " + className);
} catch (Throwable t) {
XposedBridge.log(TAG + " " + className + " hook failed: " + t.getMessage());
}
@@ -1355,16 +1392,38 @@ public final class TngRootBypassHook {
if (className == null) {
return false;
}
if (!className.startsWith("xwwqazamx.")) {
if (!isPromonPackageClass(className)) {
return false;
}
// W/A 等单字母 Promon 异常;排除 bl/w/bg 等功能类
// W/A/bd 等 Promon 异常;排除 bl/w/bg/R 等功能类
int dot = className.lastIndexOf('.');
if (dot < 0) {
return false;
}
String simple = className.substring(dot + 1);
return simple.length() <= 2;
if ("bd".equals(simple)) {
return true;
}
return simple.length() == 1;
}
private static boolean isPromonPackageClass(String className) {
for (String prefix : PROMON_PKG_PREFIXES) {
if (className.startsWith(prefix + ".")) {
return true;
}
}
return false;
}
private static Class<?> findPromonClass(ClassLoader loader, String simpleName) {
for (String prefix : PROMON_PKG_PREFIXES) {
try {
return XposedHelpers.findClass(prefix + "." + simpleName, loader);
} catch (Throwable ignored) {
}
}
return null;
}
/** SecurityGuard探测命令 stub10101 init + 104xx/105xx sign/verify 走真实 native。 */
@@ -1866,35 +1925,24 @@ public final class TngRootBypassHook {
/** Promon native 桥接类:强制 int/boolean 检测返回安全值。 */
private static void hookPromonNativeBridge(XC_LoadPackage.LoadPackageParam lpparam) {
String[] classes = {
"xwwqazamx.F",
"xwwqazamx.bg",
"xwwqazamx.b",
"xwwqazamx.c",
"xwwqazamx.d",
"xwwqazamx.h",
"xwwqazamx.k",
"xwwqazamx.l",
"xwwqazamx.m",
"xwwqazamx.o",
"xwwqazamx.s",
"xwwqazamx.t",
"xwwqazamx.z",
String[] simpleNames = {
"F", "bg", "b", "c", "d", "h", "k", "l", "m", "o", "s", "t", "z",
};
int total = 0;
for (String className : classes) {
total += hookPromonIntBooleanMethods(lpparam, className);
for (String simpleName : simpleNames) {
Class<?> clazz = findPromonClass(lpparam.classLoader, simpleName);
if (clazz != null) {
total += hookPromonIntBooleanMethods(clazz);
}
}
if (total > 0) {
XposedBridge.log(TAG + " Promon native-bridge total hooks=" + total);
}
}
private static int hookPromonIntBooleanMethods(
XC_LoadPackage.LoadPackageParam lpparam, String className) {
private static int hookPromonIntBooleanMethods(Class<?> clazz) {
int count = 0;
try {
Class<?> clazz = XposedHelpers.findClass(className, lpparam.classLoader);
for (Method method : clazz.getDeclaredMethods()) {
Class<?> returnType = method.getReturnType();
if (returnType != boolean.class && returnType != Boolean.class