// // 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; }