fix(tng): 修复地区选择黑屏并加固注册链 native abort 防护

This commit is contained in:
mars
2026-08-03 11:22:51 +08:00
parent 18ae42ec63
commit 193c04a24b
6 changed files with 274 additions and 84 deletions

View File

@@ -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();