Add inode plt hook APIs

This commit is contained in:
LoveSy
2022-11-21 16:59:22 +08:00
committed by John Wu
parent e38f35eab2
commit aa0a2f77cf
30 changed files with 176 additions and 4745 deletions
+25 -71
View File
@@ -2,63 +2,23 @@
#include <base.hpp>
#include "zygisk.hpp"
#include <lsplt.hpp>
using namespace std;
namespace {
struct map_info {
uintptr_t start;
uintptr_t end;
uintptr_t off;
int perms;
unsigned long inode;
map_info() : start(0), end(0), off(0), perms(0), inode(0) {}
};
} // namespace
template<typename Func>
static void parse_maps(int pid, Func fn) {
char file[32];
// format: start-end perms offset dev inode path
sprintf(file, "/proc/%d/maps", pid);
file_readline(true, file, [=](string_view l) -> bool {
char *line = (char *) l.data();
map_info info;
char perm[5];
int path_off;
if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %4s %" PRIxPTR " %*x:%*x %lu %n%*s",
&info.start, &info.end, perm, &info.off, &info.inode, &path_off) != 5)
return true;
// Parse permissions
if (perm[0] != '-')
info.perms |= PROT_READ;
if (perm[1] != '-')
info.perms |= PROT_WRITE;
if (perm[2] != '-')
info.perms |= PROT_EXEC;
return fn(info, line + path_off);
});
}
static vector<map_info> find_maps(const char *name) {
vector<map_info> maps;
parse_maps(getpid(), [=, &maps](const map_info &info, const char *path) -> bool {
if (strcmp(path, name) == 0)
maps.emplace_back(info);
return true;
});
static vector<lsplt::MapInfo> find_maps(const char *name) {
auto maps = lsplt::MapInfo::Scan();
for (auto iter = maps.begin(); iter != maps.end();) {
if (iter->path != name) {
iter = maps.erase(iter);
} else {
++iter;
}
}
return maps;
}
std::pair<void *, size_t> find_map_range(const char *name, unsigned long inode) {
vector<map_info> maps = find_maps(name);
auto maps = find_maps(name);
uintptr_t start = 0u;
uintptr_t end = 0u;
for (const auto &map : maps) {
@@ -76,8 +36,8 @@ std::pair<void *, size_t> find_map_range(const char *name, unsigned long inode)
}
void unmap_all(const char *name) {
vector<map_info> maps = find_maps(name);
for (map_info &info : maps) {
auto maps = find_maps(name);
for (auto &info : maps) {
void *addr = reinterpret_cast<void *>(info.start);
size_t size = info.end - info.start;
if (info.perms & PROT_READ) {
@@ -91,8 +51,8 @@ void unmap_all(const char *name) {
}
void remap_all(const char *name) {
vector<map_info> maps = find_maps(name);
for (map_info &info : maps) {
auto maps = find_maps(name);
for (auto &info : maps) {
void *addr = reinterpret_cast<void *>(info.start);
size_t size = info.end - info.start;
void *copy = xmmap(nullptr, size, PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
@@ -106,27 +66,21 @@ void remap_all(const char *name) {
}
uintptr_t get_function_off(int pid, uintptr_t addr, char *lib) {
uintptr_t off = 0;
parse_maps(pid, [=, &off](const map_info &info, const char *path) -> bool {
for (auto &info : lsplt::MapInfo::Scan()) {
if (addr >= info.start && addr < info.end) {
if (lib)
strcpy(lib, path);
off = addr - info.start + info.off;
return false;
strcpy(lib, info.path.data());
return addr - info.start + info.offset;
}
return true;
});
return off;
}
return 0;
}
uintptr_t get_function_addr(int pid, const char *lib, uintptr_t off) {
uintptr_t addr = 0;
parse_maps(pid, [=, &addr](const map_info &info, const char *path) -> bool {
if (strcmp(path, lib) == 0 && (info.perms & PROT_EXEC)) {
addr = info.start - info.off + off;
return false;
for (auto &info : lsplt::MapInfo::Scan()) {
if (info.path == lib && (info.perms & PROT_EXEC)) {
return info.start - info.offset + off;
}
return true;
});
return addr;
}
return 0;
}