ELF文件由ELF头、程序头表、节头表、节和段组成,ELF头描述文件属性,程序头表指导加载到内存的段映射,节头表用于链接调试,节存储实际数据,段由多个节构成并决定内存布局,通过readelf等工具可分析其结构。

ELF(Executable and Linkable Format)是Linux系统中广泛使用的可执行文件、目标文件和共享库的标准格式。理解ELF结构对逆向分析、程序调试和系统安全研究非常重要。它不仅决定了程序如何被加载执行,还包含了链接、重定位、符号等关键信息。
ELF文件的基本组成
一个典型的ELF文件由以下几个主要部分构成:
- ELF头(ELF Header):位于文件最开始,描述整个文件的基本属性,如类型(可执行、共享库等)、架构(x86、ARM等)、入口地址、程序头表和节头表的位置与数量。
- 程序头表(Program Header Table):用于运行时加载,告诉操作系统如何将文件映射到内存,每个条目称为一个段(Segment),如代码段(LOAD)、动态链接信息等。
- 节头表(Section Header Table):用于链接和调试,包含各个节(Section)的信息,如 .text(代码)、.data(已初始化数据)、.symtab(符号表)、.strtab(字符串表)等。
- 节(Sections):实际的数据存储单元,用于链接阶段处理,不一定会全部加载到内存。
- 段(Segments):由多个节组成,是操作系统加载器关心的单位,决定内存布局。
可以用readelf -h 查看ELF头内容,快速识别文件类型和架构。
解析ELF头信息
ELF头固定长度为64字节(64位系统)或52字节(32位系统),其结构定义在
- e_ident:前16个字节标识ELF魔数(0x7F, 'E', 'L', 'F'),以及位数、字节序、版本等。
- e_type:文件类型,如ET_EXEC(可执行文件)、ET_DYN(共享对象)。
- e_machine:目标机器架构,如EM_X86_64、EM_ARM。
- e_entry:程序入口虚拟地址,CPU开始执行的位置。
- e_phoff / e_shoff:程序头表和节头表在文件中的偏移。
- e_phnum / e_shnum:程序头和节头的数量。
例如,使用readelf -h ./a.out可以看到入口点地址和是否为动态链接可执行文件。
程序头表与内存加载机制
程序头表指导操作系统如何将ELF文件加载进内存。每个程序头描述一个段,常见类型有:
- PT_LOAD:表示需要加载到内存的段,包含代码或数据。每个LOAD段有文件偏移、虚拟地址、内存大小、权限(r-x, rw-)等属性。
- PT_DYNAMIC:指向动态链接信息,如依赖的共享库、重定位表位置。
- PT_INTERP:指定动态链接器路径,如 /lib64/ld-linux-x86-64.so.2。
- PT_GNU_STACK:控制栈是否可执行,用于安全防护。
通过readelf -l 可以查看所有段及其内存布局。加载器会根据这些信息设置虚拟内存空间,并进行页对齐映射。
节头表与链接过程
节头表主要用于链接和调试,不参与运行时加载。每个节保存特定类型的数据:
- .text:存放编译后的机器指令。
- .data / .bss:分别存放已初始化和未初始化的全局变量。
- .rodata:只读数据,如字符串常量。
- .symtab:符号表,记录函数和全局变量名及其地址。
- .strtab:字符串表,保存符号名等字符串。
- .rel.text / .rel.data:重定位表,指示链接时需要修补的位置。
使用readelf -S 列出所有节,结合objdump -d反汇编代码,可深入分析程序结构。
基本上就这些。掌握ELF格式有助于理解程序从磁盘到内存的全过程,也能更好应对二进制分析任务。虽然结构复杂,但工具链完善,配合readelf、objdump、hexdump等命令,能逐步拆解每一个细节。










