Elf-Hook持续记录中

Elf32_rel保存的是重定向的数据

typedef struct elf32_rel {
  Elf32_Addr    r_offset;     // 重定位入口偏移
  Elf32_Word    r_info;      // 入口符号和类型,高8位表示入口类型,低24位表示索引idx     
} Elf32_Rel;



hook导入函数需要修改relplt结构
hook导出函数则需要修改st_value
其他则inlinehook

#include <stdio.h>
#include <stdlib.h>
#include <elf.h>
#include <error.h>
#include <fcntl.h>
#include <string.h>

#include <android/log.h>
#include <unistd.h>
#include "../hook.h"

#define NDK_LOG_TAG GEEEE"
#define LOGIHHHH(...) ((void)__android_log_print(ANDROID_LOG_INFO, NDK_LOG_TAG, __VA_ARGS__))
#define LOGDHHHH(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, NDK_LOG_TAG, __VA_ARGS__))
#define LOGEHH(...) ((void)__android_log_print(ANDROID_LOG_ERROR, NDK_LOG_TAG, __VA_ARGS__))

#define PAGE_START(addr, size) ~((size - 1) & (addr))

uint32_t get_so_addr(const char *soname) {

    FILE *fp = NULL;
    char line[256];
    uint32_t result = 0;
    if ((fp = fopen("/proc/self/maps", "r")) != NULL) {
        while (fgets(line, sizeof(line), fp) != NULL) {
            if (strstr(line, soname)) {
                line[8] = '\0';
                result = strtoul(line, NULL, 16);
                break;
            }
        }
    }
    fclose(fp);
    return result;
}

