ELF文件格式分析
ELF文件格式分析
基本知识:
1.ELF文件的三种类型:
l 可重定位:
编译器和汇编器创建
运行前需要被链接器处理
l 可执行
完成了所有重定位工作和符号解析
除了运行时解析的共享库符号
l 共享库
链接器需要的符号信息
运行时可以直接执行的代码
2.ELF文件的两个视角:
3.可重定位目标文件结构:
ELF头部 |
.text |
.rodata |
.data |
.bss |
.sym |
.rel.txt |
.rel.data |
.line |
.debug |
.strtab |
节头部表 |
分析过程:
自编一个简单的程序,并对其进行编译。生成一些elf文件:
在终端中键入hexdump -x hello,会看到很多16进制编码。
数据均为16进制数据(因为使用了-x选项),并且第一列为偏移地址。
使用下面命令来显示hello中各个段相关信息:objdump –x hello
输出结果如下:
也可以用下面的命令来查看各个段信息:
readelf -a hello
下面分析hello文件内容
l 文件头分析:
首先是Elf文件头,其定义为(在/usr/include/elf.h中)64位系统包括两部分:
2.section header
typedef struct
{
Elf32_Word sh_name; /* Section name (string tbl index) */
Elf32_Word sh_type; /* Section type */
Elf32_Word sh_flags; /* Section flags */
Elf32_Addr sh_addr; /* Section virtual addr at execution */
Elf32_Off sh_offset; /* Section file offset */
Elf32_Word sh_size; /* Section size in bytes */
Elf32_Word sh_link; /* Link to another section */
Elf32_Word sh_info; /* Additional section information */
Elf32_Word sh_addralign; /* Section alignment */
Elf32_Word sh_entsize; /* Entry size if section holds table */
} Elf32_Shdr;
typedef struct
{
Elf64_Word sh_name; /* Section name (string tbl index) */
Elf64_Word sh_type; /* Section type */
Elf64_Xword sh_flags; /* Section flags */
Elf64_Addr sh_addr; /* Section virtual addr at execution */
Elf64_Off sh_offset; /* Section file offset */
Elf64_Xword sh_size; /* Section size in bytes */
Elf64_Word sh_link; /* Link to another section */
Elf64_Word sh_info; /* Additional section information */
Elf64_Xword sh_addralign; /* Section alignment */
Elf64_Xword sh_entsize; /* Entry size if section holds table */
} Elf64_Shdr;
第二行:e_type(两个字节)值为0x0002,表示是一个可执行文件。
e_machine(两个字节)值为0x003e,表示是X86-64的处理器体系结构。
e_version(四个字节)值为0x00000001,表示是当前版本。
e_entry(八个字节)值为0x0550004000000000,表示入口点
第三行:e_phoff(八个字节)值为0x0000000000000000,表示没有程序头表。
e_shoff(八个字节)值为0x0000000000000420,表示段表的偏移地址。
第四行:e_flags(四个字节)值为0x00000000,表示未知处理器特定标志
e_ehsize(两个字节)值为0x0040,表示elf文件头大小;
e_phentsize(两个字节)值均为0x0000,因为重定位文件没有程序头表。
e_phnum(两个字节)的值为0x0000,因为重定位文件没有程序头表。
e_ehentsize(两个字节)值为0x0040表示段头大小为64个字节(由这里知道section header table里面每个header的大小)。
e_shnum(两个字节)值为0x000d,表示段表入口有13个(由这里知道段表有13个段)。
e_shstrndx(两个字节)值为0x000a,表示段名串表的在段表中的索引号(由这里知道.shstrtab段(符号表)的信息在段表的索引号是10)。
由ELF头可知段表从00000420开始,每个节区大小为0040,共有000d个节区,第000a为段名串表的索引号。
第二节区(461-4a0)
第四节区(4e1-520)
第八节区(5e1-620)
第九节区(621-660)
第十二节区(6e1-720)