fix(tng): 修复地区选择黑屏并加固注册链 native abort 防护
This commit is contained in:
@@ -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<int> g_cxx_plt{0};
|
||||
static std::atomic<int> g_seccomp_ok{0};
|
||||
static std::atomic<int> g_stack_chk{0};
|
||||
static std::atomic<int> 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();
|
||||
|
||||
Binary file not shown.
15
reverse/scripts/_scan_tng_vhv_u.py
Normal file
15
reverse/scripts/_scan_tng_vhv_u.py
Normal file
@@ -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()
|
||||
14
reverse/scripts/parse_reg_crash_log.py
Normal file
14
reverse/scripts/parse_reg_crash_log.py
Normal file
@@ -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]))
|
||||
89
reverse/scripts/tap_country_code.py
Normal file
89
reverse/scripts/tap_country_code.py
Normal file
@@ -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())
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user