uint32_t find_got_addr(const char *soname, const char *symbol) {
    uint32_t module_base = get_so_addr(soname);
    int fd = open(soname, O_RDONLY);
    Elf32_Ehdr *elf_ehdr = (Elf32_Ehdr *) malloc(sizeof(Elf32_Ehdr));
    if (read(fd, elf_ehdr, sizeof(Elf32_Ehdr)) != sizeof(Elf32_Ehdr)) {
        LOGEHH("read elf eader error");
        return 0;
    }
    uint32_t sh_base = elf_ehdr->e_shoff;
    uint32_t ndx = elf_ehdr->e_shstrndx;
    // 最后一个section header结构体
    uint32_t shstr_base = sh_base + ndx * sizeof(Elf32_Shdr);
    // 调到最后一个secition header
    lseek(fd, shstr_base, SEEK_SET);
    // 解析shstrtab section header
    Elf32_Shdr *shstrtab_shdr = (Elf32_Shdr *) malloc(sizeof(Elf32_Shdr));
    if (read(fd, shstrtab_shdr, sizeof(Elf32_Shdr)) != sizeof(Elf32_Shdr)) {
        LOGEHH("read section header error");
        return 0;
    }
    // 分配内存-存储节区头字符串  section header str tab
    char *shstrtab = (char *) malloc(sizeof(char) * shstrtab_shdr->sh_size);
    lseek(fd, shstrtab_shdr->sh_offset, SEEK_SET);
    if (read(fd, shstrtab, shstrtab_shdr->sh_size) != shstrtab_shdr->sh_size) {
        LOGEHH("read shstr section error");
        return 0;
    }
    LOGDHHHH("read section : %s", shstrtab);

    // 所有的section header开头
    Elf32_Shdr *shdr = (Elf32_Shdr *) malloc(sizeof(Elf32_Shdr));
    Elf32_Shdr *relplt_shdr = (Elf32_Shdr *) malloc(sizeof(Elf32_Shdr));
    Elf32_Shdr *dynsym_shdr = (Elf32_Shdr *) malloc(sizeof(Elf32_Shdr));
    Elf32_Shdr *dynstr_shdr = (Elf32_Shdr *) malloc(sizeof(Elf32_Shdr));
    Elf32_Shdr *got_shdr = (Elf32_Shdr *) malloc(sizeof(Elf32_Shdr));
    // 跳转到section header第一个结构处
    lseek(fd, sh_base, SEEK_SET);
    if (read(fd, shdr, sizeof(Elf32_Shdr)) != sizeof(Elf32_Shdr)) {
        LOGEHH("read section header shdr error");
        return 0;
    }
    char *s = NULL;
    // 根据节区名称字符串过滤需要的节区relplt dynsym dynstr
    for (int i = 1; i < elf_ehdr->e_shnum; i++) {
        // shstrtab是 section header str tab的地址(第一个section header的地址)
        // 遍历节区名称,起始地址+节区头的name偏移
        s = shstrtab + shdr->sh_name;
        LOGIHHHH("shstrtab + shdr->sh_name :%s  e_shnum:%d %d ", s, elf_ehdr->e_shnum, i);
        if (strcmp(s, ".rel.plt") == 0) {
            memcpy(relplt_shdr, shdr, sizeof(Elf32_Shdr));
        } else if (strcmp(s, ".dynsym") == 0) {
            memcpy(dynsym_shdr, shdr, sizeof(Elf32_Shdr));
        } else if (strcmp(s, ".dynstr") == 0) {
            memcpy(dynstr_shdr, shdr, sizeof(Elf32_Shdr));
        } else if (strcmp(s, ".got") == 0) {
            memcpy(got_shdr, shdr, sizeof(Elf32_Shdr));
        }
        if (read(fd, shdr, sizeof(Elf32_Shdr)) != sizeof(Elf32_Shdr)) {
            LOGEHH("loop shstrtab section header str tab error");
            return 0;
        }
    }


    // 解析got表字符串
    Elf32_Sym *gotsymtab = (Elf32_Sym *) malloc(sizeof(char) * got_shdr->sh_size);
    lseek(fd, got_shdr->sh_offset, SEEK_SET);
    read(fd, gotsymtab, got_shdr->sh_size);




    // 把dynstr动态字符串表读入到分配的内存中
    char *dynstr = (char *) malloc(sizeof(char) * dynstr_shdr->sh_size);
    lseek(fd, dynstr_shdr->sh_offset, SEEK_SET);
    read(fd, dynstr, dynstr_shdr->sh_size);
    // 把dynsym动态函数表读入到分配的内存中
    Elf32_Sym *dynsymtab = (Elf32_Sym *) malloc(sizeof(char) * dynsym_shdr->sh_size);
    lseek(fd, dynsym_shdr->sh_offset, SEEK_SET);
    read(fd, dynsymtab, dynsym_shdr->sh_size);
    for (int i = 0; i < dynsym_shdr->sh_size / sizeof(Elf32_Sym); i++) {
        Elf32_Sym *elf32Sym =  (dynsymtab + i);
        const char *funcName = elf32Sym->st_name + dynstr;

        LOGIHHHH(" elf32Sym->st_name :%s", funcName);
    }

    // 把rel读入到分配的内存
    Elf32_Rel *relplt = (Elf32_Rel *) malloc(sizeof(Elf32_Rel));
    lseek(fd, relplt_shdr->sh_offset, SEEK_SET);
    read(fd, relplt, sizeof(Elf32_Rel));
    // 遍历relplt
    for (int i = 0; i < relplt_shdr->sh_size / sizeof(Elf32_Rel); i++) {
        // 取出函数索引
//        ndx = ELF32_R_SYM(relplt->r_info);
//        // 字符串地址加上动态符号表
//        LOGIHHHH("find symbol is :%s", dynstr + dynsymtab[ndx].st_name);
//        if (strcmp(dynstr + dynsymtab[ndx].st_name, symbol) == 0) {
//            LOGIHHHH("got entry find OK");
//            break;
//        }
//        if (read(fd, relplt, sizeof(Elf32_Rel)) != sizeof(Elf32_Rel)) {
//            LOGIHHHH("read loop relpot error");
//            break;
//        }
    }
    // 找到了重定向函数符号
    uint32_t offset = relplt->r_offset;
    Elf32_Half type = elf_ehdr->e_type;
    free(elf_ehdr);
    free(shstrtab_shdr);
    free(shstrtab);
    free(shdr);
    free(relplt_shdr);
    free(dynsym_shdr);
    free(dynstr_shdr);
    free(dynstr);
    free(dynsymtab);
    free(relplt);
    if (type == ET_EXEC) {
        // 如果是可执行文件
        return offset;
    } else if (type == ET_DYN)
        // 共享库
        return offset + module_base;
    return 0;
}

uint32_t gothook(const char *module_path, uint32_t hook_func, const char *symbol) {
    uint32_t entry_addr = find_got_addr(module_path, symbol);
    if (entry_addr == 0) {
        LOGEHH("find module error");
        return 0;
    }
    uint32_t original_addr = 0;
    // 查找到原始函数,存放到original addr
    memcpy(&original_addr, (uint32_t *) entry_addr, sizeof(uint32_t));
    LOGDHHHH("[++] hook func: 0x%x", hook_func);
    LOGDHHHH("[++] got entry: 0x%x", entry_addr);
    LOGDHHHH("[++] original func: 0x%x", original_addr);
    uint32_t page_size = getpagesize();
    uint32_t entry_page_start = PAGE_START(entry_addr, page_size);
    mprotect((uint32_t *) entry_page_start, page_size, PROT_READ | PROT_WRITE);
    memcpy((uint32_t *) entry_addr, &hook_func, sizeof(uint32_t));
    return original_addr;
}

 

posted @ 2018-04-04 18:01  xadxxx  阅读(767)  评论(0编辑  收藏  举报