Merge pull request #3 from jiqiu2022/hide_inject

Hide inject
This commit is contained in:
Ji qiu
2024-11-16 23:01:09 +08:00
committed by GitHub
6 changed files with 565 additions and 0 deletions

View File

@@ -36,6 +36,8 @@ aux_source_directory(xdl xdl-src)
add_library(${MODULE_NAME} SHARED
main.cpp
hack.cpp
newriruhide.cpp
pmparser.cpp
${xdl-src})
target_link_libraries(${MODULE_NAME} log)

View File

@@ -18,6 +18,7 @@
#include <sys/stat.h>
//#include <asm-generic/fcntl.h>
#include <fcntl.h>
#include "newriruhide.h"
void load_so(const char *game_data_dir, JavaVM *vm, const char *soname) {
bool load = false;
LOGI("hack_start %s", game_data_dir);
@@ -76,6 +77,9 @@ void load_so(const char *game_data_dir, JavaVM *vm, const char *soname) {
if (handle) {
LOGI("Successfully loaded %s", new_so_path);
load = true;
char new_soname[256];
sprintf(new_soname, "%s.so", soname);
riru_hide(new_soname);
break;
} else {
LOGE("Failed to load %s: %s", new_so_path, dlerror());

View File

@@ -0,0 +1,134 @@
//
// 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) { \
LOGE(#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;
}

View File

@@ -0,0 +1,19 @@
//
// Created by Mac on 2024/11/15.
//
#ifndef ZYGISK_MYINJECTOR_NEWRIRUHIDE_H
#define ZYGISK_MYINJECTOR_NEWRIRUHIDE_H
#define EXPORT __attribute__((visibility("default"))) __attribute__((used))
#include <cinttypes>
#include <sys/mman.h>
#include <set>
#include <string_view>
#include "pmparser.h"
#include "android/log.h"
#include "log.h"
extern "C" {
int riru_hide(const char *name) EXPORT;
}
#endif //ZYGISK_MYINJECTOR_NEWRIRUHIDE_H

View File

@@ -0,0 +1,307 @@
/*
@Author : ouadimjamal@gmail.com
@date : December 2015
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation. No representations are made about the suitability of this
software for any purpose. It is provided "as is" without express or
implied warranty.
*/
#include "pmparser.h"
#include "log.h"
/**
* gobal variables
*/
//procmaps_struct* g_last_head=NULL;
//procmaps_struct* g_current=NULL;
procmaps_iterator* pmparser_parse(int pid){
LOGI("pmparser_parse called with pid: %d", pid);
procmaps_iterator* maps_it = (procmaps_iterator *)malloc(sizeof(procmaps_iterator));
if (!maps_it) {
LOGI("Failed to allocate memory for procmaps_iterator");
return NULL;
}
LOGI("Allocated memory for procmaps_iterator: %p", maps_it);
char maps_path[500];
if(pid >= 0 ){
snprintf(maps_path, sizeof(maps_path), "/proc/%d/maps", pid);
LOGI("Constructed maps_path for pid: %s", maps_path);
} else {
snprintf(maps_path, sizeof(maps_path), "/proc/self/maps");
LOGI("Constructed maps_path for self: %s", maps_path);
}
FILE* file = fopen(maps_path, "r");
if(!file){
LOGI("pmparser: cannot open the memory maps, %s", strerror(errno));
free(maps_it);
return NULL;
}
LOGI("Opened maps file: %s", maps_path);
int ind = 0;
char buf[PROCMAPS_LINE_MAX_LENGTH];
procmaps_struct* list_maps = NULL;
procmaps_struct* tmp;
procmaps_struct* current_node = NULL;
char addr1[20], addr2[20], perm[8], offset[20], dev[10], inode[30], pathname[PATH_MAX];
while (fgets(buf, PROCMAPS_LINE_MAX_LENGTH, file)) {
LOGI("Read line %d: %s", ind + 1, buf);
// 分配一个新的节点
tmp = (procmaps_struct*)malloc(sizeof(procmaps_struct));
if (!tmp) {
LOGI("Failed to allocate memory for procmaps_struct at line %d", ind + 1);
fclose(file);
// 需要释放已分配的节点,避免内存泄漏
procmaps_struct* iter = list_maps;
while (iter) {
procmaps_struct* next = iter->next;
free(iter);
iter = next;
}
free(maps_it);
return NULL;
}
LOGI("Allocated memory for procmaps_struct: %p", tmp);
// 填充节点
_pmparser_split_line(buf, addr1, addr2, perm, offset, dev, inode, pathname);
LOGI("Parsed line %d - addr1: %s, addr2: %s, perm: %s, offset: %s, dev: %s, inode: %s, pathname: %s",
ind + 1, addr1, addr2, perm, offset, dev, inode, pathname);
// 使用临时变量解析地址
unsigned long tmp_addr_start_ul, tmp_addr_end_ul;
if (sscanf(addr1, "%lx", &tmp_addr_start_ul) != 1) {
LOGI("Failed to parse addr_start at line %d", ind + 1);
free(tmp);
continue;
}
if (sscanf(addr2, "%lx", &tmp_addr_end_ul) != 1) {
LOGI("Failed to parse addr_end at line %d", ind + 1);
free(tmp);
continue;
}
LOGI("Parsed addresses - addr_start: 0x%lx, addr_end: 0x%lx", tmp_addr_start_ul, tmp_addr_end_ul);
tmp->addr_start = (void*)tmp_addr_start_ul;
tmp->addr_end = (void*)tmp_addr_end_ul;
// size
tmp->length = (unsigned long)((char*)tmp->addr_end - (char*)tmp->addr_start);
LOGI("Calculated length: %lu", tmp->length);
// perm
strncpy(tmp->perm, perm, sizeof(tmp->perm) - 1);
tmp->perm[sizeof(tmp->perm) - 1] = '\0';
tmp->is_r = (perm[0] == 'r');
tmp->is_w = (perm[1] == 'w');
tmp->is_x = (perm[2] == 'x');
tmp->is_p = (perm[3] == 'p');
LOGI("Permissions - is_r: %d, is_w: %d, is_x: %d, is_p: %d", tmp->is_r, tmp->is_w, tmp->is_x, tmp->is_p);
// offset
if (sscanf(offset, "%lx", &tmp->offset) != 1) {
LOGI("Failed to parse offset at line %d", ind + 1);
free(tmp);
continue;
}
LOGI("Parsed offset: 0x%lx", tmp->offset);
// device
strncpy(tmp->dev, dev, sizeof(tmp->dev) - 1);
tmp->dev[sizeof(tmp->dev) - 1] = '\0';
LOGI("Device: %s", tmp->dev);
// inode
tmp->inode = atoi(inode);
LOGI("Inode: %d", tmp->inode);
// pathname
strncpy(tmp->pathname, pathname, sizeof(tmp->pathname) - 1);
tmp->pathname[sizeof(tmp->pathname) - 1] = '\0';
LOGI("Pathname: %s", tmp->pathname);
tmp->next = NULL;
// 连接节点到链表
if(ind == 0){
list_maps = tmp;
current_node = list_maps;
LOGI("Initialized list_maps with first node: %p", list_maps);
}
else{
current_node->next = tmp;
current_node = tmp;
LOGI("Appended node to list_maps: %p", tmp);
}
ind++;
}
if (ferror(file)) {
LOGI("Error occurred while reading the maps file");
// 释放已分配的节点和 maps_it
procmaps_struct* iter = list_maps;
while (iter) {
procmaps_struct* next = iter->next;
free(iter);
iter = next;
}
fclose(file);
free(maps_it);
return NULL;
}
// 关闭文件
fclose(file);
LOGI("Closed maps file: %s", maps_path);
// 设置迭代器
maps_it->head = list_maps;
maps_it->current = list_maps;
LOGI("Initialized procmaps_iterator - head: %p, current: %p", maps_it->head, maps_it->current);
return maps_it;
}
procmaps_struct* pmparser_next(procmaps_iterator* p_procmaps_it){
if(p_procmaps_it->current == NULL)
return NULL;
procmaps_struct* p_current = p_procmaps_it->current;
p_procmaps_it->current = p_procmaps_it->current->next;
return p_current;
/*
if(g_current==NULL){
g_current=g_last_head;
}else
g_current=g_current->next;
return g_current;
*/
}
void pmparser_free(procmaps_iterator* p_procmaps_it){
procmaps_struct* maps_list = p_procmaps_it->head;
if(maps_list==NULL) return ;
procmaps_struct* act=maps_list;
procmaps_struct* nxt=act->next;
while(act!=NULL){
free(act);
act=nxt;
if(nxt!=NULL)
nxt=nxt->next;
}
free(p_procmaps_it);
}
void _pmparser_split_line(
char*buf,char*addr1,char*addr2,
char*perm,char* offset,char* device,char*inode,
char* pathname){
//
int orig=0;
int i=0;
//addr1
while(buf[i]!='-'){
addr1[i-orig]=buf[i];
i++;
}
addr1[i]='\0';
i++;
//addr2
orig=i;
while(buf[i]!='\t' && buf[i]!=' '){
addr2[i-orig]=buf[i];
i++;
}
addr2[i-orig]='\0';
//perm
while(buf[i]=='\t' || buf[i]==' ')
i++;
orig=i;
while(buf[i]!='\t' && buf[i]!=' '){
perm[i-orig]=buf[i];
i++;
}
perm[i-orig]='\0';
//offset
while(buf[i]=='\t' || buf[i]==' ')
i++;
orig=i;
while(buf[i]!='\t' && buf[i]!=' '){
offset[i-orig]=buf[i];
i++;
}
offset[i-orig]='\0';
//dev
while(buf[i]=='\t' || buf[i]==' ')
i++;
orig=i;
while(buf[i]!='\t' && buf[i]!=' '){
device[i-orig]=buf[i];
i++;
}
device[i-orig]='\0';
//inode
while(buf[i]=='\t' || buf[i]==' ')
i++;
orig=i;
while(buf[i]!='\t' && buf[i]!=' '){
inode[i-orig]=buf[i];
i++;
}
inode[i-orig]='\0';
//pathname
pathname[0]='\0';
while(buf[i]=='\t' || buf[i]==' ')
i++;
orig=i;
while(buf[i]!='\t' && buf[i]!=' ' && buf[i]!='\n'){
pathname[i-orig]=buf[i];
i++;
}
pathname[i-orig]='\0';
}
void pmparser_print(procmaps_struct* map, int order){
procmaps_struct* tmp=map;
int id=0;
if(order<0) order=-1;
while(tmp!=NULL){
//(unsigned long) tmp->addr_start;
if(order==id || order==-1){
printf("Backed by:\t%s\n",strlen(tmp->pathname)==0?"[anonym*]":tmp->pathname);
printf("Range:\t\t%p-%p\n",tmp->addr_start,tmp->addr_end);
printf("Length:\t\t%ld\n",tmp->length);
printf("Offset:\t\t%ld\n",tmp->offset);
printf("Permissions:\t%s\n",tmp->perm);
printf("Inode:\t\t%d\n",tmp->inode);
printf("Device:\t\t%s\n",tmp->dev);
}
if(order!=-1 && id>order)
tmp=NULL;
else if(order==-1){
printf("#################################\n");
tmp=tmp->next;
}else tmp=tmp->next;
id++;
}
}

View File

@@ -0,0 +1,99 @@
/*
@Author : ouadimjamal@gmail.com
@date : December 2015
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation. No representations are made about the suitability of this
software for any purpose. It is provided "as is" without express or
implied warranty.
*/
#ifndef H_PMPARSER
#define H_PMPARSER
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/limits.h>
//maximum line length in a procmaps file
#define PROCMAPS_LINE_MAX_LENGTH (PATH_MAX + 100)
/**
* procmaps_struct
* @desc hold all the information about an area in the process's VM
*/
typedef struct procmaps_struct{
void* addr_start; //< start address of the area
void* addr_end; //< end address
unsigned long length; //< size of the range
char perm[5]; //< permissions rwxp
short is_r; //< rewrote of perm with short flags
short is_w;
short is_x;
short is_p;
long offset; //< offset
char dev[12]; //< dev major:minor
int inode; //< inode of the file that backs the area
char pathname[600]; //< the path of the file that backs the area
//chained list
struct procmaps_struct* next; //<handler of the chinaed list
} procmaps_struct;
/**
* procmaps_iterator
* @desc holds iterating information
*/
typedef struct procmaps_iterator{
procmaps_struct* head;
procmaps_struct* current;
} procmaps_iterator;
/**
* pmparser_parse
* @param pid the process id whose memory map to be parser. the current process if pid<0
* @return an iterator over all the nodes
*/
procmaps_iterator* pmparser_parse(int pid);
/**
* pmparser_next
* @description move between areas
* @param p_procmaps_it the iterator to move on step in the chained list
* @return a procmaps structure filled with information about this VM area
*/
procmaps_struct* pmparser_next(procmaps_iterator* p_procmaps_it);
/**
* pmparser_free
* @description should be called at the end to free the resources
* @param p_procmaps_it the iterator structure returned by pmparser_parse
*/
void pmparser_free(procmaps_iterator* p_procmaps_it);
/**
* _pmparser_split_line
* @description internal usage
*/
void _pmparser_split_line(char*buf,char*addr1,char*addr2,char*perm, char* offset, char* device,char*inode,char* pathname);
/**
* pmparser_print
* @param map the head of the list
* @order the order of the area to print, -1 to print everything
*/
void pmparser_print(procmaps_struct* map,int order);
#endif