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();
|
||||
|
||||
Reference in New Issue
Block a user