From 581506a1b564ff1a8c53761c2df12408b6ed86cd Mon Sep 17 00:00:00 2001 From: Nullptr Date: Thu, 2 Feb 2023 14:57:43 +0800 Subject: [PATCH] Fix random crash --- README.md | 2 +- loader/src/include/elf_util.h | 137 ---------------- loader/src/injector/elf_util.cpp | 260 ------------------------------- loader/src/injector/hook.cpp | 8 +- 4 files changed, 3 insertions(+), 404 deletions(-) delete mode 100644 loader/src/include/elf_util.h delete mode 100644 loader/src/injector/elf_util.cpp 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;