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:
@@ -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-circuit:a/b 之外的方法仍会跑 native,~40s 后 stack_chk/SEGV。
|
||||
* xwwqazamx.a.run 是 bl#b 后台 Runnable,必须 beforeHook 直接 return。
|
||||
* bl/R 全方法 short-circuit:a/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 后台 Runnable(bl#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:探测命令 stub;10101 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
|
||||
|
||||
Reference in New Issue
Block a user