You've already forked ReZygisk
mirror of
https://github.com/PerformanC/ReZygisk.git
synced 2025-09-06 06:37:01 +00:00
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:
@@ -50,7 +50,7 @@ void* DlopenMem(int fd, int flags) {
|
||||
.library_fd = fd
|
||||
};
|
||||
|
||||
auto* handle = android_dlopen_ext("/jit-cache", flags, &info);
|
||||
auto* handle = android_dlopen_ext("/jit-cache-zygisk", flags, &info);
|
||||
if (handle) {
|
||||
LOGV("dlopen fd %d: %p", fd, handle);
|
||||
} else {
|
||||
|
||||
235
loader/src/common/elf_util.cpp
Normal file
235
loader/src/common/elf_util.cpp
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
#include <malloc.h>
|
||||
#include <cstring>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <cassert>
|
||||
#include <sys/stat.h>
|
||||
#include "elf_util.h"
|
||||
|
||||
using namespace SandHook;
|
||||
|
||||
template<typename T>
|
||||
inline constexpr auto offsetOf(ElfW(Ehdr) *head, ElfW(Off) off) {
|
||||
return reinterpret_cast<std::conditional_t<std::is_pointer_v<T>, T, T *>>(
|
||||
reinterpret_cast<uintptr_t>(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<decltype(header)>(mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0));
|
||||
|
||||
close(fd);
|
||||
|
||||
section_header = offsetOf<decltype(section_header)>(header, header->e_shoff);
|
||||
|
||||
auto shoff = reinterpret_cast<uintptr_t>(section_header);
|
||||
char *section_str = offsetOf<char *>(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<decltype(dynsym_start)>(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<decltype(symtab_start)>(header, symtab_offset);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SHT_STRTAB: {
|
||||
if (bias == -4396) {
|
||||
strtab = section_h;
|
||||
symstr_offset = section_h->sh_offset;
|
||||
strtab_start = offsetOf<decltype(strtab_start)>(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<ElfW(Word)>(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<ElfW(Word) *>(((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<decltype(gnu_bloom_filter_)>(d_buf + 4);
|
||||
gnu_bucket_ = reinterpret_cast<decltype(gnu_bucket_)>(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<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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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<void *>(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<void *>(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<void *>(offset), elf.data());
|
||||
return offset;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool ElfImg::findModuleBase() {
|
||||
dl_iterate_phdr([](struct dl_phdr_info *info, size_t size, void *data) -> int {
|
||||
(void) size;
|
||||
|
||||
if ((info)->dlpi_name == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto *self = reinterpret_cast<ElfImg *>(data);
|
||||
if (strstr(info->dlpi_name, self->elf.data())) {
|
||||
self->elf = info->dlpi_name;
|
||||
self->base = reinterpret_cast<void *>(info->dlpi_addr);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}, this);
|
||||
return base != 0;
|
||||
}
|
||||
136
loader/src/include/elf_util.h
Normal file
136
loader/src/include/elf_util.h
Normal 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
loader/src/include/solist.hpp
Normal file
103
loader/src/include/solist.hpp
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "files.hpp"
|
||||
#include "misc.hpp"
|
||||
|
||||
#include "solist.hpp"
|
||||
|
||||
#include "art_method.hpp"
|
||||
|
||||
using namespace std;
|
||||
@@ -579,18 +581,98 @@ void ZygiskContext::run_modules_post() {
|
||||
}
|
||||
m.tryUnload();
|
||||
}
|
||||
|
||||
// Remove from SoList to avoid detection
|
||||
bool solist_res = SoList::Initialize();
|
||||
if (!solist_res) {
|
||||
LOGE("Failed to initialize SoList\n");
|
||||
} else {
|
||||
SoList::NullifySoName("jit-cache");
|
||||
}
|
||||
|
||||
// Remap as well to avoid checking of /memfd:jit-cache
|
||||
for (auto &info : lsplt::MapInfo::Scan()) {
|
||||
if (strstr(info.path.c_str(), "jit-cache-zygisk"))
|
||||
{
|
||||
void *addr = (void *)info.start;
|
||||
size_t size = info.end - info.start;
|
||||
// MAP_SHARED should fix the suspicious mapping.
|
||||
void *copy = mmap(nullptr, size, PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
|
||||
if (copy == MAP_FAILED) {
|
||||
LOGE("Failed to mmap jit-cache-zygisk\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((info.perms & PROT_READ) == 0) {
|
||||
mprotect(addr, size, PROT_READ);
|
||||
}
|
||||
memcpy(copy, addr, size);
|
||||
mremap(copy, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, addr);
|
||||
mprotect(addr, size, info.perms);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't know if there's a header for things like this
|
||||
// so I just put it into a lambda
|
||||
auto generateRandomString = [](char *str, int length) {
|
||||
const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
srand(time(NULL));
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
int key = rand() % (sizeof(charset) - 1);
|
||||
str[i] = charset[key];
|
||||
}
|
||||
|
||||
str[length] = '\0';
|
||||
};
|
||||
|
||||
// Randomize name of anonymous mappings
|
||||
// We don't run this in the previous loop because LSPosed might also add
|
||||
// mappings that are not related to /memfd:jit-zygisk-cache
|
||||
//
|
||||
// Since we changed to MAP_SHARED, I don't think this is still needed but let's
|
||||
// leave it here just in case.
|
||||
for (auto info : lsplt::MapInfo::Scan()) {
|
||||
// I had some problems with info.perms & PROT_EXEC so I had to change lsplt source a bit.
|
||||
// If that problem occurs here, do strchr(info.perms_str.c_str(), 'x') instead and add perms_str
|
||||
// to the lsplt MapInfo struct and set it to the raw perms string in Scan();
|
||||
if (info.perms & PROT_EXEC && info.path.empty()) {
|
||||
// Generate Random Name
|
||||
char randomString[11];
|
||||
generateRandomString(randomString, 10);
|
||||
LOGI("Randomized Memory map name: %s", randomString);
|
||||
|
||||
// Memory address of random string
|
||||
uintptr_t strAddr = (uintptr_t)&randomString;
|
||||
|
||||
// https://lore.kernel.org/lkml/1383170047-21074-2-git-send-email-ccross@android.com/
|
||||
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, info.start, info.end - info.start, strAddr);
|
||||
}
|
||||
|
||||
// Remap as MAP_SHARED
|
||||
if (info.perms & PROT_EXEC && info.dev == 0 && info.path.find("anon") != std::string::npos) {
|
||||
void *addr = reinterpret_cast<void *>(info.start);
|
||||
size_t size = info.end - info.start;
|
||||
void *copy = mmap(nullptr, size, PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
|
||||
if ((info.perms & PROT_READ) == 0) {
|
||||
mprotect(addr, size, PROT_READ);
|
||||
}
|
||||
memcpy(copy, addr, size);
|
||||
mremap(copy, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, addr);
|
||||
mprotect(addr, size, info.perms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Zygisksu changed: Load module fds */
|
||||
void ZygiskContext::app_specialize_pre() {
|
||||
flags[APP_SPECIALIZE] = true;
|
||||
info_flags = zygiskd::GetProcessFlags(g_ctx->args.app->uid);
|
||||
if ((info_flags & (PROCESS_IS_MANAGER | PROCESS_ROOT_IS_MAGISK)) == (PROCESS_IS_MANAGER | PROCESS_ROOT_IS_MAGISK)) {
|
||||
LOGI("current uid %d is manager!", g_ctx->args.app->uid);
|
||||
setenv("ZYGISK_ENABLED", "1", 1);
|
||||
} else {
|
||||
run_modules_pre();
|
||||
if ((info_flags & PROCESS_ON_DENYLIST) == PROCESS_ON_DENYLIST) {
|
||||
flags[DO_REVERT_UNMOUNT] = true;
|
||||
}
|
||||
|
||||
run_modules_pre();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ fn load_modules(arch: &str) -> Result<Vec<Module>> {
|
||||
|
||||
fn create_library_fd(so_path: &PathBuf) -> Result<OwnedFd> {
|
||||
let opts = memfd::MemfdOptions::default().allow_sealing(true);
|
||||
let memfd = opts.create("jit-cache")?;
|
||||
let memfd = opts.create("jit-cache-zygisk")?;
|
||||
let file = fs::File::open(so_path)?;
|
||||
let mut reader = std::io::BufReader::new(file);
|
||||
let mut writer = memfd.as_file();
|
||||
|
||||
Reference in New Issue
Block a user