add: maps hiding (#13)

This commit adds maps hiding. This commit is taken from Reveny's PR, for more information, see #9.

solves #9
This commit is contained in:
Pedro.js
2024-06-26 19:38:34 -03:00
committed by GitHub
parent 4aa8b2f828
commit af96b85a91
6 changed files with 563 additions and 7 deletions
+136
View File
@@ -0,0 +1,136 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2019 Swift Gan
* Copyright (C) 2021 LSPosed Contributors
*/
#ifndef SANDHOOK_ELF_UTIL_H
#define SANDHOOK_ELF_UTIL_H
#include <string_view>
#include <unordered_map>
#include <linux/elf.h>
#include <sys/types.h>
#include <link.h>
#include <string>
#define SHT_GNU_HASH 0x6ffffff6
namespace SandHook {
class ElfImg {
public:
ElfImg(std::string_view elf);
constexpr ElfW(Addr) getSymbOffset(std::string_view name) const {
return getSymbOffset(name, GnuHash(name), ElfHash(name));
}
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 {
return 0;
}
}
template<typename T>
constexpr T getSymbAddress(std::string_view name) const {
return reinterpret_cast<T>(getSymbAddress(name));
}
bool isValid() const {
return base != nullptr;
}
const std::string name() const {
return elf;
}
~ElfImg();
private:
ElfW(Addr) getSymbOffset(std::string_view name, uint32_t gnu_hash, uint32_t elf_hash) const;
ElfW(Addr) ElfLookup(std::string_view name, uint32_t hash) const;
ElfW(Addr) GnuLookup(std::string_view name, uint32_t hash) const;
ElfW(Addr) LinearLookup(std::string_view name) const;
constexpr static uint32_t ElfHash(std::string_view name);
constexpr static uint32_t GnuHash(std::string_view name);
bool findModuleBase();
std::string elf;
void *base = nullptr;
char *buffer = nullptr;
off_t size = 0;
off_t bias = -4396;
ElfW(Ehdr) *header = nullptr;
ElfW(Shdr) *section_header = nullptr;
ElfW(Shdr) *symtab = nullptr;
ElfW(Shdr) *strtab = nullptr;
ElfW(Shdr) *dynsym = nullptr;
ElfW(Sym) *symtab_start = nullptr;
ElfW(Sym) *dynsym_start = nullptr;
ElfW(Sym) *strtab_start = nullptr;
ElfW(Off) symtab_count = 0;
ElfW(Off) symstr_offset = 0;
ElfW(Off) symstr_offset_for_symtab = 0;
ElfW(Off) symtab_offset = 0;
ElfW(Off) dynsym_offset = 0;
ElfW(Off) symtab_size = 0;
uint32_t nbucket_{};
uint32_t *bucket_ = nullptr;
uint32_t *chain_ = nullptr;
uint32_t gnu_nbucket_{};
uint32_t gnu_symndx_{};
uint32_t gnu_bloom_size_;
uint32_t gnu_shift2_;
uintptr_t *gnu_bloom_filter_;
uint32_t *gnu_bucket_;
uint32_t *gnu_chain_;
mutable std::unordered_map<std::string_view, ElfW(Sym) *> symtabs_;
};
constexpr uint32_t ElfImg::ElfHash(std::string_view name) {
uint32_t h = 0, g = 0;
for (unsigned char p: name) {
h = (h << 4) + p;
g = h & 0xf0000000;
h ^= g;
h ^= g >> 24;
}
return h;
}
constexpr uint32_t ElfImg::GnuHash(std::string_view name) {
uint32_t h = 5381;
for (unsigned char p: name) {
h += (h << 5) + p;
}
return h;
}
}
#endif //SANDHOOK_ELF_UTIL_H
+103
View File
@@ -0,0 +1,103 @@
//
// Original from https://github.com/LSPosed/NativeDetector/blob/master/app/src/main/jni/solist.cpp
//
#pragma once
#include <string>
#include "elf_util.h"
namespace SoList
{
class SoInfo {
public:
#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
inline static const char *(*get_realpath_sym)(SoInfo *) = nullptr;
inline static const char *(*get_soname_sym)(SoInfo *) = nullptr;
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_name() {
return get_soname_sym ? get_soname_sym(this) : *((const char **) ((uintptr_t) this + solist_realpath_offset - sizeof(void *)));
}
void nullify_name() {
const char** name = (const char**)get_soname_sym(this);
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);
}
};
static SoInfo *solist = nullptr;
static SoInfo *somain = nullptr;
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 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\n", 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();
break;
}
}
}
static bool Initialize() {
SandHook::ElfImg linker("/linker");
solist = getStaticPointer<SoInfo>(linker, "__dl__ZL6solist");
somain = getStaticPointer<SoInfo>(linker, "__dl__ZL6somain");
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");
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;
}
}
return (SoInfo::get_realpath_sym != nullptr && SoInfo::get_soname_sym != nullptr);
}
return false;
}
}