Android SO 加载分析与导入表Hook、导出表Hook
来源:互联网 发布:cms企业建站系统 编辑:程序博客网 时间:2024/06/04 18:40
0x00 参考文章
关于so加载分析,就是从System.loadlibrary开始的,层层玻璃代码真相,在Android SO 加壳(加密)与脱壳思路,我们说ELF Header中的一些字段是无用的,Section Header也是无用的,这是为什么呢?
答案是在so加载的过程中,没有使用的,有关Android so加载深入分析,请参考这篇pdf,http://download.csdn.net/detail/jltxgcy/9602858,写的非常细致。
0x01 so加载流程
大致说一下加载so的流程:
1.1 根节点入栈,根节点是待加载的.so文件。
1.2 从待加载库中,加载.so文件和其依赖库。
1.2.1 把.so文件的内容读取到内存中。
1.2.2 加载到内存后,用soinfo结构体管理.so内存中的数据。
1.2.3 PrelinkImage,解析.dynamic section,补充soinfo结构体中的段信息。
1.2.4 将该.so文件依赖的库添加到待加载队列中。
1.2.5 循环至1.2,加载其依赖库。
1.3 循环链接(LinkImage).so和其依赖库。
特别说一下,1.2.4:
static void for_each_dt_needed(const soinfo* si, F action) { for (ElfW(Dyn)* d = si->dynamic; d->d_tag != DT_NULL; ++d) { if (d->d_tag == DT_NEEDED) { action(si->get_string(d->d_un.d_val)); } }}如果d_tag 为DT_NEEDED,那么d->d_un.d_val 是字符 串表的索引,其指向的值是该.so 文件的一个依赖库的名字。
0x02 导入表(GOT表Hook)
在Android PLT/GOT 符号重定向过程中,直接调用函数,整个过程是先到.plt,再到.got,最后才定位到真正的函数地址。那么只需要修改.got表中的函数指针,便可以实现Hook,具体实现的例子请参考Android中的so注入(inject)和挂钩(hook) - For both x86 and arm。
0x03 基于 Android linker 的导出表 HOOK
在so加载流程中,最后一步是循环LinkImage .so,代码如下:
int soinfo::Relocate(ElfW(Rel)* rel, unsigned count) { for (size_t idx = 0; idx < count; ++idx, ++rel) { unsigned type = ELFW(R_TYPE)(rel->r_info); // TODO: don't use unsigned for 'sym'. Use uint32_t or ElfW(Addr) instead. unsigned sym = ELFW(R_SYM)(rel->r_info); ElfW(Addr) reloc = static_cast<ElfW(Addr)>(rel->r_offset + load_bias); ElfW(Addr) sym_addr = 0; const char* sym_name = nullptr; DEBUG("Processing '%s' relocation at index %zd", name, idx); if (type == 0) { // R_*_NONE continue; } ElfW(Sym)* s = nullptr; soinfo* lsi = nullptr; if (sym != 0) { sym_name = get_string(symtab[sym].st_name); s = soinfo_do_lookup(this, sym_name, &lsi); if (s == nullptr) { // We only allow an undefined symbol if this is a weak reference... s = &symtab[sym]; if (ELF_ST_BIND(s->st_info) != STB_WEAK) { DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, name); return -1; }#if defined(__arm__) case R_ARM_COPY: // Fall through. Can't really copy if weak symbol is not found at run-time.#endif default: DL_ERR("unknown weak reloc type %d @ %p (%zu)", type, rel, idx); return -1; } } else { // We got a definition. sym_addr = lsi->resolve_symbol_address(s); } count_relocation(kRelocSymbol); } switch (type) {#if defined(__arm__) case R_ARM_JUMP_SLOT: count_relocation(kRelocAbsolute); MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO JMP_SLOT %08x <- %08x %s", reloc, sym_addr, sym_name); *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr; break; case R_ARM_GLOB_DAT: count_relocation(kRelocAbsolute); MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO GLOB_DAT %08x <- %08x %s", reloc, sym_addr, sym_name); *reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr; break; case R_ARM_ABS32: count_relocation(kRelocAbsolute); MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO ABS %08x <- %08x %s", reloc, sym_addr, sym_name); *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr; break; case R_ARM_REL32: count_relocation(kRelocRelative); MARK(rel->r_offset); TRACE_TYPE(RELO, "RELO REL32 %08x <- %08x - %08x %s", reloc, sym_addr, rel->r_offset, sym_name); *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr - rel->r_offset; break; ......} } return 0;}首先soinfo_do_lookup,根据要链接的函数名,比如puts,那么找到libc.so文件的soinfo结构体。lsi为libc.so文件的soinfo结构体。返回值为puts函数的Sym符号表结构体s。
然后通过resolve_symbol_address来找到puts函数的实际地址,代码如下:
ElfW(Addr) soinfo::resolve_symbol_address(ElfW(Sym)* s) { if (ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC) { return call_ifunc_resolver(s->st_value + load_bias); } return static_cast<ElfW(Addr)>(s->st_value + load_bias);}
1. 注入 zygote 进程。
2. dlopen libc.so,找到 puts 符号。
3. 解析此符号,得到其 st_value 地址。
4. 修改此地址的值为:NewFunc – BaseAddr(libc.so 加载的基地址)。因为符号的绝对地址是 通过 base + st_value 计算,即 st_value 保存的本身是偏移地址。
- Android SO 加载分析与导入表Hook、导出表Hook
- Dll导出表Hook
- Cydia Substrate框架Android so hook分析
- Hook导入表 —— 实现挂钩FreeLibaray和HOOK延迟加载模块的API
- 导出表钩子------EAT HOOK
- 输入表与HOOK
- HOOK SO文件的GOT表
- Cydia Substrate Android SO Hook
- Android so库Hook技术
- 【原创】导出表钩子------EAT HOOK
- 导出表钩子------EAT HOOK(转)
- 修改导入表HOOK API(ring3_iat_exe_hook_Messagebox)
- 修改导入表HOOK API(ring3_iat_exe_hook_Messagebox)
- Android的so注入( inject)和函数Hook(基于got表) - 支持arm和x86
- Android进程so注入Hook java方法
- Hook与Socket Hook
- Hook与Socket Hook
- Apk 分析与Hook技术
- [CC PARSIN]math
- 顺序表应用6:有序顺序表查询
- codeforces 628 B. New Skateboard (数学-被4整除)
- ReSharper10插件简介与安装
- 三个小李子讲述安卓动画用法
- Android SO 加载分析与导入表Hook、导出表Hook
- 游戏开发常用设计模式(一):观察者模式
- Particle for alexa smart home skill (6)
- Java知识点4
- iOS一行代码压缩图片大小
- Windows平台网站图片服务器架构的演进
- 虚拟按键遮挡控件的问题
- 第9篇.Fragment相关
- 算法讲解之Dynamic Programing —— 区间DP [变形:环形DP]