HKAlong
- 关注
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
第二部分主要介绍ELF的格式,ELF是Executable and Linkable Format的缩写,即可执行与可链接的文件格式的总称。ELF是UNIX系统常见的标准文件格式,如可执行文件、目标文件、共享库文件及core dumps文件。
一般来说,ELF文件由三部分组成:可执行文件的头、节和段
链接视图(节视图) | 执行视图(段视图) |
ELF文件的头 | ELF文件的头 |
程序头部表(可选) | 程序头部表 |
节1 | 段1 |
.... .... | |
节n | 段2 |
.... .... | |
.... .... | |
节头部表 | 节头部表(可选) |
64位ELF二进制文件的格式和内容如下:
在linux系统中,ELF文件定义位置: /usr/include/elf.h 。接下来我们来拆解一下文件。
1、ELF头部
ELF64_Ehdr定义如下:
typedef struct {
unsigned char e_ident[16]; /* 幻数以及其他信息*/
uint16_t e_type; /* 对象文件类型*/
uint16_t e_machine; /* 架构*/
uint32_t e_version; /* 对象文件版本*/
uint64_t e_entry; /* 程序入口的虚拟地址*/
uint64_t e_phoff; /* 程序头表的偏移量(按字节计算)*/
uint64_t e_shoff; /* 节头表的偏移量(按字节计算)*/
uint32_t e_flags; /* 保存与文件相关的、特定于处理器的标 志。标志名称采用EF_machine_flag的格式*/ uint16_t e_ehsize; /* ELF头部的大小(按字节计算) */
uint16_t e_phentsize; /* 程序头表的条目大小(按字节计算) */
uint16_t e_phnum; /* 程序头表的条目数,可以为0 */
uint16_t e_shentsize; /* 节头表的条目大小(按字节计算) */
uint16_t e_shnum; /* 节头表的条目数,可以为0 */
uint16_t e_shstrndx; /* 节头表中与节名称字符串表相关的条目的 索引。如果文件没有节名称字符串表,此参数可以为SHN_UNDEF */
} Elf64_Ehdr;
1.1、e_ident数组
幻数由十六进制数字0x7f组成,后跟字母E、L及F的 ASCII字符代码
字节偏移 | 名称 | 含义 |
0 | EI_MAG0 | 魔数的第一个字节,通常为 0x7F('0x7F') |
1 | EI_MAG1 | 魔数的第二个字节,通常为 'E'('0x45') |
2 | EI_MAG2 | 魔数的第三个字节,通常为 'L'('0x4C') |
3 | EI_MAG3 | 魔数的第四个字节,通常为 'F'('0x46') |
4 | EI_CLASS | 文件的位数,标识是 32 位还是 64 位,可能的值为: |
- ELFCLASS32 (1):32 位对象 | ||
- ELFCLASS64 (2):64 位对象 | ||
5 | EI_DATA | 数据编码方式,标识字节序,可能的值为: |
- ELFDATA2LSB (1):小端字节序(Least Significant Byte first) | ||
- ELFDATA2MSB (2):大端字节序(Most Significant Byte first) | ||
6 | EI_VERSION | ELF 版本,通常为 1(EV_CURRENT) |
7 | EI_OSABI | 操作系统和 ABI 标识,可能的值为: |
- ELFOSABI_SYSV (0):UNIX System V ABI | ||
- ELFOSABI_HPUX (1):HP-UX ABI | ||
- ELFOSABI_NETBSD (2):NetBSD ABI | ||
- ELFOSABI_LINUX (3):Linux ABI | ||
- ELFOSABI_SOLARIS (6):Solaris ABI | ||
- ELFOSABI_AIX (7):AIX ABI | ||
- ELFOSABI_IRIX (8):IRIX ABI | ||
- ELFOSABI_FREEBSD (9):FreeBSD ABI | ||
- ELFOSABI_TRU64 (10):TRU64 UNIX ABI | ||
- ELFOSABI_MODESTO (11):Novell Modesto ABI | ||
- ELFOSABI_OPENBSD (12):OpenBSD ABI | ||
- ELFOSABI_ARM_AEABI (64):ARM EABI | ||
- ELFOSABI_ARM (97):ARM ABI | ||
- ELFOSABI_STANDALONE (255):Standalone (embedded) ABI | ||
8 | EI_ABIVERSION | ABI 版本号 |
9 | EI_PAD | 填充字节,通常为 0,用于对齐和将来扩展 |
10 | EI_PAD | 填充字节,通常为 0,用于对齐和将来扩展 |
11 | EI_PAD | 填充字节,通常为 0,用于对齐和将来扩展 |
12 | EI_PAD | 填充字节,通常为 0,用于对齐和将来扩展 |
13 | EI_PAD | 填充字节,通常为 0,用于对齐和将来扩展 |
14 | EI_PAD | 填充字节,通常为 0,用于对齐和将来扩展 |
15 | EI_PAD | 填充字节,通常为 0,用于对齐和将来扩展 |
如下是在系统中使用readelf查看文件的头信息
root@z:~/bin_learn/chater01# 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: DYN (Shared object file) # e_type
Machine: Advanced Micro Devices X86-64 # e_machine
Version: 0x1 # e_version
Entry point address: 0x1060 # e_entry字段表示二进制文件的入口点
Start of program headers: 64 (bytes into file) # e_phoff程序头的偏移量,64字节
Start of section headers: 14712 (bytes into file) # e_shoff节头表的偏移量14712字节
Flags: 0x0 # e_flags字段保存了二进制文件在特定处理器的标志,对于x86二进制文件,e_flags通常设置为零
Size of this header: 64 (bytes) # e_ehsize以字节单位指定了ELF头部的大小
Size of program headers: 56 (bytes) # e_phentsize; /* 程序头表的条目大小(按字节计算) */
Number of program headers: 13 # e_phnum; /* 程序头表的条目数,可以为0 */
Size of section headers: 64 (bytes) # e_shentsize; /* 节头表的条目大小(按字节计算) */
Number of section headers: 31 # e_shnum; /* 节头表的条目数,可以为0 */
Section header string table index: 30 # e_shstrndx字段包含一个名为.shstrtab的、与特殊字符串表 节(string table section)相关的头索引(在节头表中)。 .shstrtab的节头在索引30 的位置
查看shstrtab节头:
root@z:~/bin_learn/chater01# readelf -x .shstrtab a.out
Hex dump of section '.shstrtab':
0x00000000 002e7379 6d746162 002e7374 72746162 ..symtab..strtab
0x00000010 002e7368 73747274 6162002e 696e7465 ..shstrtab..inte
0x00000020 7270002e 6e6f7465 2e676e75 2e70726f rp..note.gnu.pro
0x00000030 70657274 79002e6e 6f74652e 676e752e perty..note.gnu.
0x00000040 6275696c 642d6964 002e6e6f 74652e41 build-id..note.A
0x00000050 42492d74 6167002e 676e752e 68617368 BI-tag..gnu.hash
0x00000060 002e6479 6e73796d 002e6479 6e737472 ..dynsym..dynstr
0x00000070 002e676e 752e7665 7273696f 6e002e67 ..gnu.version..g
0x00000080 6e752e76 65727369 6f6e5f72 002e7265 nu.version_r..re
0x00000090 6c612e64 796e002e 72656c61 2e706c74 la.dyn..rela.plt
0x000000a0 002e696e 6974002e 706c742e 676f7400 ..init..plt.got.
0x000000b0 2e706c74 2e736563 002e7465 7874002e .plt.sec..text..
0x000000c0 66696e69 002e726f 64617461 002e6568 fini..rodata..eh
0x000000d0 5f667261 6d655f68 6472002e 65685f66 _frame_hdr..eh_f
0x000000e0 72616d65 002e696e 69745f61 72726179 rame..init_array
0x000000f0 002e6669 6e695f61 72726179 002e6479 ..fini_array..dy
0x00000100 6e616d69 63002e64 61746100 2e627373 namic..data..bss
0x00000110 002e636f 6d6d656e 7400 ..comment.
2、节头
节头的第一个字段称为sh_name,如果该字段 被设置,则在字符串表中包含索引,如果索引为零,则表示
畅读付费文章
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
