ELF文件格式-第一讲,详解程序文件头

目录

Elf文件格式 ELF32or64

前言

本文参考链接: https://segmentfault.com/a/1190000007103522?utm_source=tuicool&utm_medium=referral

非原创。 在学习ELF的过程中记录自己学习的历程。

参考数据: LINUX二进制分析

一丶ELF 程序头

​ 一个ELF文件可以被标记为以下几种类型

名词 属性 注解
ET_NONE 未知类型 这个标记表明了文件类型不确定或者还未定义
ET_REL 重定位文件 如果elf文件标记为了relocatable那么意味着该文件被标记为了一段可冲定位的代码,也称为目标文件。可重定位目标文件通常是还未被链接到可执行程序的一段位置独立代码的代码(position independent code)。在编译完代码之后通常可以看到一个.o的格式的文件,这种文件包含了创建可执行文件所需要的代码和数据。
ET_EXEC 可执行文件 elf文件如果为executable,那么表明了这个文件被标记为了可执行文件。这种类型的文件也成为程序,是一个进程开始执行的入口。
ET_DYN 共享目标文件 ELF类型如果为dynamic意味着该文件被标记为了一个动态的可链接的目标文件,也称为共享库。这类共享库会在程序运行的时候被装载并且链接到程序的进程镜像中。
ET_CORE 核心文件 在进程崩溃或者进程传递了一个SIGSEGV信号(分段违规)时,会在核心文件中记录整个进程的镜像信息。可以使用GDB读取这类文件来辅助调试并且查找程序崩溃的原因。

在linux有一个readelf的小程序。 可以来查看elf文件。 可以看到原始的elf文件头。

其实所谓的格式就是 C语言中的结构体来做表,并且赋予每个字段含义以及信息。

例子:

>>> readelf -h main.out
ELF 头:
Magic:  7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
类别:                              ELF32
数据:                              2 补码,小端序 (little endian)
Version:                           1 (current)
OS/ABI:                            UNIX - System V
ABI 版本:                          0
类型:                              DYN (共享目标文件)
系统架构:                          Intel 80386
版本:                              0x1
入口点地址:              0x1070
程序头起点:              52 (bytes into file)
Start of section headers:          13980 (bytes into file)
标志:             0x0
Size of this header:               52 (bytes)
Size of program headers:           32 (bytes)
Number of program headers:         12
Size of section headers:           40 (bytes)
Number of section headers:         30
Section header string table index: 29

elf文件的结构如下

#define EI_NIDENT 16
typedef struct
{
    unsigned char e_ident[EI_NIDENT];
    uint16_t e_type;                    ;表示文件的类型,这里为3 就是ET_DYN类型
    uint16_t e_machine;                 ;表示平台的版本,我使用gcc编译所以标识 intel 8086
    uint32_t e_version;                 ; 表示版本号
    ElfN_Addr e_entry;					; 重要字段标识了入口点位置程序的第一行代码位置
    ElfN_Off e_phoff;                   ; 重要,标识了program table的在文件的偏移开始位置
    ElfN_Off e_shoff;                   ;section header table的偏移位置
    uint32_t e_flags;                   ;保存与文件相关 特定于处理器的标识。
    uint16_t e_ehsize;
    uint16_t e_phentsize;              ;重要字段,表明了program table 每个结构体的大小           
    uint16_t e_phnum;                  ;重要字段,表明programtable有多少项
    uint16_t e_shentsize;              ;表明了sectiontable每一项结构有多大
    uint16_t e_shnum;                  ;表明了sectiontable有多少项
    uint16_t e_shstrndx;               ;节区头部表格中与节区名称字符串相关的表项的索引。
} ElfN_Ehdr;

其实重要的就几个字段

1.ELF文件标识头(4个字节即可)

  1. e_entry 记录的程序开始位置
  2. e_phoff 记录了program table在文件的起始位置
  3. e_ phentsize 记录了program table的每个结构大小
    .5 e_phnum 表明了有多少个 program table

其余的非必须的都可以设置为错误的值。对于程序来说是可以正常运行的。可以进行手动尝试

1.2 详解elf头(32or64)

​ 上面所说是实际应用过程中我们需要重点了解的内容

那么下面就给出详细的elf头。让我们更加的了解elf其他属性以及作用。

1.2.1 简介

​ 可制定链接格式 最初是由UNIX系统实验室开发并且发布的。是作为应用程序二进制接口的一部分。 工具接口委员会还在将发展的ELF标准选作为一种可移植的目标文件格式。 可以在32位的intel体系结构上的很多操作系统中使用。

