You've already forked ReZygisk
mirror of
https://github.com/PerformanC/ReZygisk.git
synced 2025-09-06 06:37:01 +00:00
improve: drop soinfo records of loaded modules
In Bionic linker, the `soinfo` structure has a field `next`, which points to the next loaded library in a linked list consisting of all loaded libraries.
Hence, an injected process can easily find all loaded libraries.
Previously in ReZygisk, module library records are hidden by setting the `pathname` field to be empty, which is futile but easier to detect.
Current idea of dropping record can be found in the following commit:
5d635e8c66
This commit is contained in:
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "elf_util.h"
|
#include "elf_util.h"
|
||||||
|
#include "logging.h"
|
||||||
|
|
||||||
namespace SoList {
|
namespace SoList {
|
||||||
class SoInfo {
|
class SoInfo {
|
||||||
@@ -36,23 +37,59 @@ namespace SoList {
|
|||||||
return ((std::string *) ((uintptr_t) this + solist_realpath_offset - sizeof(void *)))->c_str();
|
return ((std::string *) ((uintptr_t) this + solist_realpath_offset - sizeof(void *)))->c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nullify_name() {
|
void set_next(SoInfo *si) {
|
||||||
const char **name = (const char**)get_soname_sym(this);
|
*(SoInfo **) ((uintptr_t) this + solist_next_offset) = si;
|
||||||
|
|
||||||
static const char *empty_string = "";
|
|
||||||
*name = reinterpret_cast<const char *>(&empty_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nullify_path() {
|
|
||||||
const char **name = (const char**)get_realpath_sym(this);
|
|
||||||
|
|
||||||
static const char *empty_string = "";
|
|
||||||
*name = reinterpret_cast<const char *>(&empty_string);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ProtectedDataGuard {
|
||||||
|
public:
|
||||||
|
ProtectedDataGuard() {
|
||||||
|
if (ctor != nullptr)
|
||||||
|
(this->*ctor)();
|
||||||
|
}
|
||||||
|
|
||||||
|
~ProtectedDataGuard() {
|
||||||
|
if (dtor != nullptr)
|
||||||
|
(this->*dtor)();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool setup(const SandHook::ElfImg &linker) {
|
||||||
|
ctor = MemFunc{.data = {.p = reinterpret_cast<void *>(linker.getSymbAddress(
|
||||||
|
"__dl__ZN18ProtectedDataGuardC2Ev")), .adj = 0}}.f;
|
||||||
|
dtor = MemFunc{.data = {.p = reinterpret_cast<void *>(linker.getSymbAddress(
|
||||||
|
"__dl__ZN18ProtectedDataGuardD2Ev")), .adj = 0}}.f;
|
||||||
|
return ctor != nullptr && dtor != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtectedDataGuard(const ProtectedDataGuard &) = delete;
|
||||||
|
|
||||||
|
void operator=(const ProtectedDataGuard &) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
using FuncType = void (ProtectedDataGuard::*)();
|
||||||
|
|
||||||
|
static FuncType ctor;
|
||||||
|
static FuncType dtor;
|
||||||
|
|
||||||
|
union MemFunc {
|
||||||
|
FuncType f;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
void *p;
|
||||||
|
std::ptrdiff_t adj;
|
||||||
|
} data;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static SoInfo *solist = NULL;
|
static SoInfo *solist = NULL;
|
||||||
static SoInfo *somain = NULL;
|
static SoInfo *somain = NULL;
|
||||||
|
static SoInfo **sonext = NULL;
|
||||||
|
ProtectedDataGuard::FuncType ProtectedDataGuard::ctor = NULL;
|
||||||
|
ProtectedDataGuard::FuncType ProtectedDataGuard::dtor = NULL;
|
||||||
|
|
||||||
|
static bool Initialize();
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T *getStaticPointer(const SandHook::ElfImg &linker, const char *name) {
|
inline T *getStaticPointer(const SandHook::ElfImg &linker, const char *name) {
|
||||||
@@ -61,25 +98,28 @@ namespace SoList {
|
|||||||
return addr == NULL ? NULL : *addr;
|
return addr == NULL ? NULL : *addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void NullifySoName(const char* target_name) {
|
static void DropSoPath(const char* target_path) {
|
||||||
for (auto *iter = solist; iter; iter = iter->get_next()) {
|
if (solist == NULL && !Initialize()) {
|
||||||
if (iter->get_name() && iter->get_path() && strstr(iter->get_path(), target_name)) {
|
LOGE("Failed to initialize solist");
|
||||||
iter->nullify_path();
|
return;
|
||||||
LOGI("Cleared SOList entry for %s", target_name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
SoInfo *prev = NULL;
|
||||||
for (auto *iter = somain; iter; iter = iter->get_next()) {
|
for (auto iter = solist; iter; iter = iter->get_next()) {
|
||||||
if (iter->get_name() && iter->get_path() && strstr(iter->get_path(), target_name)) {
|
if (prev != NULL && iter->get_name() && iter->get_path() && strstr(iter->get_path(), target_path)) {
|
||||||
iter->nullify_path();
|
SoList::ProtectedDataGuard guard;
|
||||||
|
prev->set_next(iter->get_next());
|
||||||
break;
|
if (iter == *sonext) {
|
||||||
|
*sonext = prev;
|
||||||
|
}
|
||||||
|
LOGI("Dropped solist record for %s loaded at %s", iter->get_name(), iter->get_path());
|
||||||
}
|
}
|
||||||
|
prev = iter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Initialize() {
|
static bool Initialize() {
|
||||||
SandHook::ElfImg linker("/linker");
|
SandHook::ElfImg linker("/linker");
|
||||||
|
if (!ProtectedDataGuard::setup(linker)) return false;
|
||||||
|
|
||||||
/* INFO: Since Android 15, the symbol names for the linker have a suffix,
|
/* 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 makes it impossible to hardcode the symbol names. To allow
|
||||||
@@ -107,13 +147,20 @@ namespace SoList {
|
|||||||
char somain_sym_name[sizeof("__dl__ZL6somain") + sizeof(llvm_sufix)];
|
char somain_sym_name[sizeof("__dl__ZL6somain") + sizeof(llvm_sufix)];
|
||||||
snprintf(somain_sym_name, sizeof(somain_sym_name), "__dl__ZL6somain%s", llvm_sufix);
|
snprintf(somain_sym_name, sizeof(somain_sym_name), "__dl__ZL6somain%s", llvm_sufix);
|
||||||
|
|
||||||
|
char sonext_sym_name[sizeof("__dl__ZL6sonext") + sizeof(llvm_sufix)];
|
||||||
|
snprintf(sonext_sym_name, sizeof(somain_sym_name), "__dl__ZL6sonext%s", llvm_sufix);
|
||||||
|
|
||||||
char vsdo_sym_name[sizeof("__dl__ZL4vdso") + sizeof(llvm_sufix)];
|
char vsdo_sym_name[sizeof("__dl__ZL4vdso") + sizeof(llvm_sufix)];
|
||||||
snprintf(vsdo_sym_name, sizeof(vsdo_sym_name), "__dl__ZL4vdso%s", llvm_sufix);
|
snprintf(vsdo_sym_name, sizeof(vsdo_sym_name), "__dl__ZL4vdso%s", llvm_sufix);
|
||||||
|
|
||||||
somain = getStaticPointer<SoInfo>(linker, somain_sym_name);
|
somain = getStaticPointer<SoInfo>(linker, somain_sym_name);
|
||||||
if (somain == NULL) return false;
|
if (somain == NULL) return false;
|
||||||
|
|
||||||
auto vsdo = getStaticPointer<SoInfo>(linker, vsdo_sym_name);
|
sonext = linker.getSymbAddress<SoInfo **>(sonext_sym_name);
|
||||||
|
if (sonext == NULL) return false;
|
||||||
|
|
||||||
|
SoInfo *vsdo = getStaticPointer<SoInfo>(linker, vsdo_sym_name);
|
||||||
|
if (vsdo == NULL) return false;
|
||||||
|
|
||||||
SoInfo::get_realpath_sym = reinterpret_cast<decltype(SoInfo::get_realpath_sym)>(linker.getSymbAddress("__dl__ZNK6soinfo12get_realpathEv"));
|
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"));
|
SoInfo::get_soname_sym = reinterpret_cast<decltype(SoInfo::get_soname_sym)>(linker.getSymbAddress("__dl__ZNK6soinfo10get_sonameEv"));
|
||||||
|
|||||||
@@ -582,13 +582,7 @@ void ZygiskContext::run_modules_post() {
|
|||||||
m.tryUnload();
|
m.tryUnload();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove from SoList to avoid detection
|
SoList::DropSoPath("jit-cache");
|
||||||
bool solist_res = SoList::Initialize();
|
|
||||||
if (!solist_res) {
|
|
||||||
LOGE("Failed to initialize SoList");
|
|
||||||
} else {
|
|
||||||
SoList::NullifySoName("jit-cache");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remap as well to avoid checking of /memfd:jit-cache
|
// Remap as well to avoid checking of /memfd:jit-cache
|
||||||
for (auto &info : lsplt::MapInfo::Scan()) {
|
for (auto &info : lsplt::MapInfo::Scan()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user