From fd6a454275237bd9f063275a7197f6822e0b3194 Mon Sep 17 00:00:00 2001 From: 5ec1cff Date: Mon, 13 Nov 2023 15:04:23 +0800 Subject: [PATCH] fix compatibility on lower android version --- loader/src/ptracer/monitor.cpp | 6 ++++-- loader/src/ptracer/ptracer.cpp | 33 +++++++++++++++++++++++++++++---- loader/src/ptracer/utils.cpp | 20 +++++++++++++++----- loader/src/ptracer/utils.hpp | 1 + module/src/post-fs-data.sh | 4 ++-- module/src/sepolicy.rule | 1 + 6 files changed, 52 insertions(+), 13 deletions(-) diff --git a/loader/src/ptracer/monitor.cpp b/loader/src/ptracer/monitor.cpp index d834ddb..533032a 100644 --- a/loader/src/ptracer/monitor.cpp +++ b/loader/src/ptracer/monitor.cpp @@ -172,6 +172,8 @@ struct SocketHandler : public EventHandler { } }; +constexpr auto MAX_RETRY_COUNT = 2; + struct timespec last_zygote64{.tv_sec = 0, .tv_nsec = 0}; int count_zygote64 = 0; bool should_stop_inject64() { @@ -183,7 +185,7 @@ bool should_stop_inject64() { count_zygote64 = 0; } last_zygote64 = now; - return count_zygote64 >= 5; + return count_zygote64 >= MAX_RETRY_COUNT; } struct timespec last_zygote32{.tv_sec = 0, .tv_nsec = 0}; @@ -197,7 +199,7 @@ bool should_stop_inject32() { count_zygote32 = 0; } last_zygote32 = now; - return count_zygote32 >= 5; + return count_zygote32 >= MAX_RETRY_COUNT; } struct PtraceHandler : public EventHandler { diff --git a/loader/src/ptracer/ptracer.cpp b/loader/src/ptracer/ptracer.cpp index dd5b998..4bcbdf8 100644 --- a/loader/src/ptracer/ptracer.cpp +++ b/loader/src/ptracer/ptracer.cpp @@ -88,7 +88,8 @@ bool inject_on_main(int pid, const char *lib_path) { memcpy(&backup, ®s, sizeof(regs)); map = MapInfo::Scan(std::to_string(pid)); auto local_map = MapInfo::Scan(); - auto libc_base = find_module_base(map, "libc.so"); + auto libc_return_addr = find_module_return_addr(map, "libc.so"); + LOGD("libc return addr %p", libc_return_addr); // call dlopen auto dlopen_addr = find_func_addr(local_map, map, "libdl.so", "dlopen"); @@ -98,10 +99,34 @@ bool inject_on_main(int pid, const char *lib_path) { args.clear(); args.push_back((long) str); args.push_back((long) RTLD_NOW); - auto remote_handle = remote_call(pid, regs, (uintptr_t) dlopen_addr, (uintptr_t) libc_base, args); + auto remote_handle = remote_call(pid, regs, (uintptr_t) dlopen_addr, (uintptr_t) libc_return_addr, args); LOGD("remote handle %p", (void *) remote_handle); if (remote_handle == 0) { LOGE("handle is null"); + // call dlerror + auto dlerror_addr = find_func_addr(local_map, map, "libdl.so", "dlerror"); + if (dlerror_addr == nullptr) { + LOGE("find dlerror"); + return false; + } + args.clear(); + auto dlerror_str_addr = remote_call(pid, regs, (uintptr_t) dlerror_addr, (uintptr_t) libc_return_addr, args); + LOGD("dlerror str %p", (void*) dlerror_str_addr); + if (dlerror_str_addr == 0) return false; + auto strlen_addr = find_func_addr(local_map, map, "libc.so", "strlen"); + if (strlen_addr == nullptr) { + LOGE("find strlen"); + return false; + } + args.clear(); + args.push_back(dlerror_str_addr); + auto dlerror_len = remote_call(pid, regs, (uintptr_t) strlen_addr, (uintptr_t) libc_return_addr, args); + LOGD("dlerror len %ld", dlerror_len); + if (dlerror_len <= 0) return false; + std::string err; + err.resize(dlerror_len + 1, 0); + read_proc(pid, (uintptr_t*) dlerror_str_addr, err.data(), dlerror_len); + LOGE("dlerror info %s", err.c_str()); return false; } @@ -112,7 +137,7 @@ bool inject_on_main(int pid, const char *lib_path) { str = push_string(pid, regs, "entry"); args.push_back(remote_handle); args.push_back((long) str); - auto injector_entry = remote_call(pid, regs, (uintptr_t) dlsym_addr, (uintptr_t) libc_base, args); + auto injector_entry = remote_call(pid, regs, (uintptr_t) dlsym_addr, (uintptr_t) libc_return_addr, args); LOGD("injector entry %p", (void*) injector_entry); if (injector_entry == 0) { LOGE("injector entry is null"); @@ -122,7 +147,7 @@ bool inject_on_main(int pid, const char *lib_path) { // call injector entry(handle) args.clear(); args.push_back(remote_handle); - remote_call(pid, regs, injector_entry, (uintptr_t) libc_base, args); + remote_call(pid, regs, injector_entry, (uintptr_t) libc_return_addr, args); // reset pc to entry backup.REG_IP = (long) entry_addr; diff --git a/loader/src/ptracer/utils.cpp b/loader/src/ptracer/utils.cpp index 899bd9d..8179d38 100644 --- a/loader/src/ptracer/utils.cpp +++ b/loader/src/ptracer/utils.cpp @@ -152,6 +152,16 @@ std::string get_addr_mem_region(std::vector &info, void *addr) { return ""; } + +void *find_module_return_addr(std::vector &info, std::string_view suffix) { + for (auto &map: info) { + if ((map.perms & PROT_EXEC) == 0 && map.path.ends_with(suffix)) { + return (void *) map.start; + } + } + return nullptr; +} + void *find_module_base(std::vector &info, std::string_view suffix) { for (auto &map: info) { if (map.offset == 0 && map.path.ends_with(suffix)) { @@ -301,18 +311,18 @@ uintptr_t remote_call(int pid, struct user_regs_struct ®s, uintptr_t func_add if (waitpid(pid, &status, __WALL) == -1) { PLOGE("wait"); } + if (!get_regs(pid, regs)) { + LOGE("failed to get regs after call"); + return 0; + } if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGSEGV) { - if (!get_regs(pid, regs)) { - LOGE("failed to get regs after call"); - return 0; - } if (regs.REG_IP != return_addr) { LOGE("wrong return addr %p", (void *) regs.REG_IP); return 0; } return regs.REG_RET; } else { - LOGE("stopped by other reason %s", parse_status(status).c_str()); + LOGE("stopped by other reason %s at addr %p", parse_status(status).c_str(), (void*) regs.REG_IP); } return 0; } diff --git a/loader/src/ptracer/utils.hpp b/loader/src/ptracer/utils.hpp index 90aac2e..965952b 100644 --- a/loader/src/ptracer/utils.hpp +++ b/loader/src/ptracer/utils.hpp @@ -117,4 +117,5 @@ inline const char* sigabbrev_np(int sig) { } std::string get_program(int pid); +void *find_module_return_addr(std::vector &info, std::string_view suffix); diff --git a/module/src/post-fs-data.sh b/module/src/post-fs-data.sh index 7e797fe..46c2d1c 100644 --- a/module/src/post-fs-data.sh +++ b/module/src/post-fs-data.sh @@ -31,13 +31,13 @@ create_sys_perm /dev/zygisk if [ -f $MODDIR/lib64/libzygisk.so ];then create_sys_perm /dev/zygisk/lib64 cp $MODDIR/lib64/libzygisk.so /dev/zygisk/lib64/libzygisk.so - chcon u:object_r:system_lib_file:s0 /dev/zygisk/lib64/libzygisk.so + chcon u:object_r:system_file:s0 /dev/zygisk/lib64/libzygisk.so fi if [ -f $MODDIR/lib/libzygisk.so ];then create_sys_perm /dev/zygisk/lib cp $MODDIR/lib/libzygisk.so /dev/zygisk/lib/libzygisk.so - chcon u:object_r:system_lib_file:s0 /dev/zygisk/lib/libzygisk.so + chcon u:object_r:system_file:s0 /dev/zygisk/lib/libzygisk.so fi unshare -m sh -c "./bin/zygisk-ptrace64 monitor &" diff --git a/module/src/sepolicy.rule b/module/src/sepolicy.rule index 2a9090e..a99f9ef 100644 --- a/module/src/sepolicy.rule +++ b/module/src/sepolicy.rule @@ -17,3 +17,4 @@ allow zygote mnt_vendor_file dir search allow zygote system_file dir mounton allow zygote labeledfs filesystem mount allow zygote fs_type filesystem unmount +allow zygote zygote process execmem