Android中GOT表HOOK手动实现续
2017-11-29 19:05
501 查看
上篇实现了GOT表的手动HOOK,这里需要说明一下,GOT表其实包含了导入表和导出表,导出表指将当前动态库的一些函数符号保留,供外部调用,之前针对HOOK的就是这种类型的函数。而针对导入表,这样的做法显然不行的,导入表中的函数实际是在该动态库中调用外部的导出函数。
导入表在对应在动态链接段.got.plt(DT_PLTGOT)指向处,但是每项的详细是和GOT表中的表项对应的,因此,在解析动态链接段时,需要解析DT_JMPREL、DT_SYMTAB,前者指向了每一个导入表表项的偏移地址和相关信息,包括在GOT表中偏移,后者为GOT表。
HOOK时只需要判断找到导入表表项对应的偏移地址,替换内容为需要跳转的地址即可。
基于此,我实现了一个导入表HOOK的示例,调用ReturnGiveValue函数查看LOG日志即可发现HOOK成功。
导入表在对应在动态链接段.got.plt(DT_PLTGOT)指向处,但是每项的详细是和GOT表中的表项对应的,因此,在解析动态链接段时,需要解析DT_JMPREL、DT_SYMTAB,前者指向了每一个导入表表项的偏移地址和相关信息,包括在GOT表中偏移,后者为GOT表。
HOOK时只需要判断找到导入表表项对应的偏移地址,替换内容为需要跳转的地址即可。
基于此,我实现了一个导入表HOOK的示例,调用ReturnGiveValue函数查看LOG日志即可发现HOOK成功。
#include <jni.h> #include <dlfcn.h> #include <elf.h> #include <android/log.h> #include <sys/mman.h> #define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, "ror_got_hook", __VA_ARGS__)) #define MEM_PAGE_SIZE 4096 #define MEM_PAGE_MASK (MEM_PAGE_SIZE-1) #define MEM_PAGE_START(x) ((x) & ~MEM_PAGE_MASK) #define MEM_PAGE_END(x) MEM_PAGE_START((x) + (MEM_PAGE_SIZE-1)) #define ElfW(type) Elf32_ ## type char str[] = "return give value"; JNIEXPORT void JNICALL ReturnGiveValue() { char logStr[255] = {0}; strncpy(logStr,str,strlen(str)); LOGD("%x",(unsigned int)strncpy); LOGD("show : %s",logStr); } int my_strncpy(char* s1, char* s2, int n) { memcpy(s1,"return fake value\0",18); LOGD("%x",(unsigned int)strncpy); return 1; } int __attribute__((constructor)) gothook() { //获取动态库基值 void* testlib = dlopen("/data/local/tmp/libtest.so",RTLD_LAZY); int nBase = *(int*)(testlib+0x8C); LOGD("nBase : %x",nBase); //计算program header table实际地址 ElfW(Ehdr) *header = (ElfW(Ehdr)*)(nBase); if (memcmp(header->e_ident, "\177ELF", 4) != 0) { return 0; } ElfW(Phdr)* phdr_table = (ElfW(Phdr)*)(nBase + header->e_phoff); if (phdr_table == 0) { LOGD("phdr_table address : 0"); return 0; } size_t phdr_count = header->e_phnum; LOGD("phdr_count : %d", phdr_count); //遍历program header table,ptype等于PT_DYNAMIC即为dynameic,获取到p_offset unsigned long dynamicAddr = 0; unsigned int dynamicSize = 0; for (int i = 0; i < phdr_count; i++) { if (phdr_table[i].p_type == PT_DYNAMIC) { dynamicAddr = phdr_table[i].p_vaddr + nBase; dynamicSize = phdr_table[i].p_memsz; break; } } LOGD("Dynamic Addr : %x",dynamicAddr); LOGD("Dynamic Size : %x",dynamicSize); /* typedef struct dynamic { Elf32_Sword d_tag; union { Elf32_Sword d_val; Elf32_Addr d_ptr; } d_un; } Elf32_Dyn; */ ElfW(Dyn)* dynamic_table = (ElfW(Dyn)*)(dynamicAddr); unsigned long jmpRelOff = 0; unsigned long strTabOff = 0; unsigned long pltRelSz = 0; unsigned long symTabOff = 0; int i; for(i=0;i < dynamicSize / 8;i ++) { int val = dynamic_table[i].d_un.d_val; if (dynamic_table[i].d_tag == DT_JMPREL) { jmpRelOff = val; } if (dynamic_table[i].d_tag == DT_STRTAB) { strTabOff = val; } if (dynamic_table[i].d_tag == DT_PLTRELSZ) { pltRelSz = val; } if (dynamic_table[i].d_tag == DT_SYMTAB) { symTabOff = val; } } ElfW(Rel)* rel_table = (ElfW(Rel)*)(jmpRelOff+nBase); LOGD("jmpRelOff : %x",jmpRelOff); LOGD("strTabOff : %x",strTabOff); LOGD("symTabOff : %x",symTabOff); //遍历查找要hook的导入函数,这里以strncpy做示例 for(i=0;i < pltRelSz / 8;i++) { int number = (rel_table[i].r_info >> 8) & 0xffffff; ElfW(Sym)* symTableIndex = (ElfW(Sym)*)(number*16 + symTabOff + nBase); char* funcName = (char*)(symTableIndex->st_name + strTabOff + nBase); // LOGD("Func Name : %s",funcName); if(memcmp(funcName,"strncpy",7) == 0) { void* pstart = (void*)MEM_PAGE_START(((ElfW(Addr))rel_table[i].r_offset + nBase)); mprotect(pstart,MEM_PAGE_SIZE,PROT_READ | PROT_WRITE | PROT_EXEC); LOGD("r_off : %x",rel_table[i].r_offset + nBase); LOGD("my_strncpy : %x",my_strncpy); *(unsigned int*)(rel_table[i].r_offset + nBase) = my_strncpy; } } return 0; }
相关文章推荐
- Android中GOT表HOOK手动实现
- 基于Android的ELF PLT/GOT符号重定向过程及ELF Hook实现
- 基于Android的ELF PLT/GOT符号重定向过程及ELF Hook实现
- 基于Android的ELF PLT/GOT符号重定向过程及ELF Hook实现
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
- 基于Android的ELF PLT/GOT符号重定向过程及ELF Hook实现(by 低端码农 2014.10.27)
- 使用Cydia Substrate实现Android Hook
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
- Android下通过hook技术实现透明加解密保障数据安全
- 在android webview实现截屏的手动tounchmove裁剪图片
- android hook 框架 ADBI 如何实现so函数挂钩
- android hook 框架 xposed 如何实现挂钩
- 基于Android的ELF PLT/GOT符号和重定向过程ELF Hook实现(by 低端农业代码 2014.10.27)
- android hook 框架 xposed 如何实现注入
- android hook 框架 libinject 如何实现so注入
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
- Android 滑动侧边栏(Sliding Menu)第一种实现 - 2 手动滚动+自动滚动 + 事件处理
- android 实现在文本内容超过固定宽度可手动左右滚动查看效果
- Android下通过hook技术实现透明加解密保障数据安全
- android自定义Gallery实现手动和自动循环滚动切换图片