From d4e00eac40382d76d95c074254397a1f150ef186 Mon Sep 17 00:00:00 2001 From: JingMatrix Date: Sat, 31 Aug 2024 15:51:02 +0200 Subject: [PATCH] Use LSPlt only for Android 15 For non-stripped `libart.so` ELFs, their plt tables are too small for inline hook. --- core/src/main/jni/include/elf_util.h | 4 +++ core/src/main/jni/include/native_util.h | 42 +++++++++++++++---------- core/src/main/jni/src/elf_util.cpp | 2 +- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/core/src/main/jni/include/elf_util.h b/core/src/main/jni/include/elf_util.h index ebe4df67..f3faa936 100644 --- a/core/src/main/jni/include/elf_util.h +++ b/core/src/main/jni/include/elf_util.h @@ -74,6 +74,10 @@ namespace SandHook { return base != nullptr; } + bool isStripped() const { + return debugdata_offset != 0 && debugdata_size != 0; + } + const std::string name() const { return elf; } diff --git a/core/src/main/jni/include/native_util.h b/core/src/main/jni/include/native_util.h index 68bf7b01..3eb98fb6 100644 --- a/core/src/main/jni/include/native_util.h +++ b/core/src/main/jni/include/native_util.h @@ -80,23 +80,30 @@ 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) { - auto 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; +inline int HookArtFunction(void *art_symbol, void *callback, void **backup, bool save = true) { + auto symbol = *reinterpret_cast(art_symbol); + + if (GetArt()->isStripped()) { + 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 && *backup != nullptr) { + if (save) plt_hook_saved.emplace_back(symbol, backup); + return 0; + } } - auto result = lsplt::RegisterHook(dev, inode, symbol, callback, backup) && lsplt::CommitHook(); - if (result && *backup != nullptr) { - if (save) plt_hook_saved.emplace_back(symbol, backup); - } else if (auto addr = GetArt()->getSymbAddress(symbol); addr) { + if (auto addr = GetArt()->getSymbAddress(symbol); addr) { Dl_info info; if (dladdr(addr, &info) && info.dli_sname != nullptr && info.dli_sname == symbol) HookFunction(addr, callback, backup); @@ -107,10 +114,13 @@ inline int HookArtFunction(void *original, void *callback, void **backup, bool s } 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; }); + Dl_info info; + if (!dladdr(original, &info) || info.dli_sname != nullptr) return 1; + if (!GetArt()->isStripped()) return UnhookFunction(original); + + auto hook_iter = std::find_if(plt_hook_saved.begin(), plt_hook_saved.end(), + [info](auto record) { return record.first == info.dli_sname; }); void *stub = nullptr; if (hook_iter != plt_hook_saved.end() && HookArtFunction(original, *(hook_iter->second), &stub, false)) { diff --git a/core/src/main/jni/src/elf_util.cpp b/core/src/main/jni/src/elf_util.cpp index 07e9e10c..d28dd5f6 100644 --- a/core/src/main/jni/src/elf_util.cpp +++ b/core/src/main/jni/src/elf_util.cpp @@ -58,7 +58,7 @@ ElfImg::ElfImg(std::string_view base_name) : elf(base_name) { close(fd); parse(header); - if (debugdata_offset != 0 && debugdata_size != 0) { + if (isStripped()) { if (xzdecompress()) { header_debugdata = reinterpret_cast(elf_debugdata.data()); parse(header_debugdata);