ELF文件
ELF文件格式最前部ELF文件头,包含了整个文件的基本属性,比如ELF版本,目标机器型号,程序入口地址等。其中ELF文件与段有关的重要结构就是段表。
ELF文件格式
- 可重定向文件:包含代码和适当的数据,用来和其他的目标文件一起来创建一个可执行性文件或者是一个共享目标文件
- 可执行文件:保存着一个用来执行的程序
- 共享目标文件:共享库,包含了用于链接的代码和数据,分两种情况:
- 静态连接器将其他可重定位文件和共享目标文件链接起来,生成新的目标文件
- 动态连接器将多个共享目标文件与可执行文件结合,作为进程映像的一部分
- core dump文件:进程意外终止时可以产生的文件,存储着该进程的内存空间中的内容等信息
ELF视图
ELF文件提供两种视图
- 链接视图,以节为单位,在链接时用到的视图
- 执行视图,以段为单位,在执行时用到的视图
- ELF header:描述整个文件的组织;
- program header table:描述文件中的各种segments,用来告诉系统如何创建进程映像;
- section header table:包含了文件各个section的属性信息;
- sections或segments:segments是从运行的角度来描述elf文件,sections是从链接的角度来描述elf文件,也就是说,在链接阶段,我们可以忽略program header table来处理此文件;在运行阶段可以忽略section header table来处理此程序(所以很多加固手段删除了section header table)
- 从图中可看出,segment和sections是包含关系,一个segment包含多个section
readelf -S ELF文件
//查看section信息
readelf -l ELF文件
//查看segment信息
文件头
- 查看文件头信息
root@ubuntu:/mnt/hgfs/ubuntu_share/pwn/brop# readelf -h a.out
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x4005c0
Start of program headers: 64 (bytes into file)
Start of section headers: 6960 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 31
Section header string table index: 28
字段解释
- type:文件类型,可执行文件
- machine:ELF文件的CPU平台属性
- version:版本号
- entry point address:ELF程序的入口虚拟地址
- start of program headers: segment表在ELF文件中的偏移
- start of section headers: section表在ELF文件中的偏移
- flags: ELF文件标志位
- size of this header: ELF文件头本身的大小
- number of section headers: section在ELF文件中的数量,与上文用readelf命令查看的数量相一致
- section header string table index: 字符串表在section表中的索引
段表(section header table)
段表就是保存ELF文件中各种各样段的基本属性的结构,段表是ELF除了文件以外最重要的结构体,它描述了ELF的各个段的信息。ELF文件的段结构就是由段表决定的。编译器,链接器和装载器都是依靠段表来定位和访问各个段的属性的。
一些特殊section
名称 | 类型 | 属性 | 含义 |
---|---|---|---|
.bss | SHT_NOBITS | SHF_ALLOC+SHF_WRITE | 包含出现在程序的内存映像中的未初始化数据。程序开始执行,系统将把这些数据初始化为0 |
.comment | SHT_PROGBITS | 包含版本控制信息 | |
.data | SHT_PROGBITS | SHF_ALLOC+SHF_WRITE | 包含了初始化了的数据,将出现在程序的内存映像中 |
.dynamic | SHT_DYNAMIC | SHF_ALLOC | 包含了用于动态连接信息,节区的属性将包含SHF_ALLOC位,是否SHF_WRITE位被设置取决于处理器 |
.dynstr | SHT_STRTAB | SHF_ALLOC | 包含了用于动态连接的字符串,大多数情况下这些字符串代表了于符号表项相关的名称 |
.dynsym | SHT_DYNSYM | SHF_ALLOC | 包含了动态连接符号表 |
.got | SHT_PROGBITS | 包含了全局偏移表 | |
.hash | SHT_HASH | SHF_ALLOC | 包含了一个符号哈希表 |
.init | SHT_PROGBITS | SHF_ALLOC+SHF_EXECINSTR | 包含了可执行指令,是进程初始化代码的一部分。在主程序入口(main函数)之前执行这些代码。 |
.plt | SHT_PROGBITS | 包含了过程链接表 | |
.text | SHT_PROGBITS | SHF_ALLOC+SHF_EXECINSTR | 包含程序的可执行指令 |
符号表 Symbol table
在链接中,函数和变量统称为符号,函数名或变量名就是符号名。每个目标文件都会有一个符号表,这个表里面记录了目标文件中所用到的所有符号,每个定义的符号有一个对应的值,叫符号值,对于函数和变量来说,符号值就是他们的地址。符号表中的符号可以分为以下几类:
- 定义在本目标文件中的全局符号
- 本目标文件中引用的,没有定义在本目标文件中的全局符号,一般称为外部符号
- 节名,值为该节的起始地址
- 局部符号:该类符号只在编译单元内部可见,这些符号对于链接过程没有作用
- 行号信息:目标文件指令与源代码中代码行的对应关系
plt表和got表
关于plt表和got表的相关知识,请参考我的这篇博客