可执行文件的数据结构通常都很复杂和繁琐。原因在于程序在加载到内存中执行时需要经过一系列非常复杂的步骤。例如要计算数据或代码被加载到虚拟内存时的位置,计算重定向数值,实现不同代码的链接等。
本节我们一点一滴的了解段的数据格式和作用,这对我们后面了解Linux系统如何加载运行程序,并掌握相关的高级hack技术有非常重要的作用,首先我们看段头对应的数据结构,它用于描述ELF文件中某个段的基本特征:
typedef struct {
uint32_t sh_name; #段名
uint32_t sh_type; #段的类型
uint64_t sh_flags; #段标志位
uint64_t sh_addr; #段被加载到内存中的位置
uint64_t sh_offset; #段对应数据在ELF文件中的偏移
uint64_t sh_size; #段的大小
uint64_t sh_link; #与该段有关系的其他段对应的段头在段头表中的下标
uint32_t sh_info; #与该段有关的信息
uint64_t sh_addralign; #段是否需要字节对齐、
uint64_t sh_entsize; #如果段含有表结构,该字段对应表中每一项的大小
}Elf64_Shdr;
用于描述段性质的段头数据结构以表格的方式存储在ELF文件中。表中每一项就对应上面描述的数据结构。该结构中的第一个字段用于指向段的名称。名称当然得对应字符串,但sh_name却是一个四字节整形,那是因为所有字符串都被存储在字符串段中,这个段里面的数据全是以0结尾的字符