前言
随着 Android 开发的技术宽度不断向 native 层扩展,Native hook 已经被用于越来越多的业务场景中,之前作者一直游离于Java层面的逆向,后来工作使然,接触到了Native 层的Hook,熟悉了ELF的文件结构&GOT/PLT&In Line Hook的相关知识和实际操作,Android Native Hook 的实现方式有很多种,我们接下来要讲的是 GOT/PLT Hook (篇幅略略略长,阅读时长约 20 min )
一、ELF 是什么?
1、ELF 的概念
官方是如何解释的呢,下面请看大屏幕:
ELF(Executable and Linking Format),即“可执行可连接格式”,最初由 UNIX 系统实验室(UNIX System Laboratories – USL)做为应用程序二进制接口(Application Binary Interface - ABI)的一部分而制定和发布。
ELF 作为一种可移植的格式,被 TIS 应用于基于 Intel 架构 32 位计算机的各种操作系统上。 ELF 的最大特点在于它有比较广泛的适用性,通用的二进制接口定义使之可以平滑地移植到多种不同的操作环境上。这样,不需要为每一种操作系统都定义一套不同的接口,因此减少了软件的重复编码与编译,加强了软件的可移植性。
ELF 文件格式规范由 TIS(Tool Interface Standards – 工具接口标准)委员会制定, TIS 委员会是一个微型计算机工业的联合组织,它致力于为 32 位操作系统下的开发工具提供标准化的软件接口。这种接口包括目标标志格式、可执行文件格式,以及调试信息的格式。
嘟嘟嘟嘟…一大堆,建议略过 ,著名哲学家嘟嘟斯基曾说过:“太长不看”
首先,综上所述,明确一个概念,ELF 是一个文件格式,诸如我们所见的.so动态库,均属于ELF文件格式
2、ELF 的组成
没图说个**?
下面是作者简单画了一个图,从两个不同的角度来进行分析

如果不太了解没关系,大概先看一下,我们接着往下说~~~
2.1、 两种视图是什么呢?
连接(链接)视图:可以简单理解为目标文件的储存视图,也就是文件的静态解析视图;
运行(执行)视图:可以简单理解为目标文件的内存视图,也就是文件的动态运行视图;
其实就是程序run没run起来的区别~
2.2、 ELF文件头又是什么西西?
文件头部定义了Magic,以及指向节头表SHT(section_header_table ) 和 程序头表PHT(program_header_table) 的偏移
我们来拿curl.so文件来看一哈~

其中Magic表示了这是一个ELF文件: ELF 文件是以 7F 45 4C 46 开头 , 其中 7F 是一个二进制标志 , 45 4C 46 是 ELF 字符对应的 ASCII 码 ;
而节头表SHT(section_header_table ) 和 程序头表PHT(program_header_table) 的偏移地址也显示出来了~
运行命令: arm-linux-androideabi-readelf -h xxx.so
2.2、 ELF中节头表是什么南南呢?
ELF文件在链接视图中是 以节(section)为单位来组织和管理各种信息
看图图~

其中比较重要的是圈起来的几个点,以下是说明:
- .dynsym:为了完成动态链接,最关键的还是所依赖的符号和相关文件的信息。为了表示动态链接这些模块之间的符号导入导出关系,ELF有一个叫做动态符号表(Dynamic Symbol Table)的段用来保存这些信息
- .rel.dyn:实际上是对数据引用的修正,它所修正的位置位于.got以及数据段
- .rel.plt:是对函数引用的修正,它所修正的位置位于.got
- .plt:程序链接表(Procedure Link Table),外部调用的跳板
- .text:为代码段,也是反汇编处理的部分,以机器码的形式存储
- .dynamic:描述了模块动态链接相关的信息
- .got:全局偏移表(Global Offset Table),用于记录外部调用的入口地址
- .data: 数据段,保存的那些已经初始化了的全局静态变量和局部静态变量
记不住?没关系,我也是,先了解大概意思,慢慢往下走~
运行命令: arm-linux-androideabi-readelf -S xxx.so
2.2、 ELF中程序头表是什么北北呢?
ELF文件在执行视图中是 以段(Segment)为单位来组织和管理各种信息
所有类型为 PT_LOAD 的段(segment)都会被动态链接器(linker)映射(mmap)到内存中

- 程序头表(program header table)是一个数组, 数组中的每一个元素称为“程序头(program header)”,每一个程序头描述了一个 “段(segment)”或者一块用于准备执行程序的信息
- 一个目标文件中的“段 (segment)”包含一个或者多个“节(section)”
- 程序头只对可执行文件或共享目标 文件有意义,对于其它类型的目标文件,该信息可以忽略
- 在目标文件的文件头 (elf header)中,e_phentsize 和 e_phnum 成员指定了程序头的大小
运行命令: arm-linux-androideabi-readelf -l xxx.so
基于ELF的结构我们暂时先了解到这里,如果展开讲的话太鸡儿多了哈~~ 不是我懒~
二、动态库装载、动态链接与重定位简单理解
1、装载
作者是Android出身,所以仅从Android角

文章详细介绍了ELF文件格式,包括其概念、组成、连接视图和运行视图。接着讨论了动态库的装载、动态链接和重定位的过程。重点讲解了PLT和GOT在动态链接中的作用,以及如何进行Hook操作。文章还提供了实际操作示例,展示了如何找到目标函数的偏移和进行注入修改。
1747

被折叠的 条评论
为什么被折叠?



