Files
Zygisk-MyInjector/module/src/main/cpp/newriruhide.cpp
2024-11-16 23:04:25 +08:00

135 lines
3.9 KiB
C++

//
// Created by Mac on 2024/11/15.
//
// 给riru修复了内存泄漏的问题
#include "newriruhide.h"
/**
* Magic to hide from /proc/###/maps, the idea is from Haruue Icymoon (https://github.com/haruue)
*/
extern "C" {
int riru_hide(const char *name) ;
}
#ifdef __LP64__
#define LIB_PATH "/system/lib64/"
#else
#define LIB_PATH "/system/lib/"
#endif
struct hide_struct {
procmaps_struct *original;
uintptr_t backup_address;
};
static int get_prot(const procmaps_struct *procstruct) {
int prot = 0;
if (procstruct->is_r) {
prot |= PROT_READ;
}
if (procstruct->is_w) {
prot |= PROT_WRITE;
}
if (procstruct->is_x) {
prot |= PROT_EXEC;
}
return prot;
}
#define FAILURE_RETURN(exp, failure_value) ({ \
__typeof__(exp) _rc; \
_rc = (exp); \
if (_rc == failure_value) { \
PLOGE(#exp); \
return 1; \
} \
_rc; })
static int do_hide(hide_struct *data) {
auto procstruct = data->original;
auto start = (uintptr_t) procstruct->addr_start;
auto end = (uintptr_t) procstruct->addr_end;
auto length = end - start;
int prot = get_prot(procstruct);
// backup
data->backup_address = (uintptr_t) FAILURE_RETURN(
mmap(nullptr, length, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0),
MAP_FAILED);
LOGD("%" PRIxPTR"-%" PRIxPTR" %s %ld %s is backup to %" PRIxPTR, start, end, procstruct->perm,
procstruct->offset,
procstruct->pathname, data->backup_address);
if (procstruct->is_r || procstruct->is_x) { // If readable or executable
LOGD("memcpy -> backup");
memcpy((void *) data->backup_address, (void *) start, length);
// Unmap original memory region
LOGD("munmap original");
FAILURE_RETURN(munmap((void *) start, length), -1);
// Remap backup memory to original location
LOGD("mmap original with backup");
FAILURE_RETURN(mmap((void *) start, length, prot, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0),
MAP_FAILED);
}
return 0;
}
int riru_hide(const char *name) {
procmaps_iterator *maps = pmparser_parse(-1);
if (maps == nullptr) {
LOGE("cannot parse the memory map");
return false;
}
char buf[PATH_MAX];
hide_struct *data = nullptr;
size_t data_count = 0;
procmaps_struct *maps_tmp;
while ((maps_tmp = pmparser_next(maps)) != nullptr) {
bool matched = false;
#ifdef DEBUG_APP
matched = strstr(maps_tmp->pathname, "libriru.so");
#endif
matched = strstr(maps_tmp->pathname, name) != nullptr;
// Match the memory regions we want to hide
if (!matched) continue;
LOGI("matched %s", maps_tmp->pathname);
auto start = (uintptr_t) maps_tmp->addr_start;
auto end = (uintptr_t) maps_tmp->addr_end;
if (maps_tmp->is_r || maps_tmp->is_x) { // If memory is readable or executable
if (data) {
data = (hide_struct *) realloc(data, sizeof(hide_struct) * (data_count + 1));
} else {
data = (hide_struct *) malloc(sizeof(hide_struct));
}
data[data_count].original = maps_tmp;
data_count += 1;
}
LOGD("%" PRIxPTR"-%" PRIxPTR" %s %ld %s", start, end, maps_tmp->perm, maps_tmp->offset,
maps_tmp->pathname);
}
for (int i = 0; i < data_count; ++i) {
LOGI("do_hide %d", i);
do_hide(&data[i]);
}
// Free backup memory to avoid leaks
for (int i = 0; i < data_count; ++i) {
FAILURE_RETURN(munmap((void *) data[i].backup_address,
(uintptr_t) data[i].original->addr_end - (uintptr_t) data[i].original->addr_start), -1);
}
if (data) free(data);
pmparser_free(maps);
return 0;
}