From e28e194682ce71fb297d0249dd81df451afe7892 Mon Sep 17 00:00:00 2001 From: JingMatrix Date: Thu, 12 Sep 2024 14:07:16 +0200 Subject: [PATCH] Indicate plt hook explicitly The file magisk_loader.cpp is reformatted using clangd --- core/src/main/jni/include/native_util.h | 10 +- core/src/main/jni/src/native_api.cpp | 6 +- core/src/main/jni/src/native_api.h | 4 +- external/lsplant | 2 +- .../src/main/jni/src/magisk_loader.cpp | 370 +++++++++--------- 5 files changed, 190 insertions(+), 202 deletions(-) diff --git a/core/src/main/jni/include/native_util.h b/core/src/main/jni/include/native_util.h index f90ae4e4..591b5599 100644 --- a/core/src/main/jni/include/native_util.h +++ b/core/src/main/jni/include/native_util.h @@ -80,7 +80,7 @@ static dev_t dev = 0; static ino_t inode = 0; static std::vector> plt_hook_saved = {}; -inline int HookArtFunction(void *art_symbol, void *callback, void **backup, bool save = true) { +inline int HookPLT(void *art_symbol, void *callback, void **backup, bool save = true) { auto symbol = reinterpret_cast(art_symbol); if (GetArt()->isStripped()) { @@ -106,25 +106,25 @@ inline int HookArtFunction(void *art_symbol, void *callback, void **backup, bool if (auto addr = GetArt()->getSymbAddress(symbol); addr) { Dl_info info; if (dladdr(addr, &info) && info.dli_sname != nullptr && strcmp(info.dli_sname, symbol) == 0) - HookFunction(addr, callback, backup); + HookInline(addr, callback, backup); } else if (*backup == nullptr && isDebug) { LOGW("Failed to {} Art symbol {}", save ? "hook" : "unhook", symbol); } return *backup == nullptr; } -inline int UnhookArtFunction(void *original) { +inline int UnhookPLT(void *original) { Dl_info info; if (!dladdr(original, &info) || info.dli_sname != nullptr) return 1; - if (!GetArt()->isStripped()) return UnhookFunction(original); + if (!GetArt()->isStripped()) return UnhookInline(original); auto hook_iter = std::find_if(plt_hook_saved.begin(), plt_hook_saved.end(), [info](auto record) { return strcmp(record.first, info.dli_sname) == 0; }); void *stub = nullptr; if (hook_iter != plt_hook_saved.end() && - HookArtFunction(original, *(hook_iter->second), &stub, false)) { + HookPLT(original, *(hook_iter->second), &stub, false)) { plt_hook_saved.erase(hook_iter); return 0; } diff --git a/core/src/main/jni/src/native_api.cpp b/core/src/main/jni/src/native_api.cpp index 1c131f27..abf93538 100644 --- a/core/src/main/jni/src/native_api.cpp +++ b/core/src/main/jni/src/native_api.cpp @@ -58,8 +58,8 @@ namespace lspd { const auto[entries] = []() { auto *entries = new(protected_page.get()) NativeAPIEntries{ .version = 2, - .hookFunc = &HookFunction, - .unhookFunc = &UnhookFunction, + .hookFunc = &HookInline, + .unhookFunc = &UnhookInline, }; mprotect(protected_page.get(), 4096, PROT_READ); @@ -71,7 +71,7 @@ namespace lspd { return InstallNativeAPI(lsplant::InitInfo { .inline_hooker = [](auto t, auto r) { void* bk = nullptr; - return HookFunction(t, r, &bk) == 0 ? bk : nullptr; + return HookInline(t, r, &bk) == 0 ? bk : nullptr; }, .art_symbol_resolver = [](auto symbol){ return GetLinker()->getSymbAddress(symbol); diff --git a/core/src/main/jni/src/native_api.h b/core/src/main/jni/src/native_api.h index b1203742..4c6c4388 100644 --- a/core/src/main/jni/src/native_api.h +++ b/core/src/main/jni/src/native_api.h @@ -52,7 +52,7 @@ namespace lspd { void RegisterNativeLib(const std::string &library_name); - inline int HookFunction(void *original, void *replace, void **backup) { + inline int HookInline(void *original, void *replace, void **backup) { if constexpr (isDebug) { Dl_info info; if (dladdr(original, &info)) @@ -64,7 +64,7 @@ namespace lspd { return DobbyHook(original, reinterpret_cast(replace), reinterpret_cast(backup)); } - inline int UnhookFunction(void *original) { + inline int UnhookInline(void *original) { if constexpr (isDebug) { Dl_info info; if (dladdr(original, &info)) diff --git a/external/lsplant b/external/lsplant index 2a18d73b..d73aa7f9 160000 --- a/external/lsplant +++ b/external/lsplant @@ -1 +1 @@ -Subproject commit 2a18d73b4d2150ca02b30938c0e82eb9aab1619e +Subproject commit d73aa7f9742b3c13084bb719962cfcd9358dd0f3 diff --git a/magisk-loader/src/main/jni/src/magisk_loader.cpp b/magisk-loader/src/main/jni/src/magisk_loader.cpp index 624241b3..13c1c221 100644 --- a/magisk-loader/src/main/jni/src/magisk_loader.cpp +++ b/magisk-loader/src/main/jni/src/magisk_loader.cpp @@ -18,6 +18,8 @@ * Copyright (C) 2021 - 2022 LSPosed Contributors */ +#include "magisk_loader.h" + #include #include #include @@ -25,7 +27,6 @@ #include "config_impl.h" #include "elf_util.h" #include "loader.h" -#include "magisk_loader.h" #include "native_util.h" #include "service.h" #include "symbol_cache.h" @@ -36,207 +37,194 @@ using namespace lsplant; static_assert(FS_IOC_SETFLAGS == LP_SELECT(0x40046602, 0x40086602)); namespace lspd { - extern int *allowUnload; - jboolean is_parasitic_manager = JNI_FALSE; +extern int *allowUnload; +jboolean is_parasitic_manager = JNI_FALSE; - constexpr int FIRST_ISOLATED_UID = 99000; - constexpr int LAST_ISOLATED_UID = 99999; - constexpr int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000; - constexpr int LAST_APP_ZYGOTE_ISOLATED_UID = 98999; - constexpr int SHARED_RELRO_UID = 1037; - constexpr int PER_USER_RANGE = 100000; +constexpr int FIRST_ISOLATED_UID = 99000; +constexpr int LAST_ISOLATED_UID = 99999; +constexpr int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000; +constexpr int LAST_APP_ZYGOTE_ISOLATED_UID = 98999; +constexpr int SHARED_RELRO_UID = 1037; +constexpr int PER_USER_RANGE = 100000; - static constexpr uid_t kAidInjected = INJECTED_AID; - static constexpr uid_t kAidInet = 3003; +static constexpr uid_t kAidInjected = INJECTED_AID; +static constexpr uid_t kAidInet = 3003; - void MagiskLoader::LoadDex(JNIEnv *env, PreloadedDex &&dex) { - auto classloader = JNI_FindClass(env, "java/lang/ClassLoader"); - auto getsyscl_mid = JNI_GetStaticMethodID( - env, classloader, "getSystemClassLoader", "()Ljava/lang/ClassLoader;"); - auto sys_classloader = JNI_CallStaticObjectMethod(env, classloader, getsyscl_mid); - if (!sys_classloader) [[unlikely]] { - LOGE("getSystemClassLoader failed!!!"); - return; - } - auto in_memory_classloader = JNI_FindClass(env, "dalvik/system/InMemoryDexClassLoader"); - auto initMid = JNI_GetMethodID(env, in_memory_classloader, "", - "(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V"); - auto byte_buffer_class = JNI_FindClass(env, "java/nio/ByteBuffer"); - auto dex_buffer = env->NewDirectByteBuffer(dex.data(), dex.size()); - if (auto my_cl = JNI_NewObject(env, in_memory_classloader, initMid, - dex_buffer, sys_classloader)) { - inject_class_loader_ = JNI_NewGlobalRef(env, my_cl); - } else { - LOGE("InMemoryDexClassLoader creation failed!!!"); - return; - } - - env->DeleteLocalRef(dex_buffer); +void MagiskLoader::LoadDex(JNIEnv *env, PreloadedDex &&dex) { + auto classloader = JNI_FindClass(env, "java/lang/ClassLoader"); + auto getsyscl_mid = JNI_GetStaticMethodID(env, classloader, "getSystemClassLoader", + "()Ljava/lang/ClassLoader;"); + auto sys_classloader = JNI_CallStaticObjectMethod(env, classloader, getsyscl_mid); + if (!sys_classloader) [[unlikely]] { + LOGE("getSystemClassLoader failed!!!"); + return; + } + auto in_memory_classloader = JNI_FindClass(env, "dalvik/system/InMemoryDexClassLoader"); + auto initMid = JNI_GetMethodID(env, in_memory_classloader, "", + "(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V"); + auto byte_buffer_class = JNI_FindClass(env, "java/nio/ByteBuffer"); + auto dex_buffer = env->NewDirectByteBuffer(dex.data(), dex.size()); + if (auto my_cl = + JNI_NewObject(env, in_memory_classloader, initMid, dex_buffer, sys_classloader)) { + inject_class_loader_ = JNI_NewGlobalRef(env, my_cl); + } else { + LOGE("InMemoryDexClassLoader creation failed!!!"); + return; } - std::string GetEntryClassName() { - const auto &obfs_map = ConfigBridge::GetInstance()->obfuscation_map(); - static auto signature = obfs_map.at("org.lsposed.lspd.core.") + "Main"; - return signature; + env->DeleteLocalRef(dex_buffer); +} + +std::string GetEntryClassName() { + const auto &obfs_map = ConfigBridge::GetInstance()->obfuscation_map(); + static auto signature = obfs_map.at("org.lsposed.lspd.core.") + "Main"; + return signature; +} + +void MagiskLoader::SetupEntryClass(JNIEnv *env) { + if (auto entry_class = FindClassFromLoader(env, GetCurrentClassLoader(), GetEntryClassName())) { + entry_class_ = JNI_NewGlobalRef(env, entry_class); } +} - void MagiskLoader::SetupEntryClass(JNIEnv *env) { - if (auto entry_class = FindClassFromLoader(env, GetCurrentClassLoader(), - GetEntryClassName())) { - entry_class_ = JNI_NewGlobalRef(env, entry_class); - } - } +void MagiskLoader::OnNativeForkSystemServerPre(JNIEnv *env) { + Service::instance()->InitService(env); + setAllowUnload(skip_); +} - void - MagiskLoader::OnNativeForkSystemServerPre(JNIEnv *env) { - Service::instance()->InitService(env); - setAllowUnload(skip_); - } - - void - MagiskLoader::OnNativeForkSystemServerPost(JNIEnv *env) { - if (!skip_) { - auto *instance = Service::instance(); - auto system_server_binder = instance->RequestSystemServerBinder(env); - if (!system_server_binder) { - LOGF("Failed to get system server binder, system server initialization failed."); - return; - } - - auto application_binder = instance->RequestApplicationBinderFromSystemServer(env, system_server_binder); - - // Call application_binder directly if application binder is available, - // or we proxy the request from system server binder - auto &&next_binder = application_binder ? application_binder : system_server_binder; - const auto [dex_fd, size] = instance->RequestLSPDex(env, next_binder); - auto obfs_map = instance->RequestObfuscationMap(env, next_binder); - ConfigBridge::GetInstance()->obfuscation_map(std::move(obfs_map)); - LoadDex(env, PreloadedDex(dex_fd, size)); - close(dex_fd); - instance->HookBridge(*this, env); - - // always inject into system server - lsplant::InitInfo initInfo{ - .inline_hooker = [](auto t, auto r) { - void* bk = nullptr; - return HookArtFunction(t, r, &bk) == 0 ? bk : nullptr; - }, - .inline_unhooker = [](auto t) { - return UnhookArtFunction(t) == 0 ; - }, - .art_symbol_resolver = [](auto symbol) { - return GetArt()->getSymbAddress(symbol); - }, - .art_symbol_prefix_resolver = [](auto symbol) { - return GetArt()->getSymbPrefixFirstAddress(symbol); - }, - }; - InitArtHooker(env, initInfo); - InitHooks(env); - SetupEntryClass(env); - FindAndCall(env, "forkCommon", - "(ZLjava/lang/String;Ljava/lang/String;Landroid/os/IBinder;)V", - JNI_TRUE, JNI_NewStringUTF(env, "system"), nullptr, application_binder, is_parasitic_manager); - GetArt(true); - } - } - - void MagiskLoader::OnNativeForkAndSpecializePre(JNIEnv *env, - jint uid, - jintArray &gids, - jstring &nice_name, - jboolean is_child_zygote, - jstring app_data_dir) { - jboolean is_manager = JNI_FALSE; - if (uid == kAidInjected) { - const JUTFString name(env, nice_name); - if (name.get() == "org.lsposed.manager"sv) { - int array_size = gids ? env->GetArrayLength(gids) : 0; - auto region = std::make_unique(array_size + 1); - auto *new_gids = env->NewIntArray(array_size + 1); - if (gids) env->GetIntArrayRegion(gids, 0, array_size, region.get()); - region.get()[array_size] = kAidInet; - env->SetIntArrayRegion(new_gids, 0, array_size + 1, region.get()); - if (gids) env->SetIntArrayRegion(gids, 0, 1, region.get() + array_size); - gids = new_gids; - nice_name = JNI_NewStringUTF(env, "com.android.shell").release(); - is_manager = JNI_TRUE; - } - } - is_parasitic_manager = is_manager; - Service::instance()->InitService(env); - const auto app_id = uid % PER_USER_RANGE; - JUTFString process_name(env, nice_name); - skip_ = false; - if (!skip_ && !app_data_dir) { - LOGD("skip injecting into {} because it has no data dir", process_name.get()); - skip_ = true; - } - if (!skip_ && is_child_zygote) { - skip_ = true; - LOGD("skip injecting into {} because it's a child zygote", process_name.get()); - } - - if (!skip_ && ((app_id >= FIRST_ISOLATED_UID && app_id <= LAST_ISOLATED_UID) || - (app_id >= FIRST_APP_ZYGOTE_ISOLATED_UID && - app_id <= LAST_APP_ZYGOTE_ISOLATED_UID) || - app_id == SHARED_RELRO_UID)) { - skip_ = true; - LOGI("skip injecting into {} because it's isolated", process_name.get()); - } - setAllowUnload(skip_); - } - - void - MagiskLoader::OnNativeForkAndSpecializePost(JNIEnv *env, jstring nice_name, jstring app_dir) { - const JUTFString process_name(env, nice_name); +void MagiskLoader::OnNativeForkSystemServerPost(JNIEnv *env) { + if (!skip_) { auto *instance = Service::instance(); - if (is_parasitic_manager) nice_name = JNI_NewStringUTF(env, "org.lsposed.manager").release(); - auto binder = skip_ ? ScopedLocalRef{env, nullptr} - : instance->RequestBinder(env, nice_name); - if (binder) { - lsplant::InitInfo initInfo{ - .inline_hooker = [](auto t, auto r) { - void* bk = nullptr; - return HookArtFunction(t, r, &bk) == 0 ? bk : nullptr; - }, - .inline_unhooker = [](auto t) { - return UnhookArtFunction(t) == 0; - }, - .art_symbol_resolver = [](auto symbol){ - return GetArt()->getSymbAddress(symbol); - }, - .art_symbol_prefix_resolver = [](auto symbol) { - return GetArt()->getSymbPrefixFirstAddress(symbol); - }, - }; - auto [dex_fd, size] = instance->RequestLSPDex(env, binder); - auto obfs_map = instance->RequestObfuscationMap(env, binder); - ConfigBridge::GetInstance()->obfuscation_map(std::move(obfs_map)); - LoadDex(env, PreloadedDex(dex_fd, size)); - close(dex_fd); - InitArtHooker(env, initInfo); - InitHooks(env); - SetupEntryClass(env); - LOGD("Done prepare"); - FindAndCall(env, "forkCommon", - "(ZLjava/lang/String;Ljava/lang/String;Landroid/os/IBinder;)V", - JNI_FALSE, nice_name, app_dir, binder); - LOGD("injected xposed into {}", process_name.get()); - setAllowUnload(false); - GetArt(true); - } else { - auto context = Context::ReleaseInstance(); - auto service = Service::ReleaseInstance(); - GetArt(true); - LOGD("skipped {}", process_name.get()); - setAllowUnload(true); + auto system_server_binder = instance->RequestSystemServerBinder(env); + if (!system_server_binder) { + LOGF("Failed to get system server binder, system server initialization failed."); + return; } + + auto application_binder = + instance->RequestApplicationBinderFromSystemServer(env, system_server_binder); + + // Call application_binder directly if application binder is available, + // or we proxy the request from system server binder + auto &&next_binder = application_binder ? application_binder : system_server_binder; + const auto [dex_fd, size] = instance->RequestLSPDex(env, next_binder); + auto obfs_map = instance->RequestObfuscationMap(env, next_binder); + ConfigBridge::GetInstance()->obfuscation_map(std::move(obfs_map)); + LoadDex(env, PreloadedDex(dex_fd, size)); + close(dex_fd); + instance->HookBridge(*this, env); + + // always inject into system server + lsplant::InitInfo initInfo{ + .inline_hooker = + [](auto t, auto r) { + void *bk = nullptr; + return HookPLT(t, r, &bk) == 0 ? bk : nullptr; + }, + .inline_unhooker = [](auto t) { return UnhookPLT(t) == 0; }, + .art_symbol_resolver = [](auto symbol) { return GetArt()->getSymbAddress(symbol); }, + .art_symbol_prefix_resolver = + [](auto symbol) { return GetArt()->getSymbPrefixFirstAddress(symbol); }, + .is_plt_hook = true}; + InitArtHooker(env, initInfo); + InitHooks(env); + SetupEntryClass(env); + FindAndCall(env, "forkCommon", + "(ZLjava/lang/String;Ljava/lang/String;Landroid/os/IBinder;)V", JNI_TRUE, + JNI_NewStringUTF(env, "system"), nullptr, application_binder, + is_parasitic_manager); + GetArt(true); + } +} + +void MagiskLoader::OnNativeForkAndSpecializePre(JNIEnv *env, jint uid, jintArray &gids, + jstring &nice_name, jboolean is_child_zygote, + jstring app_data_dir) { + jboolean is_manager = JNI_FALSE; + if (uid == kAidInjected) { + const JUTFString name(env, nice_name); + if (name.get() == "org.lsposed.manager"sv) { + int array_size = gids ? env->GetArrayLength(gids) : 0; + auto region = std::make_unique(array_size + 1); + auto *new_gids = env->NewIntArray(array_size + 1); + if (gids) env->GetIntArrayRegion(gids, 0, array_size, region.get()); + region.get()[array_size] = kAidInet; + env->SetIntArrayRegion(new_gids, 0, array_size + 1, region.get()); + if (gids) env->SetIntArrayRegion(gids, 0, 1, region.get() + array_size); + gids = new_gids; + nice_name = JNI_NewStringUTF(env, "com.android.shell").release(); + is_manager = JNI_TRUE; + } + } + is_parasitic_manager = is_manager; + Service::instance()->InitService(env); + const auto app_id = uid % PER_USER_RANGE; + JUTFString process_name(env, nice_name); + skip_ = false; + if (!skip_ && !app_data_dir) { + LOGD("skip injecting into {} because it has no data dir", process_name.get()); + skip_ = true; + } + if (!skip_ && is_child_zygote) { + skip_ = true; + LOGD("skip injecting into {} because it's a child zygote", process_name.get()); } - void MagiskLoader::setAllowUnload(bool unload) { - if (allowUnload) { - *allowUnload = unload ? 1 : 0; - } + if (!skip_ && + ((app_id >= FIRST_ISOLATED_UID && app_id <= LAST_ISOLATED_UID) || + (app_id >= FIRST_APP_ZYGOTE_ISOLATED_UID && app_id <= LAST_APP_ZYGOTE_ISOLATED_UID) || + app_id == SHARED_RELRO_UID)) { + skip_ = true; + LOGI("skip injecting into {} because it's isolated", process_name.get()); } + setAllowUnload(skip_); +} + +void MagiskLoader::OnNativeForkAndSpecializePost(JNIEnv *env, jstring nice_name, jstring app_dir) { + const JUTFString process_name(env, nice_name); + auto *instance = Service::instance(); + if (is_parasitic_manager) nice_name = JNI_NewStringUTF(env, "org.lsposed.manager").release(); + auto binder = + skip_ ? ScopedLocalRef{env, nullptr} : instance->RequestBinder(env, nice_name); + if (binder) { + lsplant::InitInfo initInfo{ + .inline_hooker = + [](auto t, auto r) { + void *bk = nullptr; + return HookPLT(t, r, &bk) == 0 ? bk : nullptr; + }, + .inline_unhooker = [](auto t) { return UnhookPLT(t) == 0; }, + .art_symbol_resolver = [](auto symbol) { return GetArt()->getSymbAddress(symbol); }, + .art_symbol_prefix_resolver = + [](auto symbol) { return GetArt()->getSymbPrefixFirstAddress(symbol); }, + .is_plt_hook = true}; + auto [dex_fd, size] = instance->RequestLSPDex(env, binder); + auto obfs_map = instance->RequestObfuscationMap(env, binder); + ConfigBridge::GetInstance()->obfuscation_map(std::move(obfs_map)); + LoadDex(env, PreloadedDex(dex_fd, size)); + close(dex_fd); + InitArtHooker(env, initInfo); + InitHooks(env); + SetupEntryClass(env); + LOGD("Done prepare"); + FindAndCall(env, "forkCommon", + "(ZLjava/lang/String;Ljava/lang/String;Landroid/os/IBinder;)V", JNI_FALSE, + nice_name, app_dir, binder); + LOGD("injected xposed into {}", process_name.get()); + setAllowUnload(false); + GetArt(true); + } else { + auto context = Context::ReleaseInstance(); + auto service = Service::ReleaseInstance(); + GetArt(true); + LOGD("skipped {}", process_name.get()); + setAllowUnload(true); + } +} + +void MagiskLoader::setAllowUnload(bool unload) { + if (allowUnload) { + *allowUnload = unload ? 1 : 0; + } +} } // namespace lspd