ELF文件结构简介(30)
ELF文件结构介绍
1.ELF文件介绍
首先需要知道的是:对象文件(Object files)有三个种类
可重定位的对象文件(Relocatable file)
这是由编译前汇编生成的 .o 文件。后面的连接器(link editor)拿一个或一些Relocatable object files 作为输入,经链接处理后,生成一个可执行的对象文件 (Executable file) 或者一个可被共享的对象文件(Shared object file)。我们可以使用 ar 工具将众多的 .o Relocatable object files 归档(archive)成 .a 静态库文件。如何产生 Relocatable file,你应该很熟悉了,请参见我们相关的基本概念文章和JulWiki。另外,可以预先告诉大家的是我们的内核可加载模块 .ko 文件也是 Relocatable object file。
可执行的对象文件(Executable file)
文本编辑器vi、调式用的工具gdb、播放mp3歌曲的软件mplayer等等都是Executableobject file。
在我们的 Linux 系统里面,存在两种可执行的东西。除了这里说的Executable object file,另外一种就是可执行的脚本(如shell脚本)。
注意这些脚本不是 Executableobject file,它们只是文本文件,但是执行这些脚本所用的解释器就是 Executable object file,比如bash shell 程序
可被共享的对象文件(Shared object file)
这些就是所谓的动态库文件,也即 .so 文件。
动态库在发挥作用的过程 中,必须经过两个步骤:
- 链接编辑器(link editor)拿它和其他Relocatable object file以及其他shared object file作为输入,经链接处理后,生存另外的shared object file或者executable file。
- 在运行时,动态链接器(dynamic linker)拿它和一个Executable file以及另外一些Shared object file来一起处理,在Linux系统里面创建一个进程映像。
这里我们主要是以Shared Object File(.so)为重点分析对象,因为我们在逆向APK中会遇到的绝大部分都是此类文件。
ELF文件格式
首先,ELF文件格式提供了两种视图,分别是链接视图和执行视图。
链接视图是以节(section)为单位,执行视图是以段(segment)为单位。链接视图就是在链接时用到的视图,而执行视图则是在执行时用到的视图。上图左侧的视角是从链接来看的,右侧的视角是执行来看的。总个文件可以分为四个部分:
ELF header: 描述整个文件的组织。
Program Header Table: 描述文件中的各种segments,用来告诉系统如何创建进程映像的
sections 或者 segments:segments是从运行的角度来描述elf文件,sections是从链接的角度来描述elf文件,也就是说,在链接阶段,我们可以忽略program header table来处理此文件,在运行阶段可以忽略section header table来处理此程序(所以很多加固手段删除了section header table)。从图中我们也可以看出,segments与sections是包含的关系,一个segment包含若干个section。
Section Header Table: 包含了文件各个segction的属性信息,我们都将结合例子来解释。
程序头部表(Program Header Table),如果存在的话,告诉系统如何创建进程映像。
节区头部表(Section Header Table)包含了描述文件节区的信息,比如大小、偏移等。
可以通过执行命令”readelf -S android_server”来查看该可执行文件中有哪些section。
通过执行命令readelf –segments android_server,可以查看该文件的执行视图。
3.ELF Header
1 |
|
e_ident : ELF的一些标识信息,前四位为.ELF,其他的信息比如大小端等
e_machine : 文件的目标体系架构,比如ARM
e_version : 0为非法版本,1为当前版本
e_entry : 程序入口的虚拟地址
e_phoff : 程序头部表偏移地址
e_shoff : 节区头部表偏移地址
e_flags :保存与文件相关的,特定于处理器的标志
e_ehsize :ELF头的大小
e_phentsize : 每个程序头部表的大小
e_phnum :程序头部表的数量
e_shentsize:每个节区头部表的大小
e_shnum : 节区头部表的数量
e_shstrndx:节区字符串表位置
接着运行readelf -h android_server命令,可以看到ELF Header结构的内容。