android的got表HOOK实现代码

概述

对于android的so文件的hook根据ELF文件特性分为:Got表hook、Sym表hook和inline hook等。
全局符号表(GOT表)hook,它是通过解析SO文件,将待hook函数在got表的地址替换为自己函数的入口地址,这样目标进程每次调用待hook函数时,实际上是执行了我们自己的函数。

Androd so注入和函数Hook(基于got表)的步骤:

1.ptrace附加目标pid进程;
2.在目标pid进程中,查找内存空间(用于存放被注入的so文件的路径和so中被调用的函数的名称或者shellcode);
3.调用目标pid进程中的dlopen、dlsym等函数,用于加载so文件实现Android so的注入和函数的Hook;
4.释放附加的目标pid进程和卸载注入的so文件。

具体代码实现

以下以fopen函数进行got hook为例。

//获取模块地址功能实现
void* getModuleBase(pid_t pid, const char* module_name){
    FILE* fp;
    long address = 0;
    char* pch;
    char filename[32];
    char line[1024];

    // 格式化字符串得到 "/proc/pid/maps"
    if(pid < 0){
        snprintf(filename, sizeof(filename), "/proc/self/maps");
    }else{
        snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
    }

    // 打开文件/proc/pid/maps,获取指定pid进程加载的内存模块信息
    fp = fopen(filename, "r");
    if(fp != NULL){
        // 每次一行,读取文件 /proc/pid/maps中内容
        while(fgets(line, sizeof(line), fp)){
            // 查找指定的so模块
            if(strstr(line, module_name)){
                // 分割字符串
                pch = strtok(line, "-");
                // 字符串转长整形
                address = strtoul(pch, NULL, 16);
               
                }
                break;
            }
        }
    }
    fclose(fp);
    return (void*)address;
}
//hook fopen进行实现
//(libxxxx.so文件是ELF32文件)
#define LIBPATH "/data/app-lib/com.xxxx/libxxxx.so"

int hookFopen(){

    // 获取目标pid中"/data/app-lib/com.xxxx/libxxxx.so"模块的加载地址
    void* base_addr = getModuleBase(getpid(), LIBPATH );
    // 保存Hook目标函数的原始调用地址
    old_fopen = fopen;
    int fd;
    // 用open打开内存模块文件"/data/app-lib/com.xxxx/libxxxx.so"
    fd = open(LIB_PATH, O_RDONLY);
    if(-1 == fd){
        return -1;
    }

     // elf32文件的文件头结构体Elf32_Ehdr
    Elf32_Ehdr ehdr;
    // 读取elf32格式的文件"/data/app-lib/com.xxxx/libxxxx.so"的文件头信息
    read(fd, &ehdr, sizeof(Elf32_Ehdr));

    // elf32文件中节区表信息结构的文件偏移
    unsigned long shdr_addr = ehdr.e_shoff;
    // elf32文件中节区表信息结构的数量
    int shnum = ehdr.e_shnum;
    // elf32文件中每个节区表信息结构中的单个信息结构的大小(描述每个节区的信息的结构体的大小)
    int shent_size = ehdr.e_shentsize;

    // elf32文件节区表中每个节区的名称存放的节区名称字符串表,在节区表中的序号index
    unsigned long stridx = ehdr.e_shstrndx;

    Elf32_Shdr shdr;
    lseek(fd, shdr_addr + stridx * shent_size, SEEK_SET);
    // 读取elf32文件中的描述每个节区的信息的结构体(这里是保存elf32文件的每个节区的名称字符串的)
    read(fd, &shdr, shent_size);

    // 为保存elf32文件的所有的节区的名称字符串申请内存空间
    char * string_table = (char *)malloc(shdr.sh_size);
    // 定位到具体存放elf32文件的所有的节区的名称字符串的文件偏移处
    lseek(fd, shdr.sh_offset, SEEK_SET);
    read(fd, string_table, shdr.sh_size);
    lseek(fd, shdr_addr, SEEK_SET);

    int i;
    uint32_t out_addr = 0;
    uint32_t out_size = 0;
    uint32_t got_item = 0;
    int32_t got_found = 0;

    // 循环遍历elf32文件的节区表(描述每个节区的信息的结构体)
    for(i = 0; i 
 

到此这篇关于android的got表HOOK实现代码的文章就介绍到这了,更多相关android HOOK实现got表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

你可能感兴趣的:(android的got表HOOK实现代码)