赞
踩
ELF Header |
.text |
.data |
.bss |
other sections |
Section header table |
String Tables |
Symbol Tables |
… |
ELF文件头(Elf header)位于最前部,它包含了描述整个文件的基本属性,包括ELF文件版本、目标机器型号、程序入口地址等
readelf -h命令可以查看文件头的相关信息
$ readelf -h ez_crackme
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x7c0
Start of program headers: 52 (bytes into file)
Start of section headers: 12588 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 9
Size of section headers: 40 (bytes)
Number of section headers: 27
Section header string table index: 26
这是将文件头解析出来的结果
各个常量和结构体定义在/usr/include/elf.h中
ELF文件有32位版本和64位版本两种,文件头也有这两种版本,分别叫做Elf32_Ehdr
和Elf64_Ehdr
32位版本与64位版本的ELF文件的文件头内容是一样的,只是一些成员由于地址不同而使得大小不同
除了e_ident成员对应了Class, Data, Verion, OS/ABI和ABI Version五个参数以外,其他成员都是一一对应的
以32位为例
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf32_Half e_type; /* Object file type */
Elf32_Half e_machine; /* Architecture */
Elf32_Word e_version; /* Object file version */
Elf32_Addr e_entry; /* Entry point virtual address */
Elf32_Off e_phoff; /* Program header table file offset */
Elf32_Off e_shoff; /* Section header table file offset */
Elf32_Word e_flags; /* Processor-specific flags */
Elf32_Half e_ehsize; /* ELF header size in bytes */
Elf32_Half e_phentsize; /* Program header table entry size */
Elf32_Half e_phnum; /* Program header table entry count */
Elf32_Half e_shentsize; /* Section header table entry size */
Elf32_Half e_shnum; /* Section header table entry count */
Elf32_Half e_shstrndx; /* Section header string table index */
} Elf32_Ehdr;
值得一提的是
- e_ident
共16字节
其中4字节魔数(Magic Number)标识ELF文件
1字节文件类,1表示32位,2表示64位
1字节字节序,表示大小端
1字节主版本号,通常是1(因为ELF标准只到1.2版)
其余9字节未在ELF标准中定义,有些平台会使用它们作为扩展标志
- e_type
标识ELF文件类型
- 可重定位文件(.o)
- 可执行文件
- 共享目标文件(.so)
- e_entry
Entry point address,规定了ELF程序的入口虚拟地址
- e_shoff
Start of section headers,表示段表在文件中的偏移字节数
- e_ehsize
Size of this header,表示文件头的大小
- e_shentsize
Size of section header,表示段表描述符的大小
- e_shnum
Number of section header,表示段表描述符的数量,即ELF文件中拥有几个段
- e_shstrndx
Section header string table index,字符串表在段表中的下标
紧接着是ELF文件各个段,最重要的是段表(Section Header Table),它描述各个段的信息,包括段名、长度、偏移、读写权限等等
通过objdump -h和readelf -s可以读出各个段的信息,不过前者仅列出比较重要的一些段,忽略字符串表等辅助段,而后者将会把所有段全部列出
$ readelf -S ez_crackme
There are 27 section headers, starting at offset 0x312c:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 00000154 000154 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 00000168 000168 000020 00 A 0 0 4
[ 3] .note.gnu.build-i NOTE 00000188 000188 000024 00 A 0 0 4
[ 4] .gnu.hash GNU_HASH 000001ac 0001ac 000034 04 A 5 0 4
[ 5] .dynsym DYNSYM 000001e0 0001e0 000110 10 A 6 1 4
[ 6] .dynstr STRTAB 000002f0 0002f0 0000f6 00 A 0 0 1
[ 7] .gnu.version VERSYM 000003e6 0003e6 000022 02 A 5 0 2
[ 8] .gnu.version_r VERNEED 00000408 000408 000040 00 A 6 1 4
[ 9] .rel.dyn REL 00000448 000448 0002f8 08 A 5 0 4
[10] .init PROGBITS 00000740 000740 000023 00 AX 0 0 4
[11] .plt PROGBITS 00000770 000770 000010 04 AX 0 0 16
[12] .plt.got PROGBITS 00000780 000780 000040 00 AX 0 0 8
[13] .text PROGBITS 000007c0 0007c0 001872 00 AX 0 0 16
[14] .fini PROGBITS 00002034 002034 000014 00 AX 0 0 4
[15] .rodata PROGBITS 00002060 002060 0001f6 00 A 0 0 32
[16] .eh_frame_hdr PROGBITS 00002258 002258 0000dc 00 A 0 0 4
[17] .eh_frame PROGBITS 00002334 002334 0003b4 00 A 0 0 4
[18] .init_array INIT_ARRAY 00003ed0 002ed0 000004 00 WA 0 0 4
[19] .fini_array FINI_ARRAY 00003ed4 002ed4 000004 00 WA 0 0 4
[20] .jcr PROGBITS 00003ed8 002ed8 000004 00 WA 0 0 4
[21] .dynamic DYNAMIC 00003edc 002edc 0000e8 08 WA 6 0 4
[22] .got PROGBITS 00003fc4 002fc4 00003c 04 WA 0 0 4
[23] .data PROGBITS 00004000 003000 000008 00 WA 0 0 4
[24] .bss NOBITS 00004020 003008 000144 00 WA 0 0 32
[25] .comment PROGBITS 00000000 003008 000034 01 MS 0 0 1
[26] .shstrtab STRTAB 00000000 00303c 0000ed 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
段表实际上是一个Elf32_Shdr
结构体数组。
这个结构体定义也在elf.h中,又被叫做段描述符
同样以32位为例
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;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。