diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index bdbecceb..1136e338 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -49,8 +49,8 @@ jobs: uses: actions/cache@v2 with: path: ~/.ccache - key: ccache-${{ github.sha }} - restore-keys: ccache + key: ccache-cache-${{ github.sha }} + restore-keys: ccache-cache- - name: Install ccache run: sudo apt-get install -y ccache - name: Build with Gradle diff --git a/core/build.gradle.kts b/core/build.gradle.kts index e0671db0..59196523 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -185,8 +185,6 @@ task("buildLibcxx", Exec::class) { println("using ccache $it") environment("NDK_CCACHE", it) environment("USE_CCACHE", "1") - environment("CCACHE_COMPILERCHECK", "content") - environment("CCACHE_MAXSIZE", "100M") } ?: run { println("not using ccache") } diff --git a/core/src/main/cpp/CMakeLists.txt b/core/src/main/cpp/CMakeLists.txt index 8384acc9..b10257f5 100644 --- a/core/src/main/cpp/CMakeLists.txt +++ b/core/src/main/cpp/CMakeLists.txt @@ -25,8 +25,6 @@ find_program(CCACHE ccache) if (CCACHE) set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE}) set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE}) - set(ENV{CCACHE_COMPILERCHECK} "content") - set(ENV{CCACHE_MAXSIZE} "100M") else () message(WARNING "Could not find CCache program.") endif () diff --git a/core/src/main/cpp/external/CMakeLists.txt b/core/src/main/cpp/external/CMakeLists.txt index b19aba36..32bc4cb9 100644 --- a/core/src/main/cpp/external/CMakeLists.txt +++ b/core/src/main/cpp/external/CMakeLists.txt @@ -10,13 +10,11 @@ macro(SET_OPTION option value) endmacro() SET_OPTION(DOBBY_GENERATE_SHARED OFF) -SET_OPTION(Plugin.Android.BionicLinkerRestriction ON) if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") SET_OPTION(DOBBY_DEBUG OFF) endif (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") add_subdirectory(Dobby) target_include_directories(dobby PUBLIC Dobby/include) -target_include_directories(dobby PUBLIC Dobby/builtin-plugin/BionicLinkerRestriction) add_library(libcxx STATIC IMPORTED GLOBAL) set_property(TARGET libcxx PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../../../../build/intermediates/ndk/obj/local/${CMAKE_ANDROID_ARCH_ABI}/libcxx.a) diff --git a/core/src/main/cpp/main/include/config.h b/core/src/main/cpp/main/include/config.h index e47f4752..1ec6d7ca 100644 --- a/core/src/main/cpp/main/include/config.h +++ b/core/src/main/cpp/main/include/config.h @@ -32,15 +32,15 @@ namespace lspd { //#define DEBUG -inline bool constexpr Is64() { + inline bool constexpr Is64() { #if defined(__LP64__) - return true; + return true; #else - return false; + return false; #endif -} + } -inline constexpr bool is64 = Is64(); + inline constexpr bool is64 = Is64(); #if defined(__LP64__) # define LP_SELECT(lp32, lp64) lp64 @@ -55,12 +55,20 @@ inline constexpr bool is64 = Is64(); static constexpr auto kLibArtName = "libart.so"_tstr; static constexpr auto kLibFwName = "libandroidfw.so"_tstr; + static constexpr auto kLinkerName = LP_SELECT("linker"_tstr, "linker64"_tstr); + static constexpr auto kLibcName = "libc.so"_tstr; + static constexpr auto kLibbaseName = "libbase.so"_tstr; static constexpr auto kLibBasePath = LP_SELECT("/system/lib/"_tstr, "/system/lib64/"_tstr); - static constexpr auto kLibArtLegacyPath = kLibBasePath + kLibArtName; + + static constexpr auto kBinBasePath = "/system/bin/"_tstr; + static constexpr auto kLibFwPath = kLibBasePath + kLibFwName; + static constexpr auto kLinkerPath = kBinBasePath + kLinkerName; + static constexpr auto kLibcPath = kLibBasePath + kLibcName; + static constexpr auto kLibbasePath = kLibBasePath + kLibbaseName; inline constexpr const char *const BoolToString(bool b) { return b ? "true" : "false"; diff --git a/core/src/main/cpp/main/src/context.cpp b/core/src/main/cpp/main/src/context.cpp index 92b6155f..7bb23254 100644 --- a/core/src/main/cpp/main/src/context.cpp +++ b/core/src/main/cpp/main/src/context.cpp @@ -31,6 +31,7 @@ #include "jni/logger.h" #include "jni/native_api.h" #include "service.h" +#include "symbol_cache.h" namespace lspd { extern int *allowUnload; @@ -168,22 +169,24 @@ namespace lspd { void Context::OnNativeForkSystemServerPre(JNIEnv *env) { Service::instance()->InitService(env); - skip_ = false; - setAllowUnload(false); + skip_ = !sym_initialized; + setAllowUnload(skip_); } void Context::OnNativeForkSystemServerPost(JNIEnv *env, jint res) { if (res != 0) return; - LoadDex(env); - Service::instance()->HookBridge(*this, env); - auto binder = Service::instance()->RequestBinderForSystemServer(env); - if (binder && !skip_) { - InstallInlineHooks(); - Init(env); - FindAndCall(env, "forkSystemServerPost", "(Landroid/os/IBinder;)V", binder); + if (!skip_) { + LoadDex(env); + Service::instance()->HookBridge(*this, env); + auto binder = Service::instance()->RequestBinderForSystemServer(env); + if (binder) { + InstallInlineHooks(); + Init(env); + FindAndCall(env, "forkSystemServerPost", "(Landroid/os/IBinder;)V", binder); + } } - setAllowUnload(false); + setAllowUnload(skip_); } void Context::OnNativeForkAndSpecializePre(JNIEnv *env, @@ -195,7 +198,7 @@ namespace lspd { const auto app_id = uid % PER_USER_RANGE; nice_name_ = nice_name; JUTFString process_name(env, nice_name); - skip_ = false; + skip_ = !sym_initialized; if (!skip_ && !app_data_dir) { LOGD("skip injecting into %s because it has no data dir", process_name.get()); skip_ = true; diff --git a/core/src/main/cpp/main/src/elf_util.cpp b/core/src/main/cpp/main/src/elf_util.cpp new file mode 100644 index 00000000..783b4faf --- /dev/null +++ b/core/src/main/cpp/main/src/elf_util.cpp @@ -0,0 +1,203 @@ +// From https://github.com/ganyao114/SandHook/blob/master/hooklib/src/main/cpp/utils/elf_util.cpp +// +// Created by Swift Gan on 2019/3/14. +// +#include +#include +#include +#include +#include +#include +#include +#include +#include "logging.h" +#include "elf_util.h" + +using namespace SandHook; +namespace fs = std::filesystem; + +ElfImg::ElfImg(const char *elf) { + this->elf = elf; + //load elf + int fd = open(elf, O_RDONLY); + if (fd < 0) { + LOGE("failed to open %s", elf); + return; + } + + size = lseek(fd, 0, SEEK_END); + if (size <= 0) { + LOGE("lseek() failed for %s", elf); + } + + header = reinterpret_cast(mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0)); + + close(fd); + + section_header = reinterpret_cast(((size_t) header) + header->e_shoff); + + auto shoff = reinterpret_cast(section_header); + char *section_str = reinterpret_cast(section_header[header->e_shstrndx].sh_offset + + ((size_t) header)); + + for (int i = 0; i < header->e_shnum; i++, shoff += header->e_shentsize) { + auto *section_h = (Elf_Shdr *) shoff; + char *sname = section_h->sh_name + section_str; + Elf_Off entsize = section_h->sh_entsize; + switch (section_h->sh_type) { + case SHT_DYNSYM: + if (bias == -4396) { + dynsym = section_h; + dynsym_offset = section_h->sh_offset; + dynsym_size = section_h->sh_size; + dynsym_count = dynsym_size / entsize; + dynsym_start = reinterpret_cast(((size_t) header) + dynsym_offset); + } + break; + case SHT_SYMTAB: + if (strcmp(sname, ".symtab") == 0) { + symtab = section_h; + symtab_offset = section_h->sh_offset; + symtab_size = section_h->sh_size; + symtab_count = symtab_size / entsize; + symtab_start = reinterpret_cast(((size_t) header) + symtab_offset); + } + break; + case SHT_STRTAB: + if (bias == -4396) { + strtab = section_h; + symstr_offset = section_h->sh_offset; + strtab_start = reinterpret_cast(((size_t) header) + symstr_offset); + } + if (strcmp(sname, ".strtab") == 0) { + symstr_offset_for_symtab = section_h->sh_offset; + } + break; + case SHT_PROGBITS: + if (strtab == nullptr || dynsym == nullptr) break; + if (bias == -4396) { + bias = (off_t) section_h->sh_addr - (off_t) section_h->sh_offset; + } + break; + } + } + + //load module base + base = getModuleBase(); +} + +ElfImg::~ElfImg() { + //open elf file local + if (buffer) { + free(buffer); + buffer = nullptr; + } + //use mmap + if (header) { + munmap(header, size); + } +} + +Elf_Addr ElfImg::getSymbOffset(const char *name) const { + Elf_Addr _offset; + + //search dynmtab + if (dynsym_start != nullptr && strtab_start != nullptr) { + Elf_Sym *sym = dynsym_start; + char *strings = (char *) strtab_start; + int k; + for (k = 0; k < dynsym_count; k++, sym++) + if (strcmp(strings + sym->st_name, name) == 0) { + _offset = sym->st_value; + LOGD("find %s: %p", elf, reinterpret_cast(_offset)); + return _offset; + } + } + + //search symtab + if (symtab_start != nullptr && symstr_offset_for_symtab != 0) { + for (int i = 0; i < symtab_count; i++) { + unsigned int st_type = ELF_ST_TYPE(symtab_start[i].st_info); + char *st_name = reinterpret_cast(((size_t) header) + symstr_offset_for_symtab + + symtab_start[i].st_name); + if ((st_type == STT_FUNC || st_type == STT_OBJECT) && symtab_start[i].st_size) { + if (strcmp(st_name, name) == 0) { + _offset = symtab_start[i].st_value; + LOGD("find %s: %p", elf, reinterpret_cast(_offset)); + return _offset; + } + } + } + } + return 0; +} + +Elf_Addr ElfImg::getSymbAddress(const char *name) const { + Elf_Addr offset = getSymbOffset(name); + Elf_Addr res; + if (offset > 0 && base != nullptr) { + res = static_cast((size_t) base + offset - bias); + } else { + res = 0; + } + if (res == 0) { + LOGE("fail to get symbol %s from %s ", name, elf); + } else { + LOGD("got symbol %s form %s with %p", name, elf, (void *) res); + } + return res; +} + +void *ElfImg::getModuleBase() const { + char buff[256]; + off_t load_addr; + int found = 0; + FILE *maps = fopen("/proc/self/maps", "r"); + + char name[PATH_MAX] = {'\0'}; + + strncpy(name, elf, PATH_MAX); + { + struct stat buf{}; + while (lstat(name, &buf) == 0 && S_ISLNK(buf.st_mode)) { + if (auto s = readlink(name, name, PATH_MAX); s >= 0) { + name[s] = '\0'; + } else { + fclose(maps); + LOGE("cannot read link for %s with %s", name, strerror(errno)); + return nullptr; + } + } + } + + + +// fs::path name(elf); +// std::error_code ec; +// while(fs::is_symlink(name, ec) && !ec) { +// name = fs::read_symlink(name); +// } + + while (fgets(buff, sizeof(buff), maps)) { + if ((strstr(buff, "r-xp") || strstr(buff, "r--p")) && strstr(buff, name)) { + found = 1; + LOGD("found: %s", buff); + break; + } + } + + if (!found) { + LOGE("failed to read load address for %s", name); + fclose(maps); + return nullptr; + } + + if (sscanf(buff, "%lx", &load_addr) != 1) + LOGE("failed to read load address for %s", name); + + fclose(maps); + + LOGD("get module base %s: %lu", name, load_addr); + + return reinterpret_cast(load_addr); +} diff --git a/core/src/main/cpp/main/src/elf_util.h b/core/src/main/cpp/main/src/elf_util.h new file mode 100644 index 00000000..9159bcc4 --- /dev/null +++ b/core/src/main/cpp/main/src/elf_util.h @@ -0,0 +1,74 @@ +// From https://github.com/ganyao114/SandHook/blob/master/hooklib/src/main/cpp/includes/elf_util.h +// +// Created by Swift Gan on 2019/3/14. +// +#ifndef SANDHOOK_ELF_UTIL_H +#define SANDHOOK_ELF_UTIL_H + +#include +#include + +#if defined(__LP64__) +typedef Elf64_Ehdr Elf_Ehdr; +typedef Elf64_Shdr Elf_Shdr; +typedef Elf64_Addr Elf_Addr; +typedef Elf64_Dyn Elf_Dyn; +typedef Elf64_Rela Elf_Rela; +typedef Elf64_Sym Elf_Sym; +typedef Elf64_Off Elf_Off; + +#define ELF_R_SYM(i) ELF64_R_SYM(i) +#else +typedef Elf32_Ehdr Elf_Ehdr; +typedef Elf32_Shdr Elf_Shdr; +typedef Elf32_Addr Elf_Addr; +typedef Elf32_Dyn Elf_Dyn; +typedef Elf32_Rel Elf_Rela; +typedef Elf32_Sym Elf_Sym; +typedef Elf32_Off Elf_Off; + +#define ELF_R_SYM(i) ELF32_R_SYM(i) +#endif + +namespace SandHook { + + class ElfImg { + public: + + ElfImg(const char* elf); + + Elf_Addr getSymbOffset(const char* name) const; + + void* getModuleBase() const; + + Elf_Addr getSymbAddress(const char* name) const; + + ~ElfImg(); + + private: + const char* elf = nullptr; + void* base = nullptr; + char* buffer = nullptr; + off_t size = 0; + off_t bias = -4396; + Elf_Ehdr* header = nullptr; + Elf_Shdr* section_header = nullptr; + Elf_Shdr* symtab = nullptr; + Elf_Shdr* strtab = nullptr; + Elf_Shdr* dynsym = nullptr; + Elf_Off dynsym_count = 0; + Elf_Sym* symtab_start = nullptr; + Elf_Sym* dynsym_start = nullptr; + Elf_Sym* strtab_start = nullptr; + Elf_Off symtab_count = 0; + Elf_Off symstr_offset = 0; + Elf_Off symstr_offset_for_symtab = 0; + Elf_Off symtab_offset = 0; + Elf_Off dynsym_offset = 0; + Elf_Off symtab_size = 0; + Elf_Off dynsym_size = 0; + }; + +} + +#endif //SANDHOOK_ELF_UTIL_H diff --git a/core/src/main/cpp/main/src/native_api.cpp b/core/src/main/cpp/main/src/native_api.cpp index a33d2b2f..5a6e8414 100644 --- a/core/src/main/cpp/main/src/native_api.cpp +++ b/core/src/main/cpp/main/src/native_api.cpp @@ -57,14 +57,15 @@ namespace lspd { return ret; } - void RegisterNativeLib(const std::string& library_name) { + void RegisterNativeLib(const std::string &library_name) { LOGD("native_api: Registered %s", library_name.c_str()); moduleNativeLibs.push_back(library_name); } bool hasEnding(std::string_view fullString, std::string_view ending) { if (fullString.length() >= ending.length()) { - return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending)); + return (0 == fullString.compare(fullString.length() - ending.length(), ending.length(), + ending)); } else { return false; } @@ -89,13 +90,14 @@ namespace lspd { // the so is a module so if (UNLIKELY(hasEnding(ns, module_lib))) { LOGI("Loading module native library %s", module_lib.data()); - void* native_init_sym = dlsym(handle, "native_init"); + void *native_init_sym = dlsym(handle, "native_init"); if (UNLIKELY(native_init_sym == nullptr)) { - LOGE("Failed to get symbol \"native_init\" from library %s", module_lib.data()); + LOGE("Failed to get symbol \"native_init\" from library %s", + module_lib.data()); break; } auto native_init = reinterpret_cast(native_init_sym); - native_init(reinterpret_cast(init)); + native_init(reinterpret_cast(init)); } } @@ -107,8 +109,8 @@ namespace lspd { }); void InstallNativeAPI() { - symbol_do_dlopen = DobbySymbolResolver(nullptr, "__dl__Z9do_dlopenPKciPK17android_dlextinfoPKv"); - LOGD("InstallNativeAPI: %p", symbol_do_dlopen); - HookSymNoHandle(symbol_do_dlopen, do_dlopen); + LOGD("InstallNativeAPI: %p", sym_do_dlopen); + if (sym_do_dlopen) + HookSymNoHandle(sym_do_dlopen, do_dlopen); } -} \ No newline at end of file +} diff --git a/core/src/main/cpp/main/src/native_hook.cpp b/core/src/main/cpp/main/src/native_hook.cpp index 631b0202..6e3229f1 100644 --- a/core/src/main/cpp/main/src/native_hook.cpp +++ b/core/src/main/cpp/main/src/native_hook.cpp @@ -25,8 +25,8 @@ #include #include #include -#include "bionic_linker_restriction.h" #include "utils.h" +#include "symbol_cache.h" #include "logging.h" #include "native_api.h" #include "native_hook.h" @@ -63,28 +63,7 @@ namespace lspd { LOGI("Using api level %d", api_level); InstallRiruHooks(); // install ART hooks - if (api_level >= __ANDROID_API_Q__) { - // From Riru v22 we can't get ART handle by hooking dlopen, so we get libart.so from soinfo. - // Ref: https://android.googlesource.com/platform/bionic/+/master/linker/linker_soinfo.h - linker_iterate_soinfo([](auto soinfo) { - const char *real_path = linker_soinfo_get_realpath(soinfo); - if (real_path != nullptr && - strstr(real_path, kLibArtName.c_str()) != nullptr){ - InstallArtHooks(soinfo); - return 1; - } - return 0; - }); - if (!art_hooks_installed) { - LOGE("Android 10+ detected and libart.so can't be found in memory."); - return; - } - } else { - // do dlopen directly in Android 9- - ScopedDlHandle art_handle(kLibArtLegacyPath.c_str()); - InstallArtHooks(art_handle.Get()); - } - + InstallArtHooks(handle_libart); InstallNativeAPI(); } diff --git a/core/src/main/cpp/main/src/riru_hook.cpp b/core/src/main/cpp/main/src/riru_hook.cpp index 41e89c8f..2f39b503 100644 --- a/core/src/main/cpp/main/src/riru_hook.cpp +++ b/core/src/main/cpp/main/src/riru_hook.cpp @@ -25,7 +25,7 @@ #include #include "utils.h" #include "riru_hook.h" -#include +#include "symbol_cache.h" namespace lspd { @@ -123,21 +123,18 @@ namespace lspd { api_level = GetAndroidApiLevel(); - auto *sym = DobbySymbolResolver(nullptr, "__system_property_get"); - if (!sym) { + if (!sym_system_property_get) { LOGE("Failed to get symbol of __system_property_get"); return; } - HookSymNoHandle(sym, __system_property_get); + HookSymNoHandle(sym_system_property_get, __system_property_get); if (GetAndroidApiLevel() >= __ANDROID_API_P__) { - sym = DobbySymbolResolver(nullptr, - "_ZN7android4base11GetPropertyERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES9_"); - if (!sym) { + if (!sym_get_property) { LOGE("Failed to get symbol of _ZN7android4base11GetPropertyERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES9_"); return; } - HookSymNoHandle(sym, GetProperty); + HookSymNoHandle(sym_get_property, GetProperty); } LOGI("Riru hooks installed"); diff --git a/core/src/main/cpp/main/src/service.cpp b/core/src/main/cpp/main/src/service.cpp index 55ac34b8..b4a841da 100644 --- a/core/src/main/cpp/main/src/service.cpp +++ b/core/src/main/cpp/main/src/service.cpp @@ -26,6 +26,7 @@ #include "service.h" #include "context.h" #include "jni_helper.h" +#include "symbol_cache.h" namespace lspd { jboolean @@ -84,7 +85,7 @@ namespace lspd { "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z"); binder_class_ = env->FindClass("android/os/Binder"); - if (binder_class_) binder_class_ = (jclass)env->NewGlobalRef(binder_class_); + if (binder_class_) binder_class_ = (jclass) env->NewGlobalRef(binder_class_); binder_ctor_ = env->GetMethodID(binder_class_, "", "()V"); // Parcel @@ -133,8 +134,8 @@ namespace lspd { exec_transact_backup_methodID_ = JNI_GetMethodID(env, binderClass.get(), "execTransact", "(IJJI)Z"); auto set_table_override = reinterpret_cast(DobbySymbolResolver(nullptr, - "_ZN3art9JNIEnvExt16SetTableOverrideEPK18JNINativeInterface")); + JNINativeInterface *)>(Dlsym(handle_libart, + "_ZN3art9JNIEnvExt16SetTableOverrideEPK18JNINativeInterface")); if (!set_table_override) { LOGE("set table override not found"); } diff --git a/core/src/main/cpp/main/src/symbol_cache.cpp b/core/src/main/cpp/main/src/symbol_cache.cpp index e1da6199..73290722 100644 --- a/core/src/main/cpp/main/src/symbol_cache.cpp +++ b/core/src/main/cpp/main/src/symbol_cache.cpp @@ -23,16 +23,126 @@ // #include "symbol_cache.h" +#include "elf_util.h" #include #include "macros.h" +#include "config.h" +#include #include namespace lspd { + bool sym_initialized = false; + void *sym_do_dlopen = nullptr; + void *sym_system_property_get = nullptr; + void *sym_get_property = nullptr; + void *handle_libart = nullptr; + + struct soinfo; + + soinfo *solist = nullptr; + soinfo *somain = nullptr; + + template + inline T *getStaticVariable(const SandHook::ElfImg &linker, std::string_view name) { + auto *addr = reinterpret_cast(linker.getSymbAddress(name.data())); + return addr == nullptr ? nullptr : *addr; + } + + struct soinfo { + soinfo *next() { + return *(soinfo **) ((uintptr_t) this + solist_next_offset); + } + + const char *get_realpath() { + return get_realpath_sym ? get_realpath_sym(this) : ((std::string *) ( + (uintptr_t) this + + solist_realpath_offset))->c_str(); + } + + const char *get_soname() { + return get_soname_sym ? get_soname_sym(this) : *((const char **) ( + (uintptr_t) this + + solist_realpath_offset - sizeof(void *))); + } + + void *to_handle() { + return to_handle_sym ? to_handle_sym(this) : nullptr; + } + + static bool setup(const SandHook::ElfImg &linker) { + get_realpath_sym = reinterpret_cast(linker.getSymbAddress( + "__dl__ZNK6soinfo12get_realpathEv")); + get_soname_sym = reinterpret_cast(linker.getSymbAddress( + "__dl__ZNK6soinfo10get_sonameEv")); + to_handle_sym = reinterpret_cast(linker.getSymbAddress( + "__dl__ZN6soinfo9to_handleEv")); + auto vsdo = getStaticVariable(linker, "__dl__ZL4vdso"); + for (size_t i = 0; i < 1024 / sizeof(void *); i++) { + auto *possible_next = *(void **) ((uintptr_t) solist + i * sizeof(void *)); + if (possible_next == somain || (vsdo && possible_next == vsdo)) { + solist_next_offset = i * sizeof(void *); + return (get_realpath_sym && get_soname_sym && to_handle_sym); + } + } + LOGW("%s", "failed to search next offset"); + // shortcut + return false; + } + +#ifdef __LP64__ + inline static size_t solist_next_offset = 0x30; + constexpr static size_t solist_realpath_offset = 0x1a8; +#else + inline static size_t solist_next_offset = 0xa4; + constexpr static size_t solist_realpath_offset = 0x174; +#endif + + // since Android 8 + inline static const char *(*get_realpath_sym)(soinfo *) = nullptr; + + inline static const char *(*get_soname_sym)(soinfo *) = nullptr; + + inline static void *(*to_handle_sym)(soinfo *) = nullptr; + }; + + std::vector linker_get_solist() { + std::vector linker_solist{}; + for (auto *iter = solist; iter; iter = iter->next()) { + linker_solist.push_back(iter); + } + return linker_solist; + } + + void *findLibArt() { + for (const auto &soinfo : linker_get_solist()) { + if (const auto &real_path = soinfo->get_realpath(), &soname = soinfo->get_soname(); + (real_path && + std::string_view(real_path).find(kLibArtName) != std::string_view::npos) || + (soname && + std::string_view(soname).find(kLibArtName) != std::string_view::npos)) { + return soinfo->to_handle(); + } + } + return nullptr; + } + void InitSymbolCache() { - if (LIKELY(initialized)) return; + if (UNLIKELY(sym_initialized)) return; LOGD("InitSymbolCache"); - // TODO: set image name - symbol_do_dlopen = DobbySymbolResolver(nullptr, "__dl__Z9do_dlopenPKciPK17android_dlextinfoPKv"); - initialized = true; + auto linker = SandHook::ElfImg(kLinkerPath.c_str()); + auto libc = SandHook::ElfImg(kLibcPath.c_str()); + auto libbase = SandHook::ElfImg(kLibbasePath.c_str()); + sym_initialized = (solist = getStaticVariable(linker, "__dl__ZL6solist")) && + (somain = getStaticVariable(linker, "__dl__ZL6somain")) && + (sym_do_dlopen = reinterpret_cast(linker.getSymbAddress( + "__dl__Z9do_dlopenPKciPK17android_dlextinfoPKv"))) && + (sym_system_property_get = reinterpret_cast(libc.getSymbAddress( + "__system_property_get"))) && + (sym_get_property = reinterpret_cast(libbase.getSymbAddress( + "_ZN7android4base11GetPropertyERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEES9_"))) && + soinfo::setup(linker) && (handle_libart = findLibArt()); + if (UNLIKELY(!sym_initialized)) { + LOGE("Init symbol cache failed"); + } } } diff --git a/core/src/main/cpp/main/src/symbol_cache.h b/core/src/main/cpp/main/src/symbol_cache.h index 466950a1..8e70cbd2 100644 --- a/core/src/main/cpp/main/src/symbol_cache.h +++ b/core/src/main/cpp/main/src/symbol_cache.h @@ -24,11 +24,13 @@ #ifndef LSPOSED_SYMBOL_CACHE_H #define LSPOSED_SYMBOL_CACHE_H -#include namespace lspd { - static std::atomic_bool initialized; - static void* symbol_do_dlopen = nullptr; + extern bool sym_initialized; + extern void *sym_do_dlopen; + extern void *sym_system_property_get; + extern void *sym_get_property; + extern void *handle_libart; void InitSymbolCache(); }