[core] Completely switch to ElfImg (#730)
This commit is contained in:
parent
c39b294d0f
commit
4cb731c1fb
|
|
@ -42,8 +42,7 @@ namespace art {
|
|||
return PrettyMethod(thiz, true);
|
||||
}
|
||||
|
||||
static void Setup(void *handle) {
|
||||
LOGD("art_method hook setup, handle=%p", handle);
|
||||
static void Setup(const SandHook::ElfImg &handle) {
|
||||
RETRIEVE_MEM_FUNC_SYMBOL(PrettyMethod, "_ZN3art9ArtMethod12PrettyMethodEb");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,8 +107,7 @@ namespace art {
|
|||
}
|
||||
|
||||
// @ApiSensitive(Level.MIDDLE)
|
||||
static void Setup(void *handle) {
|
||||
LOGD("Classlinker hook setup, handle=%p", handle);
|
||||
static void Setup(const SandHook::ElfImg &handle) {
|
||||
int api_level = lspd::GetAndroidApiLevel();
|
||||
size_t OFFSET_classlinker; // Get offset from art::Runtime::RunRootClinits() call in IDA
|
||||
switch (api_level) {
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ namespace art {
|
|||
destructor(this);
|
||||
}
|
||||
|
||||
static void Setup(void *handle) {
|
||||
static void Setup(const SandHook::ElfImg &handle) {
|
||||
RETRIEVE_MEM_FUNC_SYMBOL(constructor, "_ZN3art2gc23ScopedGCCriticalSectionC2EPNS_6ThreadENS0_7GcCauseENS0_13CollectorTypeE");
|
||||
RETRIEVE_MEM_FUNC_SYMBOL(destructor, "_ZN3art2gc23ScopedGCCriticalSectionD2Ev");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ namespace art {
|
|||
}
|
||||
);
|
||||
|
||||
static void DisableHiddenApi(void *handle) {
|
||||
static void DisableHiddenApi(const SandHook::ElfImg &handle) {
|
||||
|
||||
const int api_level = lspd::GetAndroidApiLevel();
|
||||
if (api_level < __ANDROID_API_P__) {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ namespace art {
|
|||
}
|
||||
});
|
||||
|
||||
static void DisableUpdateHookedMethodsCode(void *handle) {
|
||||
static void DisableUpdateHookedMethodsCode(const SandHook::ElfImg &handle) {
|
||||
lspd::HookSym(handle, UpdateMethodsCode);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ namespace art {
|
|||
JNIEnvExt(void *thiz) : HookedObject(thiz) {}
|
||||
|
||||
// @ApiSensitive(Level.MIDDLE)
|
||||
static void Setup(void *handle) {
|
||||
static void Setup(const SandHook::ElfImg &handle) {
|
||||
RETRIEVE_MEM_FUNC_SYMBOL(NewLocalRef, "_ZN3art9JNIEnvExt11NewLocalRefEPNS_6mirror6ObjectE");
|
||||
RETRIEVE_MEM_FUNC_SYMBOL(DeleteLocalRef, "_ZN3art9JNIEnvExt14DeleteLocalRefEP8_jobject");
|
||||
}
|
||||
|
|
@ -55,4 +55,4 @@ namespace art {
|
|||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ namespace art {
|
|||
Class(void *thiz) : HookedObject(thiz) {}
|
||||
|
||||
// @ApiSensitive(Level.MIDDLE)
|
||||
static void Setup(void *handle) {
|
||||
static void Setup(const SandHook::ElfImg &handle) {
|
||||
RETRIEVE_MEM_FUNC_SYMBOL(GetDescriptor, "_ZN3art6mirror5Class13GetDescriptorEPNSt3__112"
|
||||
"basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE");
|
||||
RETRIEVE_MEM_FUNC_SYMBOL(GetClassDef, "_ZN3art6mirror5Class11GetClassDefEv");
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ namespace art {
|
|||
}
|
||||
|
||||
// @ApiSensitive(Level.LOW)
|
||||
static void Setup(void *handle) {
|
||||
static void Setup(const SandHook::ElfImg &handle) {
|
||||
RETRIEVE_FIELD_SYMBOL(instance, "_ZN3art7Runtime9instance_E");
|
||||
RETRIEVE_MEM_FUNC_SYMBOL(SetJavaDebuggable, "_ZN3art7Runtime17SetJavaDebuggableEb");
|
||||
void *thiz = *reinterpret_cast<void **>(instance);
|
||||
|
|
|
|||
|
|
@ -32,22 +32,24 @@ namespace art {
|
|||
else
|
||||
return {.data=nullptr};
|
||||
}
|
||||
|
||||
CREATE_FUNC_SYMBOL_ENTRY(void *, CurrentFromGdb) {
|
||||
if (LIKELY(CurrentFromGdbSym))
|
||||
return CurrentFromGdbSym();
|
||||
return CurrentFromGdbSym();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
Thread(void *thiz) : HookedObject(thiz) {}
|
||||
|
||||
static Thread Current() {
|
||||
return Thread(CurrentFromGdb());
|
||||
}
|
||||
|
||||
static void Setup(void *handle) {
|
||||
static void Setup(const SandHook::ElfImg &handle) {
|
||||
RETRIEVE_MEM_FUNC_SYMBOL(DecodeJObject,
|
||||
"_ZNK3art6Thread13DecodeJObjectEP8_jobject");
|
||||
"_ZNK3art6Thread13DecodeJObjectEP8_jobject");
|
||||
RETRIEVE_FUNC_SYMBOL(CurrentFromGdb,
|
||||
"_ZN3art6Thread14CurrentFromGdbEv");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ namespace art {
|
|||
destructor(this);
|
||||
}
|
||||
|
||||
static void Setup(void *handle) {
|
||||
static void Setup(const SandHook::ElfImg &handle) {
|
||||
RETRIEVE_MEM_FUNC_SYMBOL(constructor, "_ZN3art16ScopedSuspendAllC2EPKcb");
|
||||
RETRIEVE_MEM_FUNC_SYMBOL(destructor, "_ZN3art16ScopedSuspendAllD2Ev");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <sys/mman.h>
|
||||
#include "config.h"
|
||||
#include "native_hook.h"
|
||||
#include "elf_util.h"
|
||||
#include <concepts>
|
||||
|
||||
#define _uintval(p) reinterpret_cast<uintptr_t>(p)
|
||||
|
|
@ -114,13 +115,18 @@ namespace lspd {
|
|||
return dlsym(handle, name);
|
||||
}
|
||||
|
||||
template<class T, class ... Args>
|
||||
inline void *Dlsym(void *handle, T first, Args... last) {
|
||||
auto ret = Dlsym(handle, first);
|
||||
[[gnu::always_inline]]
|
||||
inline void *Dlsym(const SandHook::ElfImg &handle, const char *name) {
|
||||
return handle.getSymbAddress<void *>(name);
|
||||
}
|
||||
|
||||
template<class H, class T, class ... Args>
|
||||
inline void *Dlsym(H &&handle, T first, Args... last) {
|
||||
auto ret = Dlsym(std::forward<H>(handle), first);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
return Dlsym(handle, last...);
|
||||
return Dlsym(std::forward<H>(handle), last...);
|
||||
}
|
||||
|
||||
inline int HookFunction(void *original, void *replace, void **backup) {
|
||||
|
|
@ -250,15 +256,16 @@ namespace lspd {
|
|||
}
|
||||
}
|
||||
|
||||
template<HookerType T>
|
||||
inline static bool HookSym(void *handle, T &arg) {
|
||||
auto original = Dlsym(handle, arg.sym);
|
||||
template<typename H, HookerType T>
|
||||
inline static bool HookSym(H &&handle, T &arg) {
|
||||
auto original = Dlsym(std::forward<H>(handle), arg.sym);
|
||||
return HookSymNoHandle(original, arg);
|
||||
}
|
||||
|
||||
template<HookerType T, HookerType...Args>
|
||||
inline static bool HookSyms(void *handle, T &first, Args &...rest) {
|
||||
if (!(HookSym(handle, first) || ... || HookSym(handle, rest))) {
|
||||
template<typename H, HookerType T, HookerType...Args>
|
||||
inline static bool HookSyms(H &&handle, T &first, Args &...rest) {
|
||||
if (!(HookSym(std::forward<H>(handle), first) || ... || HookSym(std::forward<H>(handle),
|
||||
rest))) {
|
||||
LOGW("Hook Fails: %s", first.sym);
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,20 +65,6 @@ namespace lspd {
|
|||
|
||||
inline static constexpr auto kLibArtName = "libart.so"_tstr;
|
||||
inline static constexpr auto kLibFwName = "libandroidfw.so"_tstr;
|
||||
inline static constexpr auto kLinkerName = LP_SELECT("linker"_tstr, "linker64"_tstr);
|
||||
inline static constexpr auto kLibcName = "libc.so"_tstr;
|
||||
inline static constexpr auto kLibbaseName = "libbase.so"_tstr;
|
||||
|
||||
inline static constexpr auto kLibBasePath =
|
||||
LP_SELECT("/system/lib/"_tstr,
|
||||
"/system/lib64/"_tstr);
|
||||
|
||||
inline static constexpr auto kBinBasePath = "/system/bin/"_tstr;
|
||||
|
||||
inline static constexpr auto kLibFwPath = kLibBasePath + kLibFwName;
|
||||
inline static constexpr auto kLinkerPath = kBinBasePath + kLinkerName;
|
||||
inline static constexpr auto kLibcPath = kLibBasePath + kLibcName;
|
||||
inline static constexpr auto kLibbasePath = kLibBasePath + kLibbaseName;
|
||||
|
||||
inline constexpr const char *BoolToString(bool b) {
|
||||
return b ? "true" : "false";
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ namespace android {
|
|||
return {nullptr, 0u};
|
||||
}
|
||||
|
||||
static bool setup(void* handle) {
|
||||
static bool setup(const SandHook::ElfImg &handle) {
|
||||
RETRIEVE_MEM_FUNC_SYMBOL(stringAt, LP_SELECT("_ZNK7android13ResStringPool8stringAtEjPj", "_ZNK7android13ResStringPool8stringAtEmPm"));
|
||||
RETRIEVE_MEM_FUNC_SYMBOL(stringAtS, LP_SELECT("_ZNK7android13ResStringPool8stringAtEj", "_ZNK7android13ResStringPool8stringAtEm"));
|
||||
return !stringAtSym || !stringAtSSym;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,12 @@ inline constexpr auto offsetOf(ElfW(Ehdr) *head, ElfW(Off) off) {
|
|||
reinterpret_cast<uintptr_t>(head) + off);
|
||||
}
|
||||
|
||||
ElfImg::ElfImg(std::string_view elf) : elf(elf) {
|
||||
ElfImg::ElfImg(std::string_view base_name) : elf(base_name) {
|
||||
if (!findModuleBase()) {
|
||||
base = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
//load elf
|
||||
int fd = open(elf.data(), O_RDONLY);
|
||||
if (fd < 0) {
|
||||
|
|
@ -120,9 +125,6 @@ ElfImg::ElfImg(std::string_view elf) : elf(elf) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//load module base
|
||||
base = getModuleBase();
|
||||
}
|
||||
|
||||
ElfW(Addr) ElfImg::ElfLookup(std::string_view name, uint32_t hash) const {
|
||||
|
|
@ -218,56 +220,44 @@ ElfImg::getSymbOffset(std::string_view name, uint32_t gnu_hash, uint32_t elf_has
|
|||
|
||||
}
|
||||
|
||||
void *ElfImg::getModuleBase() const {
|
||||
bool ElfImg::findModuleBase() {
|
||||
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.data(), 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)) {
|
||||
if ((strstr(buff, "r-xp") || strstr(buff, "r--p")) && strstr(buff, elf.data())) {
|
||||
found = 1;
|
||||
LOGD("found: %s", buff);
|
||||
std::string_view b = buff;
|
||||
if (auto begin = b.find_last_of(' '); begin != std::string_view::npos) {
|
||||
elf = b.substr(begin + 1);
|
||||
if (elf.back() == '\n') elf.pop_back();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
LOGD("update path: %s", elf.data());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
LOGE("failed to read load address for %s", name);
|
||||
LOGE("failed to read load address for %s", elf.data());
|
||||
fclose(maps);
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (char *next = buff; load_addr = strtoul(buff, &next, 16), next == buff) {
|
||||
LOGE("failed to read load address for %s", name);
|
||||
LOGE("failed to read load address for %s", elf.data());
|
||||
}
|
||||
|
||||
fclose(maps);
|
||||
|
||||
LOGD("get module base %s: %lx", name, load_addr);
|
||||
LOGD("get module base %s: %lx", elf.data(), load_addr);
|
||||
|
||||
return reinterpret_cast<void *>(load_addr);
|
||||
base = reinterpret_cast<void *>(load_addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,18 +39,25 @@ namespace SandHook {
|
|||
return getSymbOffset(name, GnuHash(name), ElfHash(name));
|
||||
}
|
||||
|
||||
void *getModuleBase() const;
|
||||
|
||||
constexpr ElfW(Addr) getSymbAddress(std::string_view name) const {
|
||||
ElfW(Addr) offset = getSymbOffset(name);
|
||||
if (offset > 0 && base != nullptr) {
|
||||
return static_cast<ElfW(Addr)>((uintptr_t) base + offset - bias);
|
||||
} else {
|
||||
LOGE("fail to get symbol %s from %s ", name.data(), elf.data());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
requires(std::is_pointer_v<T>)
|
||||
constexpr T getSymbAddress(std::string_view name) const {
|
||||
return reinterpret_cast<T>(getSymbAddress(name));
|
||||
}
|
||||
|
||||
bool isValid() const {
|
||||
return base != nullptr;
|
||||
}
|
||||
|
||||
~ElfImg();
|
||||
|
||||
private:
|
||||
|
|
@ -66,7 +73,9 @@ namespace SandHook {
|
|||
|
||||
constexpr static uint32_t GnuHash(std::string_view name);
|
||||
|
||||
std::string_view elf;
|
||||
bool findModuleBase();
|
||||
|
||||
std::string elf;
|
||||
void *base = nullptr;
|
||||
char *buffer = nullptr;
|
||||
off_t size = 0;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <framework/androidfw/resource_types.h>
|
||||
#include <byte_order.h>
|
||||
#include <HookMain.h>
|
||||
#include <elf_util.h>
|
||||
#include "native_util.h"
|
||||
#include "resources_hook.h"
|
||||
|
||||
|
|
@ -49,24 +50,24 @@ namespace lspd {
|
|||
static TYPE_GET_ATTR_NAME_ID ResXMLParser_getAttributeNameID = nullptr;
|
||||
|
||||
static bool PrepareSymbols() {
|
||||
ScopedDlHandle fw_handle(kLibFwPath.c_str());
|
||||
if (!fw_handle.IsValid()) {
|
||||
SandHook::ElfImg fw(kLibFwName);
|
||||
if (!fw.isValid()) {
|
||||
return false;
|
||||
};
|
||||
if (!(ResXMLParser_next = fw_handle.DlSym<TYPE_NEXT>(
|
||||
if (!(ResXMLParser_next = fw.getSymbAddress<TYPE_NEXT>(
|
||||
"_ZN7android12ResXMLParser4nextEv"))) {
|
||||
return false;
|
||||
}
|
||||
if (!(ResXMLParser_restart = fw_handle.DlSym<TYPE_RESTART>(
|
||||
if (!(ResXMLParser_restart = fw.getSymbAddress<TYPE_RESTART>(
|
||||
"_ZN7android12ResXMLParser7restartEv"))) {
|
||||
return false;
|
||||
};
|
||||
if (!(ResXMLParser_getAttributeNameID = fw_handle.DlSym<TYPE_GET_ATTR_NAME_ID>(
|
||||
if (!(ResXMLParser_getAttributeNameID = fw.getSymbAddress<TYPE_GET_ATTR_NAME_ID>(
|
||||
LP_SELECT("_ZNK7android12ResXMLParser18getAttributeNameIDEj",
|
||||
"_ZNK7android12ResXMLParser18getAttributeNameIDEm")))) {
|
||||
return false;
|
||||
}
|
||||
return android::ResStringPool::setup(fw_handle.Get());
|
||||
return android::ResStringPool::setup(fw);
|
||||
}
|
||||
|
||||
LSP_DEF_NATIVE_METHOD(jboolean, ResourcesHook, initXResourcesNative) {
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@ namespace lspd {
|
|||
return;
|
||||
}
|
||||
LOGD("Start to install inline hooks");
|
||||
SandHook::ElfImg &handle_libart = *art_img;
|
||||
if (!handle_libart.isValid()) {
|
||||
LOGE("Failed to fetch libart.so");
|
||||
}
|
||||
art::Runtime::Setup(handle_libart);
|
||||
art::hidden_api::DisableHiddenApi(handle_libart);
|
||||
art::art_method::Setup(handle_libart);
|
||||
|
|
@ -57,6 +61,7 @@ namespace lspd {
|
|||
art::instrumentation::DisableUpdateHookedMethodsCode(handle_libart);
|
||||
art::thread_list::ScopedSuspendAll::Setup(handle_libart);
|
||||
art::gc::ScopedGCCriticalSection::Setup(handle_libart);
|
||||
art_img.reset();
|
||||
LOGD("Inline hooks installed");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,10 +131,7 @@ namespace lspd {
|
|||
auto binderClass = JNI_FindClass(env, "android/os/Binder");
|
||||
exec_transact_backup_methodID_ = JNI_GetMethodID(env, binderClass, "execTransact",
|
||||
"(IJJI)Z");
|
||||
auto set_table_override = reinterpret_cast<void (*)(
|
||||
JNINativeInterface *)>(Dlsym(handle_libart,
|
||||
"_ZN3art9JNIEnvExt16SetTableOverrideEPK18JNINativeInterface"));
|
||||
if (!set_table_override) {
|
||||
if (!sym_set_table_override) {
|
||||
LOGE("set table override not found");
|
||||
}
|
||||
memcpy(&native_interface_replace_, env->functions, sizeof(JNINativeInterface));
|
||||
|
|
@ -142,8 +139,9 @@ namespace lspd {
|
|||
call_boolean_method_va_backup_ = env->functions->CallBooleanMethodV;
|
||||
native_interface_replace_.CallBooleanMethodV = &call_boolean_method_va_replace;
|
||||
|
||||
if (set_table_override != nullptr) {
|
||||
set_table_override(&native_interface_replace_);
|
||||
if (sym_set_table_override != nullptr) {
|
||||
reinterpret_cast<void (*)(JNINativeInterface *)>(sym_set_table_override)(
|
||||
&native_interface_replace_);
|
||||
}
|
||||
|
||||
LOGD("Done InitService");
|
||||
|
|
|
|||
|
|
@ -33,129 +33,43 @@
|
|||
namespace lspd {
|
||||
bool sym_initialized = false;
|
||||
void *sym_do_dlopen = nullptr;
|
||||
void *handle_libart = nullptr;
|
||||
void *sym_openInMemoryDexFilesNative = nullptr;
|
||||
void *sym_createCookieWithArray = nullptr;
|
||||
void *sym_createCookieWithDirectBuffer = nullptr;
|
||||
void *sym_openDexFileNative = nullptr;
|
||||
void *sym_setTrusted = nullptr;
|
||||
void *sym_set_table_override = nullptr;
|
||||
std::unique_ptr<SandHook::ElfImg> art_img = nullptr;
|
||||
|
||||
struct soinfo;
|
||||
|
||||
soinfo *solist = nullptr;
|
||||
soinfo *somain = nullptr;
|
||||
|
||||
template<typename T>
|
||||
constexpr inline T *getStaticVariable(const SandHook::ElfImg &linker, std::string_view name) {
|
||||
auto *addr = reinterpret_cast<T **>(linker.getSymbAddress(name));
|
||||
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<decltype(get_realpath_sym)>(linker.getSymbAddress(
|
||||
"__dl__ZNK6soinfo12get_realpathEv"));
|
||||
get_soname_sym = reinterpret_cast<decltype(get_soname_sym)>(linker.getSymbAddress(
|
||||
"__dl__ZNK6soinfo10get_sonameEv"));
|
||||
to_handle_sym = reinterpret_cast<decltype(to_handle_sym)>(linker.getSymbAddress(
|
||||
"__dl__ZN6soinfo9to_handleEv"));
|
||||
auto vsdo = getStaticVariable<soinfo>(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<soinfo *> linker_get_solist() {
|
||||
std::vector<soinfo *> 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)) {
|
||||
auto art = SandHook::ElfImg(real_path);
|
||||
auto api_level = GetAndroidApiLevel();
|
||||
if (api_level < __ANDROID_API_P__ || (
|
||||
(sym_openDexFileNative = reinterpret_cast<void *>(art.getSymbAddress(
|
||||
"_ZN3artL25DexFile_openDexFileNativeEP7_JNIEnvP7_jclassP8_jstringS5_iP8_jobjectP13_jobjectArray"))) &&
|
||||
bool findLibArt() {
|
||||
art_img = std::make_unique<SandHook::ElfImg>(kLibArtName);
|
||||
if (!art_img->isValid()) return false;
|
||||
auto api_level = GetAndroidApiLevel();
|
||||
return (sym_set_table_override = art_img->getSymbAddress<void *>(
|
||||
"_ZN3art9JNIEnvExt16SetTableOverrideEPK18JNINativeInterface")) != nullptr
|
||||
&& (api_level < __ANDROID_API_P__ || (
|
||||
(sym_openDexFileNative = art_img->getSymbAddress<void *>(
|
||||
"_ZN3artL25DexFile_openDexFileNativeEP7_JNIEnvP7_jclassP8_jstringS5_iP8_jobjectP13_jobjectArray")) &&
|
||||
(
|
||||
(sym_openInMemoryDexFilesNative = art_img->getSymbAddress<void *>(
|
||||
"_ZN3artL34DexFile_openInMemoryDexFilesNativeEP7_JNIEnvP7_jclassP13_jobjectArrayS5_P10_jintArrayS7_P8_jobjectS5_")) ||
|
||||
(
|
||||
(sym_openInMemoryDexFilesNative = reinterpret_cast<void *>(art.getSymbAddress(
|
||||
"_ZN3artL34DexFile_openInMemoryDexFilesNativeEP7_JNIEnvP7_jclassP13_jobjectArrayS5_P10_jintArrayS7_P8_jobjectS5_"))) ||
|
||||
(
|
||||
(sym_createCookieWithArray = reinterpret_cast<void *>(art.getSymbAddress(
|
||||
"_ZN3artL29DexFile_createCookieWithArrayEP7_JNIEnvP7_jclassP11_jbyteArrayii"))) &&
|
||||
(sym_createCookieWithDirectBuffer = reinterpret_cast<void *>(art.getSymbAddress(
|
||||
"_ZN3artL36DexFile_createCookieWithDirectBufferEP7_JNIEnvP7_jclassP8_jobjectii")))
|
||||
)
|
||||
) &&
|
||||
(sym_setTrusted = reinterpret_cast<void *>(art.getSymbAddress(
|
||||
"_ZN3artL18DexFile_setTrustedEP7_JNIEnvP7_jclassP8_jobject")))))
|
||||
return soinfo->to_handle();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
(sym_createCookieWithArray = art_img->getSymbAddress<void *>(
|
||||
"_ZN3artL29DexFile_createCookieWithArrayEP7_JNIEnvP7_jclassP11_jbyteArrayii")) &&
|
||||
(sym_createCookieWithDirectBuffer = art_img->getSymbAddress<void *>(
|
||||
"_ZN3artL36DexFile_createCookieWithDirectBufferEP7_JNIEnvP7_jclassP8_jobjectii"))
|
||||
)
|
||||
) &&
|
||||
(sym_setTrusted = art_img->getSymbAddress<void *>(
|
||||
"_ZN3artL18DexFile_setTrustedEP7_JNIEnvP7_jclassP8_jobject"))));
|
||||
}
|
||||
|
||||
void InitSymbolCache() {
|
||||
if (UNLIKELY(sym_initialized)) return;
|
||||
LOGD("InitSymbolCache");
|
||||
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<soinfo>(linker, "__dl__ZL6solist")) &&
|
||||
(somain = getStaticVariable<soinfo>(linker, "__dl__ZL6somain")) &&
|
||||
(sym_do_dlopen = reinterpret_cast<void *>(linker.getSymbAddress(
|
||||
"__dl__Z9do_dlopenPKciPK17android_dlextinfoPKv"))) &&
|
||||
soinfo::setup(linker) && (handle_libart = findLibArt());
|
||||
sym_initialized = findLibArt();
|
||||
if (UNLIKELY(!sym_initialized)) {
|
||||
art_img.reset();
|
||||
LOGE("Init symbol cache failed");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,15 +25,21 @@
|
|||
#ifndef LSPOSED_SYMBOL_CACHE_H
|
||||
#define LSPOSED_SYMBOL_CACHE_H
|
||||
|
||||
#include <memory>
|
||||
namespace SandHook {
|
||||
class ElfImg;
|
||||
}
|
||||
|
||||
namespace lspd {
|
||||
extern bool sym_initialized;
|
||||
extern std::unique_ptr<SandHook::ElfImg> art_img;
|
||||
extern void *sym_do_dlopen;
|
||||
extern void *handle_libart;
|
||||
extern void *sym_openInMemoryDexFilesNative;
|
||||
extern void *sym_createCookieWithArray;
|
||||
extern void *sym_createCookieWithDirectBuffer;
|
||||
extern void *sym_openDexFileNative;
|
||||
extern void *sym_setTrusted;
|
||||
extern void *sym_set_table_override;
|
||||
|
||||
void InitSymbolCache();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue