diff --git a/README.md b/README.md
index 70246ac..dd87818 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ Zygisk loader for KernelSU, which allows Zygisk modules to run without Magisk en
- [x] Stabilize injector
- [ ] Separate zygiskd process
- [ ] Handle 64 bit only devices
-- [ ] DenyList
+- [ ] DenyList & Hide
## Running on Magisk
diff --git a/loader/src/include/elf_util.h b/loader/src/include/elf_util.h
deleted file mode 100644
index 99317ae..0000000
--- a/loader/src/include/elf_util.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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 .
- *
- * Copyright (C) 2019 Swift Gan
- * Copyright (C) 2021 LSPosed Contributors
- */
-#ifndef SANDHOOK_ELF_UTIL_H
-#define SANDHOOK_ELF_UTIL_H
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#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((uintptr_t) base + offset - bias);
- } else {
- return 0;
- }
- }
-
- template
- requires(std::is_pointer_v)
- constexpr T getSymbAddress(std::string_view name) const {
- return reinterpret_cast(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 symtabs_;
- };
-
- constexpr uint32_t ElfImg::ElfHash(std::string_view name) {
- uint32_t h = 0, g;
- 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
diff --git a/loader/src/injector/elf_util.cpp b/loader/src/injector/elf_util.cpp
deleted file mode 100644
index 83c8030..0000000
--- a/loader/src/injector/elf_util.cpp
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * 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 .
- *
- * Copyright (C) 2019 Swift Gan
- * Copyright (C) 2021 LSPosed Contributors
- */
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "logging.h"
-#include "elf_util.h"
-
-using namespace SandHook;
-
-template
-inline constexpr auto offsetOf(ElfW(Ehdr) *head, ElfW(Off) off) {
- return reinterpret_cast, T, T *>>(
- reinterpret_cast(head) + off);
-}
-
-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) {
- LOGE("failed to open %s", elf.data());
- return;
- }
-
- size = lseek(fd, 0, SEEK_END);
- if (size <= 0) {
- LOGE("lseek() failed for %s", elf.data());
- }
-
- header = reinterpret_cast(mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0));
-
- close(fd);
-
- section_header = offsetOf(header, header->e_shoff);
-
- auto shoff = reinterpret_cast(section_header);
- char *section_str = offsetOf(header, section_header[header->e_shstrndx].sh_offset);
-
- for (int i = 0; i < header->e_shnum; i++, shoff += header->e_shentsize) {
- auto *section_h = (ElfW(Shdr) *) shoff;
- char *sname = section_h->sh_name + section_str;
- auto entsize = section_h->sh_entsize;
- switch (section_h->sh_type) {
- case SHT_DYNSYM: {
- if (bias == -4396) {
- dynsym = section_h;
- dynsym_offset = section_h->sh_offset;
- dynsym_start = offsetOf(header, dynsym_offset);
- }
- break;
- }
- case SHT_SYMTAB: {
- if (strcmp(sname, ".symtab") == 0) {
- symtab = section_h;
- symtab_offset = section_h->sh_offset;
- symtab_size = section_h->sh_size;
- symtab_count = symtab_size / entsize;
- symtab_start = offsetOf(header, symtab_offset);
- }
- break;
- }
- case SHT_STRTAB: {
- if (bias == -4396) {
- strtab = section_h;
- symstr_offset = section_h->sh_offset;
- strtab_start = offsetOf(header, symstr_offset);
- }
- if (strcmp(sname, ".strtab") == 0) {
- symstr_offset_for_symtab = section_h->sh_offset;
- }
- break;
- }
- case SHT_PROGBITS: {
- if (strtab == nullptr || dynsym == nullptr) break;
- if (bias == -4396) {
- bias = (off_t) section_h->sh_addr - (off_t) section_h->sh_offset;
- }
- break;
- }
- case SHT_HASH: {
- auto *d_un = offsetOf(header, section_h->sh_offset);
- nbucket_ = d_un[0];
- bucket_ = d_un + 2;
- chain_ = bucket_ + nbucket_;
- break;
- }
- case SHT_GNU_HASH: {
- auto *d_buf = reinterpret_cast(((size_t) header) +
- section_h->sh_offset);
- gnu_nbucket_ = d_buf[0];
- gnu_symndx_ = d_buf[1];
- gnu_bloom_size_ = d_buf[2];
- gnu_shift2_ = d_buf[3];
- gnu_bloom_filter_ = reinterpret_cast(d_buf + 4);
- gnu_bucket_ = reinterpret_cast(gnu_bloom_filter_ +
- gnu_bloom_size_);
- gnu_chain_ = gnu_bucket_ + gnu_nbucket_ - gnu_symndx_;
- break;
- }
- }
- }
-}
-
-ElfW(Addr) ElfImg::ElfLookup(std::string_view name, uint32_t hash) const {
- if (nbucket_ == 0) return 0;
-
- char *strings = (char *) strtab_start;
-
- for (auto n = bucket_[hash % nbucket_]; n != 0; n = chain_[n]) {
- auto *sym = dynsym_start + n;
- if (name == strings + sym->st_name) {
- return sym->st_value;
- }
- }
- return 0;
-}
-
-ElfW(Addr) ElfImg::GnuLookup(std::string_view name, uint32_t hash) const {
- static constexpr auto bloom_mask_bits = sizeof(ElfW(Addr)) * 8;
-
- if (gnu_nbucket_ == 0 || gnu_bloom_size_ == 0) return 0;
-
- auto bloom_word = gnu_bloom_filter_[(hash / bloom_mask_bits) % gnu_bloom_size_];
- uintptr_t mask = 0
- | (uintptr_t) 1 << (hash % bloom_mask_bits)
- | (uintptr_t) 1 << ((hash >> gnu_shift2_) % bloom_mask_bits);
- if ((mask & bloom_word) == mask) {
- auto sym_index = gnu_bucket_[hash % gnu_nbucket_];
- if (sym_index >= gnu_symndx_) {
- char *strings = (char *) strtab_start;
- do {
- auto *sym = dynsym_start + sym_index;
- if (((gnu_chain_[sym_index] ^ hash) >> 1) == 0
- && name == strings + sym->st_name) {
- return sym->st_value;
- }
- } while ((gnu_chain_[sym_index++] & 1) == 0);
- }
- }
- return 0;
-}
-
-ElfW(Addr) ElfImg::LinearLookup(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(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]);
- }
- }
- }
- }
- if (auto i = symtabs_.find(name); i != symtabs_.end()) {
- return i->second->st_value;
- } else {
- return 0;
- }
-}
-
-
-ElfImg::~ElfImg() {
- //open elf file local
- if (buffer) {
- free(buffer);
- buffer = nullptr;
- }
- //use mmap
- if (header) {
- munmap(header, size);
- }
-}
-
-ElfW(Addr)
-ElfImg::getSymbOffset(std::string_view name, uint32_t gnu_hash, uint32_t elf_hash) const {
- if (auto offset = GnuLookup(name, gnu_hash); offset > 0) {
- LOGD("found %s %p in %s in dynsym by gnuhash", name.data(),
- reinterpret_cast(offset), elf.data());
- return offset;
- } else if (offset = ElfLookup(name, elf_hash); offset > 0) {
- LOGD("found %s %p in %s in dynsym by elfhash", name.data(),
- reinterpret_cast(offset), elf.data());
- return offset;
- } else if (offset = LinearLookup(name); offset > 0) {
- LOGD("found %s %p in %s in symtab by linear lookup", name.data(),
- reinterpret_cast(offset), elf.data());
- return offset;
- } else {
- return 0;
- }
-
-}
-
-bool ElfImg::findModuleBase() {
- char buff[256];
- off_t load_addr;
- bool found = false;
- FILE *maps = fopen("/proc/self/maps", "r");
-
-
- while (fgets(buff, sizeof(buff), maps)) {
- if ((strstr(buff, "r-xp") || strstr(buff, "r--p")) && strstr(buff, elf.data())) {
- LOGD("found: %s", buff);
- std::string_view b = buff;
- if (auto begin = b.find_last_of(' '); begin != std::string_view::npos && b[++begin] == '/') {
- found = true;
- elf = b.substr(begin);
- if (elf.back() == '\n') elf.pop_back();
- LOGD("update path: %s", elf.data());
- break;
- }
- }
- }
-
- if (!found) {
- LOGE("failed to read load address for %s", elf.data());
- fclose(maps);
- return false;
- }
-
- if (char *next = buff; load_addr = strtoul(buff, &next, 16), next == buff) {
- LOGE("failed to read load address for %s", elf.data());
- }
-
- fclose(maps);
-
- LOGD("get module base %s: %lx", elf.data(), load_addr);
-
- base = reinterpret_cast(load_addr);
- return true;
-}
diff --git a/loader/src/injector/hook.cpp b/loader/src/injector/hook.cpp
index 8d2f60a..8dcebc6 100644
--- a/loader/src/injector/hook.cpp
+++ b/loader/src/injector/hook.cpp
@@ -14,7 +14,6 @@
#include "dl.h"
#include "daemon.h"
-#include "elf_util.h"
#include "zygisk.hpp"
#include "memory.hpp"
#include "module.hpp"
@@ -743,11 +742,8 @@ void hook_functions() {
if (old_jniRegisterNativeMethods == nullptr) {
do {
LOGD("jniRegisterNativeMethods not hooked, using fallback\n");
-
- SandHook::ElfImg art("libandroid_runtime.so");
-
- auto *GetRuntime = art.getSymbAddress("_ZN7android14AndroidRuntime10getRuntimeEv");
-
+ constexpr char sig[] = "_ZN7android14AndroidRuntime10getRuntimeEv";
+ auto *GetRuntime = (void*(*)()) dlsym(RTLD_DEFAULT, sig);
if (GetRuntime == nullptr) {
LOGE("GetRuntime is nullptr");
break;