You've already forked ReZygisk
mirror of
https://github.com/PerformanC/ReZygisk.git
synced 2025-09-06 06:37:01 +00:00
fix: linker64 static symbols lookup with suffix
On Android 15+ in some devices, the symbol names of some static variables such as `solist`, has a `llvm` suffix in its exported name. Current commit handles this case and close #63 as fixed.
This commit is contained in:
@@ -179,6 +179,7 @@ ElfW(Addr) ElfImg::LinearLookup(std::string_view name) const {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (auto i = symtabs_.find(name); i != symtabs_.end()) {
|
||||
return i->second->st_value;
|
||||
} else {
|
||||
@@ -186,6 +187,33 @@ ElfW(Addr) ElfImg::LinearLookup(std::string_view name) const {
|
||||
}
|
||||
}
|
||||
|
||||
std::string_view ElfImg::LinearLookupByPrefix(std::string_view name) const {
|
||||
if (symtabs_.empty()) {
|
||||
symtabs_.reserve(symtab_count);
|
||||
if (symtab_start != nullptr && symstr_offset_for_symtab != 0) {
|
||||
for (ElfW(Off) i = 0; i < symtab_count; i++) {
|
||||
unsigned int st_type = ELF_ST_TYPE(symtab_start[i].st_info);
|
||||
const char *st_name = offsetOf<const char *>(header, symstr_offset_for_symtab +
|
||||
symtab_start[i].st_name);
|
||||
if ((st_type == STT_FUNC || st_type == STT_OBJECT) && symtab_start[i].st_size) {
|
||||
symtabs_.emplace(st_name, &symtab_start[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto size = name.size();
|
||||
for (auto symtab : symtabs_) {
|
||||
if (symtab.first.size() < size) continue;
|
||||
|
||||
if (symtab.first.substr(0, size) == name) {
|
||||
return symtab.first;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
ElfImg::~ElfImg() {
|
||||
//open elf file local
|
||||
|
||||
@@ -48,6 +48,10 @@ namespace SandHook {
|
||||
}
|
||||
}
|
||||
|
||||
std::string_view findSymbolNameByPrefix(std::string_view prefix) const {
|
||||
return LinearLookupByPrefix(prefix);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr T getSymbAddress(std::string_view name) const {
|
||||
return reinterpret_cast<T>(getSymbAddress(name));
|
||||
@@ -72,6 +76,8 @@ namespace SandHook {
|
||||
|
||||
ElfW(Addr) LinearLookup(std::string_view name) const;
|
||||
|
||||
std::string_view LinearLookupByPrefix(std::string_view name) const;
|
||||
|
||||
constexpr static uint32_t ElfHash(std::string_view name);
|
||||
|
||||
constexpr static uint32_t GnuHash(std::string_view name);
|
||||
|
||||
@@ -6,98 +6,127 @@
|
||||
#include <string>
|
||||
#include "elf_util.h"
|
||||
|
||||
namespace SoList
|
||||
{
|
||||
class SoInfo {
|
||||
public:
|
||||
#ifdef __LP64__
|
||||
namespace SoList {
|
||||
class SoInfo {
|
||||
public:
|
||||
#ifdef __LP64__
|
||||
inline static size_t solist_next_offset = 0x30;
|
||||
constexpr static size_t solist_realpath_offset = 0x1a8;
|
||||
#else
|
||||
#else
|
||||
inline static size_t solist_next_offset = 0xa4;
|
||||
constexpr static size_t solist_realpath_offset = 0x174;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
inline static const char *(*get_realpath_sym)(SoInfo *) = nullptr;
|
||||
inline static const char *(*get_soname_sym)(SoInfo *) = nullptr;
|
||||
inline static const char *(*get_realpath_sym)(SoInfo *) = NULL;
|
||||
inline static const char *(*get_soname_sym)(SoInfo *) = NULL;
|
||||
|
||||
inline SoInfo *get_next() {
|
||||
return *(SoInfo **) ((uintptr_t) this + solist_next_offset);
|
||||
}
|
||||
inline SoInfo *get_next() {
|
||||
return *(SoInfo **) ((uintptr_t) this + solist_next_offset);
|
||||
}
|
||||
|
||||
inline const char *get_path() {
|
||||
return get_realpath_sym ? get_realpath_sym(this) : ((std::string *) ((uintptr_t) this + solist_realpath_offset))->c_str();
|
||||
}
|
||||
inline const char *get_path() {
|
||||
if (get_realpath_sym) return get_realpath_sym(this);
|
||||
|
||||
inline const char *get_name() {
|
||||
return get_soname_sym ? get_soname_sym(this) : *((const char **) ((uintptr_t) this + solist_realpath_offset - sizeof(void *)));
|
||||
}
|
||||
return ((std::string *) ((uintptr_t) this + solist_realpath_offset))->c_str();
|
||||
}
|
||||
|
||||
void nullify_name() {
|
||||
const char** name = (const char**)get_soname_sym(this);
|
||||
inline const char *get_name() {
|
||||
if (get_soname_sym) return get_soname_sym(this);
|
||||
|
||||
static const char* empty_string = "";
|
||||
*name = reinterpret_cast<const char *>(&empty_string);
|
||||
}
|
||||
return ((std::string *) ((uintptr_t) this + solist_realpath_offset - sizeof(void *)))->c_str();
|
||||
}
|
||||
|
||||
void nullify_path() {
|
||||
const char** name = (const char**)get_realpath_sym(this);
|
||||
void nullify_name() {
|
||||
const char **name = (const char**)get_soname_sym(this);
|
||||
|
||||
static const char* empty_string = "";
|
||||
*name = reinterpret_cast<const char *>(&empty_string);
|
||||
}
|
||||
};
|
||||
static const char *empty_string = "";
|
||||
*name = reinterpret_cast<const char *>(&empty_string);
|
||||
}
|
||||
|
||||
static SoInfo *solist = nullptr;
|
||||
static SoInfo *somain = nullptr;
|
||||
void nullify_path() {
|
||||
const char **name = (const char**)get_realpath_sym(this);
|
||||
|
||||
template<typename T>
|
||||
inline T *getStaticPointer(const SandHook::ElfImg &linker, const char* name)
|
||||
{
|
||||
auto *addr = reinterpret_cast<T **>(linker.getSymbAddress(name));
|
||||
return addr == nullptr ? nullptr : *addr;
|
||||
static const char *empty_string = "";
|
||||
*name = reinterpret_cast<const char *>(&empty_string);
|
||||
}
|
||||
};
|
||||
|
||||
static SoInfo *solist = NULL;
|
||||
static SoInfo *somain = NULL;
|
||||
|
||||
template<typename T>
|
||||
inline T *getStaticPointer(const SandHook::ElfImg &linker, const char *name) {
|
||||
auto *addr = reinterpret_cast<T **>(linker.getSymbAddress(name));
|
||||
|
||||
return addr == NULL ? NULL : *addr;
|
||||
}
|
||||
|
||||
static void NullifySoName(const char* target_name) {
|
||||
for (auto *iter = solist; iter; iter = iter->get_next()) {
|
||||
if (iter->get_name() && iter->get_path() && strstr(iter->get_path(), target_name)) {
|
||||
iter->nullify_path();
|
||||
LOGI("Cleared SOList entry for %s", target_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void NullifySoName(const char* target_name) {
|
||||
for (auto *iter = solist; iter; iter = iter->get_next()) {
|
||||
if (iter->get_name() && iter->get_path() && strstr(iter->get_path(), target_name)) {
|
||||
iter->nullify_path();
|
||||
LOGI("Cleared SOList entry for %s", target_name);
|
||||
}
|
||||
}
|
||||
for (auto *iter = somain; iter; iter = iter->get_next()) {
|
||||
if (iter->get_name() && iter->get_path() && strstr(iter->get_path(), target_name)) {
|
||||
iter->nullify_path();
|
||||
|
||||
for (auto *iter = somain; iter; iter = iter->get_next()) {
|
||||
if (iter->get_name() && iter->get_path() && strstr(iter->get_path(), target_name)) {
|
||||
iter->nullify_path();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool Initialize() {
|
||||
SandHook::ElfImg linker("/linker");
|
||||
|
||||
/* INFO: Since Android 15, the symbol names for the linker have a suffix,
|
||||
this makes it impossible to hardcode the symbol names. To allow
|
||||
this to work on all versions, we need to iterate over the loaded
|
||||
symbols and find the correct ones.
|
||||
|
||||
See #63 for more information.
|
||||
*/
|
||||
|
||||
std::string_view solist_sym_name = linker.findSymbolNameByPrefix("__dl__ZL6solist");
|
||||
if (solist_sym_name.empty()) return false;
|
||||
|
||||
/* INFO: The size isn't a magic number, it's the size for the string: .llvm.7690929523238822858 */
|
||||
char llvm_sufix[25 + 1];
|
||||
|
||||
if (solist_sym_name.length() != strlen("__dl__ZL6solist")) {
|
||||
strncpy(llvm_sufix, solist_sym_name.data() + strlen("__dl__ZL6solist"), sizeof(llvm_sufix));
|
||||
} else {
|
||||
llvm_sufix[0] = '\0';
|
||||
}
|
||||
|
||||
static bool Initialize() {
|
||||
SandHook::ElfImg linker("/linker");
|
||||
solist = getStaticPointer<SoInfo>(linker, "__dl__ZL6solist");
|
||||
somain = getStaticPointer<SoInfo>(linker, "__dl__ZL6somain");
|
||||
solist = getStaticPointer<SoInfo>(linker, solist_sym_name.data());
|
||||
if (solist == NULL) return false;
|
||||
|
||||
if (solist != nullptr && somain != nullptr)
|
||||
{
|
||||
SoInfo::get_realpath_sym = reinterpret_cast<decltype(SoInfo::get_realpath_sym)>(linker.getSymbAddress("__dl__ZNK6soinfo12get_realpathEv"));
|
||||
SoInfo::get_soname_sym = reinterpret_cast<decltype(SoInfo::get_soname_sym)>(linker.getSymbAddress("__dl__ZNK6soinfo10get_sonameEv"));
|
||||
auto vsdo = getStaticPointer<SoInfo>(linker, "__dl__ZL4vdso");
|
||||
char somain_sym_name[sizeof("__dl__ZL6somain") + sizeof(llvm_sufix)];
|
||||
snprintf(somain_sym_name, sizeof(somain_sym_name), "__dl__ZL6somain%s", llvm_sufix);
|
||||
|
||||
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 != nullptr && possible_next == vsdo))
|
||||
{
|
||||
SoInfo::solist_next_offset = i * sizeof(void *);
|
||||
break;
|
||||
}
|
||||
}
|
||||
char vsdo_sym_name[sizeof("__dl__ZL4vdso") + sizeof(llvm_sufix)];
|
||||
snprintf(vsdo_sym_name, sizeof(vsdo_sym_name), "__dl__ZL4vdso%s", llvm_sufix);
|
||||
|
||||
return (SoInfo::get_realpath_sym != nullptr && SoInfo::get_soname_sym != nullptr);
|
||||
}
|
||||
somain = getStaticPointer<SoInfo>(linker, somain_sym_name);
|
||||
if (somain == NULL) return false;
|
||||
|
||||
return false;
|
||||
auto vsdo = getStaticPointer<SoInfo>(linker, vsdo_sym_name);
|
||||
|
||||
SoInfo::get_realpath_sym = reinterpret_cast<decltype(SoInfo::get_realpath_sym)>(linker.getSymbAddress("__dl__ZNK6soinfo12get_realpathEv"));
|
||||
SoInfo::get_soname_sym = reinterpret_cast<decltype(SoInfo::get_soname_sym)>(linker.getSymbAddress("__dl__ZNK6soinfo10get_sonameEv"));
|
||||
|
||||
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 != NULL && possible_next == vsdo)) {
|
||||
SoInfo::solist_next_offset = i * sizeof(void *);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (SoInfo::get_realpath_sym != NULL && SoInfo::get_soname_sym != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user