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