From e02ce597d69796bb3251ab2ccdad89a5ed7f067b Mon Sep 17 00:00:00 2001 From: JingMatrix Date: Wed, 28 Aug 2024 20:29:33 +0200 Subject: [PATCH 1/4] [skip ci] Replace submodule Dobby by LSPlt It remains to implement HookFunction and UnhookFunction with LSPlt --- .gitmodules | 6 +++--- README.md | 3 ++- core/src/main/jni/CMakeLists.txt | 2 +- core/src/main/jni/include/native_util.h | 7 ++++--- core/src/main/jni/src/native_api.cpp | 1 - core/src/main/jni/src/symbol_cache.cpp | 1 - daemon/src/main/jni/logcat.cpp | 2 +- external/CMakeLists.txt | 3 ++- external/dobby | 1 - external/lsplt | 1 + magisk-loader/src/main/jni/src/service.cpp | 1 - 11 files changed, 14 insertions(+), 14 deletions(-) delete mode 160000 external/dobby create mode 160000 external/lsplt diff --git a/.gitmodules b/.gitmodules index c47499f11..c5eacef10 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,9 @@ [submodule "external/lsplant"] path = external/lsplant url = https://github.com/JingMatrix/LSPlant.git -[submodule "external/dobby"] - path = external/dobby - url = https://github.com/chiteroman/Dobby.git +[submodule "external/lsplt"] + path = external/lsplt + url = https://github.com/LSPosed/LSPlt [submodule "external/fmt"] path = external/fmt url = https://github.com/fmtlib/fmt.git diff --git a/README.md b/README.md index 1421f00fc..4731d1326 100644 --- a/README.md +++ b/README.md @@ -58,9 +58,10 @@ You can contribute translation [here](https://crowdin.com/project/lsposed_jingma - [Magisk](https://github.com/topjohnwu/Magisk/): makes all these possible - [Riru](https://github.com/RikkaApps/Riru): provides a way to inject code into zygote process - [XposedBridge](https://github.com/rovo89/XposedBridge): the OG Xposed framework APIs -- [Dobby](https://github.com/chiteroman/Dobby): used for inline hooking +- [LSPlt](https://github.com/LSPosed/LSPlt): used for inline hooking - [LSPlant](https://github.com/JingMatrix/LSPlant): the core ART hooking framework - [EdXposed](https://github.com/ElderDrivers/EdXposed): fork source +- ~[Dobby](https://github.com/chiteroman/Dobby): used for inline hooking~ - ~[SandHook](https://github.com/ganyao114/SandHook/): ART hooking framework for SandHook variant~ - ~[YAHFA](https://github.com/rk700/YAHFA): previous ART hooking framework~ - ~[dexmaker](https://github.com/linkedin/dexmaker) and [dalvikdx](https://github.com/JakeWharton/dalvik-dx): to dynamically generate YAHFA hooker classes~ diff --git a/core/src/main/jni/CMakeLists.txt b/core/src/main/jni/CMakeLists.txt index 03113fe58..62e5b1500 100644 --- a/core/src/main/jni/CMakeLists.txt +++ b/core/src/main/jni/CMakeLists.txt @@ -12,5 +12,5 @@ add_library(${PROJECT_NAME} STATIC ${SRC_LIST}) target_include_directories(${PROJECT_NAME} PUBLIC include) target_include_directories(${PROJECT_NAME} PRIVATE src) -target_link_libraries(${PROJECT_NAME} PUBLIC dobby_static lsplant_static log fmt-header-only) +target_link_libraries(${PROJECT_NAME} PUBLIC lsplt_static lsplant_static log fmt-header-only) target_link_libraries(${PROJECT_NAME} PRIVATE dex_builder_static) diff --git a/core/src/main/jni/include/native_util.h b/core/src/main/jni/include/native_util.h index a78c62f0c..5f06e4414 100644 --- a/core/src/main/jni/include/native_util.h +++ b/core/src/main/jni/include/native_util.h @@ -19,7 +19,6 @@ */ #include -#include "dobby.h" #include #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-value" @@ -83,7 +82,8 @@ inline int HookFunction(void *original, void *replace, void **backup) { info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr, info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); } - return DobbyHook(original, reinterpret_cast(replace), reinterpret_cast(backup)); + /* return DobbyHook(original, reinterpret_cast(replace), reinterpret_cast(backup)); */ + return 1; } inline int UnhookFunction(void *original) { @@ -94,7 +94,8 @@ inline int UnhookFunction(void *original) { info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr, info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); } - return DobbyDestroy(original); + /* return DobbyDestroy(original); */ + return 1; } inline std::string GetNativeBridgeSignature() { diff --git a/core/src/main/jni/src/native_api.cpp b/core/src/main/jni/src/native_api.cpp index cbbee764d..ab64250f0 100644 --- a/core/src/main/jni/src/native_api.cpp +++ b/core/src/main/jni/src/native_api.cpp @@ -26,7 +26,6 @@ #include "logging.h" #include "utils/hook_helper.hpp" #include -#include #include #include #include "native_util.h" diff --git a/core/src/main/jni/src/symbol_cache.cpp b/core/src/main/jni/src/symbol_cache.cpp index 4c35d0184..826333f8b 100644 --- a/core/src/main/jni/src/symbol_cache.cpp +++ b/core/src/main/jni/src/symbol_cache.cpp @@ -24,7 +24,6 @@ #include "symbol_cache.h" #include "elf_util.h" -#include #include "macros.h" #include "config.h" #include diff --git a/daemon/src/main/jni/logcat.cpp b/daemon/src/main/jni/logcat.cpp index 1dffc2632..af5aeb739 100644 --- a/daemon/src/main/jni/logcat.cpp +++ b/daemon/src/main/jni/logcat.cpp @@ -225,7 +225,7 @@ void Logcat::ProcessBuffer(struct log_msg *buf) { shortcut = true; } if (verbose_ && (shortcut || buf->id() == log_id::LOG_ID_CRASH || - entry.pid == my_pid_ || tag == "Magisk"sv || tag == "Dobby"sv || + entry.pid == my_pid_ || tag == "Magisk"sv || tag == "LSPlt"sv || tag.starts_with("Riru"sv) || tag.starts_with("zygisk"sv) || tag == "LSPlant"sv || tag.starts_with("LSPosed"sv))) [[unlikely]] { verbose_print_count_ += PrintLogLine(entry, verbose_file_.get()); diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index dacff51fe..52b67d1e5 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -103,7 +103,8 @@ target_include_directories(cxx PRIVATE ${LIBCXX_INCLUDES} ${LIBCXXABI_INCLUDES}) link_libraries(cxx) OPTION(LSPLANT_BUILD_SHARED OFF) +OPTION(LSPLT_BUILD_SHARED OFF) add_subdirectory(lsplant/lsplant/src/main/jni) -add_subdirectory(dobby) +add_subdirectory(lsplt/lsplt/src/main/jni) add_subdirectory(fmt) target_compile_definitions(fmt-header-only INTERFACE FMT_STATIC_THOUSANDS_SEPARATOR=1 FMT_USE_FLOAT=0 FMT_USE_DOUBLE=0 FMT_USE_LONG_DOUBLE=0) diff --git a/external/dobby b/external/dobby deleted file mode 160000 index 7447fd920..000000000 --- a/external/dobby +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7447fd9209bb43eba1e307f84df17613af5203dd diff --git a/external/lsplt b/external/lsplt new file mode 160000 index 000000000..cef80a97a --- /dev/null +++ b/external/lsplt @@ -0,0 +1 @@ +Subproject commit cef80a97a73184b4def9b3e1148884365fc173fd diff --git a/magisk-loader/src/main/jni/src/service.cpp b/magisk-loader/src/main/jni/src/service.cpp index 109553b82..a129a1722 100644 --- a/magisk-loader/src/main/jni/src/service.cpp +++ b/magisk-loader/src/main/jni/src/service.cpp @@ -21,7 +21,6 @@ // Created by loves on 2/7/2021. // -#include #include #include #include From 993a29ae017f3308d0e8b61226afd3e0d1c693bf Mon Sep 17 00:00:00 2001 From: JingMatrix Date: Wed, 28 Aug 2024 20:40:23 +0200 Subject: [PATCH 2/4] [skip ci] Implement (Unhook/Hook)Function (LSPlt) Co-authored-by: Stillhard --- core/src/main/jni/include/native_util.h | 66 ++++++++++++++++++------- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/core/src/main/jni/include/native_util.h b/core/src/main/jni/include/native_util.h index 5f06e4414..f4d0da490 100644 --- a/core/src/main/jni/include/native_util.h +++ b/core/src/main/jni/include/native_util.h @@ -19,13 +19,13 @@ */ #include +#include "lsplt.hpp" #include #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-value" #pragma once #include -#include "macros.h" #include "utils/jni_helper.hpp" #include "logging.h" #include "config.h" @@ -74,28 +74,60 @@ inline bool RegisterNativeMethodsInternal(JNIEnv *env, #define REGISTER_LSP_NATIVE_METHODS(class_name) \ RegisterNativeMethodsInternal(env, GetNativeBridgeSignature() + #class_name, gMethods, arraysize(gMethods)) +static std::vector> plt_hook_list = {}; +static auto scan_maps = lsplt::MapInfo::Scan(); + +inline int plt_hook(const char *lib, const char *symbol, void *callback, void **backup) { + dev_t dev = 0; + ino_t inode = 0; + for (auto map : scan_maps) { + if (map.path == lib) { + inode = map.inode; + dev = map.dev; + break; + } + } + + auto result = lsplt::RegisterHook(dev, inode, symbol, callback, backup) && lsplt::CommitHook(); + if (result) { + plt_hook_list.emplace_back(dev, inode, symbol, backup); + return 0; + } + return 1; +} + inline int HookFunction(void *original, void *replace, void **backup) { - if constexpr (isDebug) { - Dl_info info; - if (dladdr(original, &info)) - LOGD("Hooking {} ({}) from {} ({})", - info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr, - info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); + Dl_info info; + if (dladdr(original, &info)) { + if constexpr (isDebug) { + LOGD("Hooking {} ({}) from {} ({})", + info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr, + info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); + } + if (info.dli_sname != NULL && info.dli_fname != NULL) + return plt_hook(info.dli_fname, info.dli_sname, replace, backup); } - /* return DobbyHook(original, reinterpret_cast(replace), reinterpret_cast(backup)); */ - return 1; + return 1; } inline int UnhookFunction(void *original) { - if constexpr (isDebug) { - Dl_info info; - if (dladdr(original, &info)) - LOGD("Unhooking {} ({}) from {} ({})", - info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr, - info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); + Dl_info info; + if (dladdr(original, &info)) { + if constexpr (isDebug) { + LOGD("Unhooking {} ({}) from {} ({})", + info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr, + info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); + } + + for (const auto [dev, inode, symbol, backup] : plt_hook_list) { + if (info.dli_sname == symbol) { + auto result = lsplt::RegisterHook(dev, inode, symbol, backup, nullptr) + && lsplt::CommitHook(); + return 1 - result; + } + } } - /* return DobbyDestroy(original); */ - return 1; + return 1; } inline std::string GetNativeBridgeSignature() { From a407cb81245f1f2f3049d242dc5cabd12e8d8918 Mon Sep 17 00:00:00 2001 From: JingMatrix Date: Fri, 30 Aug 2024 14:44:18 +0200 Subject: [PATCH 3/4] Use Dobby for native_api LSPlt might not be capable for general native_api hooks --- .gitmodules | 5 ++++- README.md | 4 ++-- core/src/main/jni/CMakeLists.txt | 2 +- core/src/main/jni/src/native_api.cpp | 7 +++---- core/src/main/jni/src/native_api.h | 25 +++++++++++++++++++++++++ external/CMakeLists.txt | 3 ++- external/dobby | 1 + 7 files changed, 38 insertions(+), 9 deletions(-) create mode 160000 external/dobby diff --git a/.gitmodules b/.gitmodules index c5eacef10..f4ecf86c3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,12 @@ [submodule "external/lsplant"] path = external/lsplant url = https://github.com/JingMatrix/LSPlant.git +[submodule "external/dobby"] + path = external/dobby + url = https://github.com/chiteroman/Dobby.git [submodule "external/lsplt"] path = external/lsplt - url = https://github.com/LSPosed/LSPlt + url = https://github.com/LSPosed/LSPlt.git [submodule "external/fmt"] path = external/fmt url = https://github.com/fmtlib/fmt.git diff --git a/README.md b/README.md index 4731d1326..c74038385 100644 --- a/README.md +++ b/README.md @@ -58,10 +58,10 @@ You can contribute translation [here](https://crowdin.com/project/lsposed_jingma - [Magisk](https://github.com/topjohnwu/Magisk/): makes all these possible - [Riru](https://github.com/RikkaApps/Riru): provides a way to inject code into zygote process - [XposedBridge](https://github.com/rovo89/XposedBridge): the OG Xposed framework APIs -- [LSPlt](https://github.com/LSPosed/LSPlt): used for inline hooking +- [LSPlt](https://github.com/LSPosed/LSPlt): used for `libart` inline hooking +- [Dobby](https://github.com/chiteroman/Dobby): used for `native_api` inline hooking - [LSPlant](https://github.com/JingMatrix/LSPlant): the core ART hooking framework - [EdXposed](https://github.com/ElderDrivers/EdXposed): fork source -- ~[Dobby](https://github.com/chiteroman/Dobby): used for inline hooking~ - ~[SandHook](https://github.com/ganyao114/SandHook/): ART hooking framework for SandHook variant~ - ~[YAHFA](https://github.com/rk700/YAHFA): previous ART hooking framework~ - ~[dexmaker](https://github.com/linkedin/dexmaker) and [dalvikdx](https://github.com/JakeWharton/dalvik-dx): to dynamically generate YAHFA hooker classes~ diff --git a/core/src/main/jni/CMakeLists.txt b/core/src/main/jni/CMakeLists.txt index 62e5b1500..263cf6a61 100644 --- a/core/src/main/jni/CMakeLists.txt +++ b/core/src/main/jni/CMakeLists.txt @@ -12,5 +12,5 @@ add_library(${PROJECT_NAME} STATIC ${SRC_LIST}) target_include_directories(${PROJECT_NAME} PUBLIC include) target_include_directories(${PROJECT_NAME} PRIVATE src) -target_link_libraries(${PROJECT_NAME} PUBLIC lsplt_static lsplant_static log fmt-header-only) +target_link_libraries(${PROJECT_NAME} PUBLIC dobby_static lsplt_static lsplant_static log fmt-header-only) target_link_libraries(${PROJECT_NAME} PRIVATE dex_builder_static) diff --git a/core/src/main/jni/src/native_api.cpp b/core/src/main/jni/src/native_api.cpp index ab64250f0..414cf9f49 100644 --- a/core/src/main/jni/src/native_api.cpp +++ b/core/src/main/jni/src/native_api.cpp @@ -28,7 +28,6 @@ #include #include #include -#include "native_util.h" #include "elf_util.h" #include "symbol_cache.h" @@ -59,8 +58,8 @@ namespace lspd { const auto[entries] = []() { auto *entries = new(protected_page.get()) NativeAPIEntries{ .version = 2, - .hookFunc = &HookFunction, - .unhookFunc = &UnhookFunction, + .hookFunc = &DobbyHookFunction, + .unhookFunc = &DobbyUnhookFunction, }; mprotect(protected_page.get(), 4096, PROT_READ); @@ -72,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 DobbyHookFunction(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 8ba4ce1a4..41b651792 100644 --- a/core/src/main/jni/src/native_api.h +++ b/core/src/main/jni/src/native_api.h @@ -26,8 +26,11 @@ #define LSPOSED_NATIVE_API_H #include +#include #include +#include +#include "config.h" #include "utils/hook_helper.hpp" typedef int (*HookFunType)(void *func, void *replace, void **backup); @@ -48,6 +51,28 @@ namespace lspd { bool InstallNativeAPI(const lsplant::HookHandler& handler); void RegisterNativeLib(const std::string &library_name); + + inline int DobbyHookFunction(void *original, void *replace, void **backup) { + if constexpr (isDebug) { + Dl_info info; + if (dladdr(original, &info)) + LOGD("Dobby hooking {} ({}) from {} ({})", + info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr, + info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); + } + return DobbyHook(original, reinterpret_cast(replace), reinterpret_cast(backup)); + } + + inline int DobbyUnhookFunction(void *original) { + if constexpr (isDebug) { + Dl_info info; + if (dladdr(original, &info)) + LOGD("Dobby unhooking {} ({}) from {} ({})", + info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr, + info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); + } + return DobbyDestroy(original); + } } #endif //LSPOSED_NATIVE_API_H diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 52b67d1e5..439c9581a 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -104,7 +104,8 @@ link_libraries(cxx) OPTION(LSPLANT_BUILD_SHARED OFF) OPTION(LSPLT_BUILD_SHARED OFF) +add_subdirectory(dobby) +add_subdirectory(fmt) add_subdirectory(lsplant/lsplant/src/main/jni) add_subdirectory(lsplt/lsplt/src/main/jni) -add_subdirectory(fmt) target_compile_definitions(fmt-header-only INTERFACE FMT_STATIC_THOUSANDS_SEPARATOR=1 FMT_USE_FLOAT=0 FMT_USE_DOUBLE=0 FMT_USE_LONG_DOUBLE=0) diff --git a/external/dobby b/external/dobby new file mode 160000 index 000000000..7447fd920 --- /dev/null +++ b/external/dobby @@ -0,0 +1 @@ +Subproject commit 7447fd9209bb43eba1e307f84df17613af5203dd From a47ecda33ae92937c236ed2b2f974a3c3e0b6898 Mon Sep 17 00:00:00 2001 From: JingMatrix Date: Fri, 30 Aug 2024 16:50:30 +0200 Subject: [PATCH 4/4] Avoid resolving `libart` symbols twice LSPlt is only used to hook libart symbols. The file `native_util.h` is reformatted by clangd. --- core/src/main/jni/include/native_util.h | 123 ++++++++---------- core/src/main/jni/src/native_api.cpp | 8 +- core/src/main/jni/src/native_api.h | 10 +- external/lsplant | 2 +- .../src/main/jni/src/magisk_loader.cpp | 8 +- 5 files changed, 71 insertions(+), 80 deletions(-) diff --git a/core/src/main/jni/include/native_util.h b/core/src/main/jni/include/native_util.h index f4d0da490..0792930a6 100644 --- a/core/src/main/jni/include/native_util.h +++ b/core/src/main/jni/include/native_util.h @@ -19,27 +19,30 @@ */ #include -#include "lsplt.hpp" #include + +#include "elf_util.h" +#include "lsplt.hpp" +#include "symbol_cache.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-value" #pragma once #include -#include "utils/jni_helper.hpp" -#include "logging.h" -#include "config.h" + #include + +/* #include "../src/native_api.h" */ +#include "config.h" #include "config_bridge.h" +#include "logging.h" +#include "utils/jni_helper.hpp" namespace lspd { [[gnu::always_inline]] -inline bool RegisterNativeMethodsInternal(JNIEnv *env, - std::string_view class_name, - const JNINativeMethod *methods, - jint method_count) { - +inline bool RegisterNativeMethodsInternal(JNIEnv *env, std::string_view class_name, + const JNINativeMethod *methods, jint method_count) { auto clazz = Context::GetInstance()->FindClassFromCurrentLoader(env, class_name.data()); if (clazz.get() == nullptr) { LOGF("Couldn't find class: {}", class_name.data()); @@ -49,83 +52,69 @@ inline bool RegisterNativeMethodsInternal(JNIEnv *env, } #if defined(__cplusplus) -#define _NATIVEHELPER_JNI_MACRO_CAST(to) \ - reinterpret_cast +#define _NATIVEHELPER_JNI_MACRO_CAST(to) reinterpret_cast #else -#define _NATIVEHELPER_JNI_MACRO_CAST(to) \ - (to) +#define _NATIVEHELPER_JNI_MACRO_CAST(to) (to) #endif #ifndef LSP_NATIVE_METHOD -#define LSP_NATIVE_METHOD(className, functionName, signature) \ - { #functionName, \ - signature, \ - _NATIVEHELPER_JNI_MACRO_CAST(void*) (Java_org_lsposed_lspd_nativebridge_## className ## _ ## functionName) \ - } +#define LSP_NATIVE_METHOD(className, functionName, signature) \ + {#functionName, signature, \ + _NATIVEHELPER_JNI_MACRO_CAST(void *)( \ + Java_org_lsposed_lspd_nativebridge_##className##_##functionName)} #endif -#define JNI_START [[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz +#define JNI_START [[maybe_unused]] JNIEnv *env, [[maybe_unused]] jclass clazz #ifndef LSP_DEF_NATIVE_METHOD -#define LSP_DEF_NATIVE_METHOD(ret, className, functionName, ...) \ - extern "C" ret Java_org_lsposed_lspd_nativebridge_## className ## _ ## functionName (JNI_START, ## __VA_ARGS__) +#define LSP_DEF_NATIVE_METHOD(ret, className, functionName, ...) \ + extern "C" ret Java_org_lsposed_lspd_nativebridge_##className##_##functionName(JNI_START, \ + ##__VA_ARGS__) #endif -#define REGISTER_LSP_NATIVE_METHODS(class_name) \ - RegisterNativeMethodsInternal(env, GetNativeBridgeSignature() + #class_name, gMethods, arraysize(gMethods)) - -static std::vector> plt_hook_list = {}; -static auto scan_maps = lsplt::MapInfo::Scan(); - -inline int plt_hook(const char *lib, const char *symbol, void *callback, void **backup) { - dev_t dev = 0; - ino_t inode = 0; - for (auto map : scan_maps) { - if (map.path == lib) { - inode = map.inode; - dev = map.dev; - break; +#define REGISTER_LSP_NATIVE_METHODS(class_name) \ + RegisterNativeMethodsInternal(env, GetNativeBridgeSignature() + #class_name, gMethods, \ + arraysize(gMethods)) + +static dev_t dev = 0; +static ino_t inode = 0; +static std::vector> plt_hook_saved = {}; + +inline int HookArtFunction(void *original, void *callback, void **backup, bool save = true) { + const char *symbol = reinterpret_cast(original); + if (dev == 0 || inode == 0) { + auto libart_path = GetArt()->name(); + for (auto map : lsplt::MapInfo::Scan()) { + if (map.path == libart_path) { + inode = map.inode; + dev = map.dev; + break; + } } } auto result = lsplt::RegisterHook(dev, inode, symbol, callback, backup) && lsplt::CommitHook(); - if (result) { - plt_hook_list.emplace_back(dev, inode, symbol, backup); + if (result && *backup != nullptr) { + if (save) plt_hook_saved.emplace_back(symbol, backup); return 0; + /* } else if (auto addr = GetArt()->getSymbAddress(symbol); addr) { */ + /* HookFunction(addr, callback, backup); */ + } else if (*backup == nullptr && isDebug) { + LOGW("Failed to {} Art symbol {}", save ? "hook" : "unhook", symbol); } return 1; } -inline int HookFunction(void *original, void *replace, void **backup) { - Dl_info info; - if (dladdr(original, &info)) { - if constexpr (isDebug) { - LOGD("Hooking {} ({}) from {} ({})", - info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr, - info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); - } - if (info.dli_sname != NULL && info.dli_fname != NULL) - return plt_hook(info.dli_fname, info.dli_sname, replace, backup); - } - return 1; -} - -inline int UnhookFunction(void *original) { - Dl_info info; - if (dladdr(original, &info)) { - if constexpr (isDebug) { - LOGD("Unhooking {} ({}) from {} ({})", - info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr, - info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); - } +inline int UnhookArtFunction(void *original) { + std::string_view func_name = reinterpret_cast(original); + auto hook_iter = std::find_if(plt_hook_saved.begin(), plt_hook_saved.end(), + [func_name](auto record) { return record.first == func_name; }); - for (const auto [dev, inode, symbol, backup] : plt_hook_list) { - if (info.dli_sname == symbol) { - auto result = lsplt::RegisterHook(dev, inode, symbol, backup, nullptr) - && lsplt::CommitHook(); - return 1 - result; - } - } + void *stub = nullptr; + if (hook_iter != plt_hook_saved.end() && + HookArtFunction(original, *(hook_iter->second), &stub, false)) { + plt_hook_saved.erase(hook_iter); + return 0; } return 1; } @@ -136,6 +125,6 @@ inline std::string GetNativeBridgeSignature() { return signature; } -} // namespace lspd +} // namespace lspd #pragma clang diagnostic pop diff --git a/core/src/main/jni/src/native_api.cpp b/core/src/main/jni/src/native_api.cpp index 414cf9f49..148e035b5 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 = &DobbyHookFunction, - .unhookFunc = &DobbyUnhookFunction, + .hookFunc = &HookFunction, + .unhookFunc = &UnhookFunction, }; 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 DobbyHookFunction(t, r, &bk) == 0 ? bk : nullptr; + return HookFunction(t, r, &bk) == 0 ? bk : nullptr; }, .art_symbol_resolver = [](auto symbol){ return GetLinker()->getSymbAddress(symbol); @@ -133,6 +133,6 @@ namespace lspd { }; bool InstallNativeAPI(const lsplant::HookHandler & handler) { - return handler.hook(do_dlopen); + return handler.hook(do_dlopen, true); } } diff --git a/core/src/main/jni/src/native_api.h b/core/src/main/jni/src/native_api.h index 41b651792..b1203742d 100644 --- a/core/src/main/jni/src/native_api.h +++ b/core/src/main/jni/src/native_api.h @@ -52,23 +52,25 @@ namespace lspd { void RegisterNativeLib(const std::string &library_name); - inline int DobbyHookFunction(void *original, void *replace, void **backup) { + inline int HookFunction(void *original, void *replace, void **backup) { if constexpr (isDebug) { Dl_info info; if (dladdr(original, &info)) LOGD("Dobby hooking {} ({}) from {} ({})", - info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr, + info.dli_sname ? info.dli_sname : "(unknown symbol)", + info.dli_saddr ? info.dli_saddr : original, info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); } return DobbyHook(original, reinterpret_cast(replace), reinterpret_cast(backup)); } - inline int DobbyUnhookFunction(void *original) { + inline int UnhookFunction(void *original) { if constexpr (isDebug) { Dl_info info; if (dladdr(original, &info)) LOGD("Dobby unhooking {} ({}) from {} ({})", - info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr, + info.dli_sname ? info.dli_sname : "(unknown symbol)", + info.dli_saddr ? info.dli_saddr : original, info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase); } return DobbyDestroy(original); diff --git a/external/lsplant b/external/lsplant index cf06740d9..50cdaf8ac 160000 --- a/external/lsplant +++ b/external/lsplant @@ -1 +1 @@ -Subproject commit cf06740d9ea6ff5f99aa38c0f53baae7cb6b99e4 +Subproject commit 50cdaf8ac3b71597a3d3fcc52fce77dc5b3b3c45 diff --git a/magisk-loader/src/main/jni/src/magisk_loader.cpp b/magisk-loader/src/main/jni/src/magisk_loader.cpp index 72705adf8..624241b3a 100644 --- a/magisk-loader/src/main/jni/src/magisk_loader.cpp +++ b/magisk-loader/src/main/jni/src/magisk_loader.cpp @@ -119,10 +119,10 @@ namespace lspd { lsplant::InitInfo initInfo{ .inline_hooker = [](auto t, auto r) { void* bk = nullptr; - return HookFunction(t, r, &bk) == 0 ? bk : nullptr; + return HookArtFunction(t, r, &bk) == 0 ? bk : nullptr; }, .inline_unhooker = [](auto t) { - return UnhookFunction(t) == 0 ; + return UnhookArtFunction(t) == 0 ; }, .art_symbol_resolver = [](auto symbol) { return GetArt()->getSymbAddress(symbol); @@ -198,10 +198,10 @@ namespace lspd { lsplant::InitInfo initInfo{ .inline_hooker = [](auto t, auto r) { void* bk = nullptr; - return HookFunction(t, r, &bk) == 0 ? bk : nullptr; + return HookArtFunction(t, r, &bk) == 0 ? bk : nullptr; }, .inline_unhooker = [](auto t) { - return UnhookFunction(t) == 0; + return UnhookArtFunction(t) == 0; }, .art_symbol_resolver = [](auto symbol){ return GetArt()->getSymbAddress(symbol);