其中目录文件有三种类型,分别如下表所示:

名词 文件后缀 注解
可重定位文件(RelocatableFIle) .o 结尾 包含适合于其他目标文件链接来创建可执行文件或者共享目标文件的代码和数据。
可执行文件(ExecutableFIle) .exe 包含适合于可执行的一个程序,此文件规定了exec()如何创建一个程序的进程映像
共享目标文件(Shared object FIle) .so 包含可在两种上下文中链接的代码和数据。首先链接编辑器可以将它和其它可重定位文件和共享目标文件一起处理, 生成另外一个目标文件。其次动态链接器(Dynamic Linker)可能将它与某 个可执行文件以及其它共享目标一起组合,创建进程映像。

特点:

目标文件全部是程序的二进制表示。 目的就是直接在某种处理器上直接执行。

1.2.2 数据表示表格

​ 目标文件格式支持8位字节/32位的体系架构。不过他们是可以扩展了。也就是可以运行在现在64位的机器上。

下图则标识各个结构信息的名称 大小 对其方式等等。

名称 大小 对齐 目的
Elf32_Addr 4 4 无符号程序地址
Elf32_Half 2 2 无符号中等整数 也就是 unsigned short表示
Elf32_Off 4 4 无符号文件偏移
Elf32_SWord 4 4 有符号整数
Elf32_Word 4 4 无符号整数
unsigned char 1 1 无符号1字节

目标文件中所有的数据结构都要遵守自然大小和对齐的规则。

如果有必要则会进行对齐操作。

1.2.3 Elf Hearder表示

32位结构如下:

/* ELF Header */
#define EI_NIDENT 16
typedef struct elfhdr {
    unsigned char    e_ident[EI_NIDENT]; /* ELF Identification */
    Elf32_Half    e_type;        /* object file type */
    Elf32_Half    e_machine;    /* machine */
    Elf32_Word    e_version;    /* object file version */
    Elf32_Addr    e_entry;    /* virtual entry point */
    Elf32_Off    e_phoff;    /* program header table offset */
    Elf32_Off    e_shoff;    /* section header table offset */
    Elf32_Word    e_flags;    /* processor-specific flags */
    Elf32_Half    e_ehsize;    /* ELF header size */
    Elf32_Half    e_phentsize;    /* program header entry size */
    Elf32_Half    e_phnum;    /* number of program header entries */
    Elf32_Half    e_shentsize;    /* section header entry size */
    Elf32_Half    e_shnum;    /* number of section header entries */
    Elf32_Half    e_shstrndx;    /* section header table's "section 
                       header string table" entry offset */
} Elf32_Ehdr;

64位结构如下

typedef struct {
    unsigned char    e_ident[EI_NIDENT];    /* Id bytes */
    Elf64_Quarter    e_type;            /* file type */
    Elf64_Quarter    e_machine;        /* machine type */
    Elf64_Half    e_version;        /* version number */
    Elf64_Addr    e_entry;        /* entry point */
    Elf64_Off    e_phoff;        /* Program hdr offset */
    Elf64_Off    e_shoff;        /* Section hdr offset */
    Elf64_Half    e_flags;        /* Processor flags */
    Elf64_Quarter    e_ehsize;        /* sizeof ehdr */
    Elf64_Quarter    e_phentsize;        /* Program header entry size */
    Elf64_Quarter    e_phnum;        /* Number of program headers */
    Elf64_Quarter    e_shentsize;        /* Section header entry size */
    Elf64_Quarter    e_shnum;        /* Number of section headers */
    Elf64_Quarter    e_shstrndx;        /* String table index */
} Elf64_Ehdr;

成员1: e_ident 是一些标识信息。总共大小是16个字节(32位的结构)

其中他是一个数组。 有一些ELF的标识信息,用来标识数组中不同下表的含义。

名称 目的
EI_MAG0 0 文件标识
EI_MAG1 1 文件标识
EI_MAG2 2 文件标识
EI_MAG3 3 文件标识
EI_CLASS 4 文件类
EI_DATA 5 数据编码
EI_VERSION 6 文件的版本
EI_PAD 7 补齐字节开始处
EI_NIDENT 16 e_ident[]的大小

这就是每个下标的意义。 那么下面分别说下索引中每个值

ELF文件格式-第一讲,详解程序文件头

其余字段意义如下

ELF文件格式-第一讲,详解程序文件头

在LINUX下可以使用 readelf -h youelf 则可以看小elf文件头的信息

上一篇:SQL注入介绍


下一篇:面试官:不用背概念,说清楚cookie和session是怎么交互的?