ELF文件格式解析
ELF(Executable and Linkable Format) 即可执行可链接文件格式,是目前操作系统上最常见的可执行文件格式。不同系统的目标文件不一样,Windows是PE(Portable Executable),linux是ELF(Executable Linkable Format),它们都是COFF(Common file format)格式的变种。
1、基本格式
ELF格式的目标文件和可执行文件在结构上没有本质差异,ELF不仅仅描述目标文件,也用于描述可执行文件,Windows下的dll和.lib, Linux下的.so和.a文件都是按照类ELF格式存储,下图描述了ELF链接视图(.o文件、.so文件)和执行视图,链接视图描述了各个段(section)的组成,如.text、.data、bss段。执行视图由segment组成,segment用于表示一个一定长度的区域,按照只读/可读写划分,不区分数据的属性,如代码段、数据段。
目标文件是未经过链接的,里面的符号和地址没有调整导致无法运行。例如直接运行目标文件,系统提示无法执行该二进制文件。
$ . hello.o
bash: .: hello.o: cannot execute binary file
$ file hello.o
hello.o: Intel amd64 COFF object file, no line number info, not stripped, 7 sections, symbol offset=0x2a0, 22 symbols, 1st section name ".text"
ELF文件格式在字节对齐和元素解析时,与系统架构、字长有密切关系,ELF 文件由ELF header和各种段组成,其结构图如下所示。详细文档可以查阅https://elinux.org/Executable_and_Linkable_Format_(ELF)。
2、ELF文件头
ELF 文件的最前面是文件头,描述了ELF文件的基本属性,比如ELF文件版本、目标机器型号、程序入口地址。
详细的描述可以参考:https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html
#define EI_NIDENT 16 typedef struct {
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr; $ readelf -h /bin/ls
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 (Position-Independent Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x6180
Start of program headers: 64 (bytes into file)
Start of section headers: 145256 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 11
Size of section headers: 64 (bytes)
Number of section headers: 30
Section header string table index: 29
上面结构体里成员类型长度的定义为:
名称 |
大小 |
说明 |
Elf32_Addr |
4 |
无符号程序地址 |
Elf32_Half |
2 |
无符号中等整数 |
Elf32_Off |
4 |
无符号文件偏移 |
Elf32_SWord |
4 |
有符号大整数 |
Elf32_Word |
4 |
无符号大整数 |
unsigned char |
1 |
无符号笑整数 |
Elf32_Ehdr 各个成员简介:
- e_ident magic bytes (0x7fELF), class, ABI version....是一组包含多个标志的数组。
- e_typeobject file type—ET{REL,DYN,EXEC,CORE} 00-未知, 01--RT_REL,02--ET_EXEC, 03---ET_DY
- e_machine required architecture—EM X86 64, ... 其中3h=386, 28h=ARM
- e_version EV CURRENT, always ”1”
- e_entry virt. addr. of entry point, dl start, jmp *%r12
- e_phoff program header offset
- e_shoff section header offset
- e_flags CPU-specific flags
- e_ehsize ELF header size
- e_phentsize size of program header entry, consistency check
- e_phnum number of program header entries
- e_shentsize size of section header entry
- e_shnum number of section header entries
- e_shstrndx section header string table index
其中e_ident 对应了对各字段,有MAGIC、Class、Data、Version、 ABI这几个参数。
Name |
Value |
Purpose |
EI_MAG0 |
0 |
File identification |
EI_MAG1 |
1 |
File identification |
EI_MAG2 |
2 |
File identification |
EI_MAG3 |
3 |
File identification |
EI_CLASS |
4 |
File class |
EI_DATA |
5 |
Data encoding |
EI_VERSION |
6 |
File version |
EI_OSABI |
7 |
Operating system/ABI identification |
EI_ABIVERSION |
8 |
ABI version |
EI_PAD |
9 |
Start of padding bytes |
EI_NIDENT |
16 |
Size of e_ident[] |
1)MAGIC是ELF标志码:魔数,占4字节,byte0固定为0x7F,byte1--byte3是'E', 'L', 'F' 的ASCII码。
2)EI_CLASS 是CPU字长类型。
Name |
Value |
Meaning |
ELFCLASSNONE |
0 |
Invalid class |
ELFCLASS32 |
1 |
32-bit objects |
ELFCLASS64 |
2 |
64-bit objects |
3)EI_DATA
0:非法格式
1:小端字节序LSB
2:大端字节序MSB
4)EI_VERSION: ELF版本号,为1
5)EI_OSABI
Name |
Value |
Meaning |
ELFOSABI_NONE |
0 |
No extensions or unspecified |
ELFOSABI_HPUX |
1 |
Hewlett-Packard HP-UX |
ELFOSABI_NETBSD |
2 |
NetBSD |
ELFOSABI_LINUX |
3 |
Linux |
ELFOSABI_SOLARIS |
6 |
Sun Solaris |
ELFOSABI_AIX |
7 |
AIX |
ELFOSABI_IRIX |
8 |
IRIX |
ELFOSABI_FREEBSD |
9 |
FreeBSD |
ELFOSABI_TRU64 |
10 |
Compaq TRU64 UNIX |
ELFOSABI_MODESTO |
11 |
Novell Modesto |
ELFOSABI_OPENBSD |
12 |
Open BSD |
ELFOSABI_OPENVMS |
13 |
Open VMS |
ELFOSABI_NSK |
14 |
Hewlett-Packard Non-Stop Kernel |
64-255 |
Architecture-specific value range |
3、段表--Section
1)段表的结构
ELF 文件中有很多段,段表(Section Header Table)就是保存这些段的基本属性的结构。段表描述了ELF各个段的信息,如段名、段的长度、在文件中的偏移、读写权限等。段表在ELF文件中 的偏移是由文件头的e_shoff成员决定的。
typedef struct{
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
}Elf32_Shdr
Elf32_Shdr成员含义:
- sh_name 段名,但此次只是记录了段名字符串在 .shstrtab 中的偏移
- sh_type 段的类型
- sh_flags 段的标志位
- sh_addr 段的虚拟地址,如果此段可以被加载则表示在进程中的虚拟地址,否则为0
- sh_offset 如果此段位于文件中则表示此段在文件中的偏移
- sh_size 段的长度
- sh_link This member holds a section header table index link, whose interpretation depends on the section type.
- sh_info This member holds extra information, whose interpretation depends on the section type.
- sh_addralign 段对齐,以2的n次方表示,如果为0或1,表示没有对齐要求。
- sh_entsize Section Entry Size段的长度
sh_type :段的类型。
Name |
Value |
SHT_NULL |
0 |
SHT_PROGBITS |
1 |
SHT_SYMTAB |
2 |
SHT_STRTAB |
3 |
SHT_RELA |
4 |
SHT_HASH |
5 |
SHT_DYNAMIC |
6 |
SHT_NOTE |
7 |
SHT_NOBITS |
8 |
SHT_REL |
9 |
SHT_SHLIB |
10 |
SHT_DYNSYM |
11 |
SHT_LOPROC |
0x70000000 |
SHT_HIPROC |
0x7fffffff |
SHT_LOUSER |
0x80000000 |
SHT_HIUSER |
0xffffffff |
sh_flag:段的标志位,表示该段在进程的虚拟地址空间中的属性,如是否可读、写、执行。
Name |
Value |
notes |
SHF_WRITE |
0x1 |
可读 |
SHF_ALLOC |
0x2 |
需要分配空间 |
SHF_EXECINSTR |
0x4 |
可执行 |
SHF_MASKPROC |
0xf0000000 |
sh_link 和 sh_info: 如果段是与链接相关的,比如重定位表符号表等,sh_link和sh_info这两个成员所包含的意义如下所示。
sh_type |
sh_link |
sh_info |
SHT_DYNAMIC |
该段所使用的字符串表在段表中的下标 |
0 |
SHT_HASH |
该段所使用的符号表在段表中的下标 |
0 |
SHT_REL |
该段所使用的相应符号表在段表中的下标 |
该重定位表所作用的段在段表中的下标 |
SHT_RELA |
该段所使用的相应符号表在段表中的下标 |
该重定位表所作用的段在段表中的下标 |
SHT_SYMTAB |
操作系统相关的 |
操作系统相关的 |
SHT_DYNAMIC |
操作系统相关的 |
操作系统相关的 |
other |
SHN_UNDEF |
0 |
2)重定位表
rel.txt段就是重定位表,类型sh_type为SHT_REL(9)。链接器在处理目标文件时,对目标文件某些部位进行重定位,即代码段和数据段中的那部分绝对地址引用。这些重定位信息记录在ELF文件的重定位表中。
3)字符串表
ELF中有很多字符串,如变量名段名等,但是字符串长度是不定长的,如果用固定的长度来表示比较困难,常见的做法是把字符串集中起来放到一个表中,然后使用字符串在表中的偏移来引用字符串。
4)符号表
在ELF文件中,把函数和变量统称为符号(Sysbol),每个符号有一个相应的值叫做符号值。对函数和变量来说,符号值就是它们的地址。在ELF文件中,用.symtab这个段来记录符号表。
typedef struct{
Elf32_Word st_name;
Elf32_Addr st_value;
Elf32_Word st_size;
unsigned char st_info;
unsigned char st_other;
Elf32_Half st_shndx;
}Elf32_Sym
- st_name 符号名,符号名称在字符串表中的索引
- st_value 符号相应的值,可能是地址或一个绝对值数
- st_size 符号大小
- st_info 符号类型和绑定值
- st_other 默认0
- st_shndx 符号所在的段
st_info 高4位表示符号绑定信息,低4位表示符号类型。
Symbol Binding, ELF32_ST_BIND
Name |
Value |
STB_LOCAL |
0 |
STB_GLOBAL |
1 |
STB_WEAK |
2 |
STB_LOPROC |
13 |
STB_HIPROC |
15 |
Symbol Types, ELF32_ST_TYPE
Name |
Value |
STT_NOTYPE |
0 |
STT_OBJECT |
1 |
STT_FUNC |
2 |
STT_SECTION |
3 |
STT_FILE |
4 |
STT_LOPROC |
13 |
STT_HIPROC |
15 |
5)全局偏移表和跳转表
.plt和.got 动态链接的跳转表和全局入口表。
6)其它
代码段(.text): 代码数据
数据段(.data): 初始化过了的全局变量和局部静态变量
只读数据段(.rodata) 只读数据如const值、字符串常量。
.bss段:未初始化的全局变量和局部变量,是否为全局变量和局部变量预留空间和编译器的实现相关。
自定义段:在变量和函数前加__attribute__((section("name"))) 属性就可以把相应的函数或变量放到以name作为段名的段中。
4、ELF文件加载视图
虽然ELF把可变数据和不可变数据分的很细,用户也可以自己添加段或命名一个段,但加载器把ELF文件加载到内存时,并不按照ELF的结构读取。例如目标文件.o里的代码段.text是section,链接时多个可重定位文件整合成一个可执行的文件,为了提高程序的效率,链接器把目标文件中相同的section 整合成一个segment,方便运行时加载器加载程序。由于虚拟内存的映射和优化的存在,ELF文件在加载到虚拟内存时,也会合并不同的段来达到节约资源的目的。
5、参考文献
1、Linux Referenced Specifications https://refspecs.linuxbase.org/
2、Executable and Linkable Format (ELF) https://elinux.org/Executable_and_Linkable_Format_(ELF)
3、ELF文件格式 https://zhuanlan.zhihu.com/p/286088470
尊重原创技术文章,转载请注明: https://www.cnblogs.com/pingwen/p/17323862.html
ELF文件格式解析的更多相关文章
- Linux课程实践四:ELF文件格式分析
一.ELF文件格式概述 1. ELF文件 ELF:Executable and Linking Format,是一种对象文件的格式,用于定义不同类型的对象文件(Object files)中都放了什么东 ...
- elf 文件格式探秘——程序运行背后的故事
摘要:本文主要讲解elf文件格式,通过readelf命令结合底层的相关数据结构,讲解相关内容,分析程序运行的基本原理. 本文来源:elf 文件格式探秘——程序运行背后的故事 http://blog.c ...
- Android逆向之旅---SO(ELF)文件格式详解(转)
第一.前言 从今天开始我们正式开始Android的逆向之旅,关于逆向的相关知识,想必大家都不陌生了,逆向领域是一个充满挑战和神秘的领域.作为一名Android开发者,每个人都想去探索这个领域,因为一旦 ...
- ELF文件格式与进程地址空间的联系
http://blog.csdn.net/q_l_s/article/details/52597330 三.分析在fork产生新进程中ELF文件格式与进程地址空间的联系 1.进程的虚拟地址空间 每个程 ...
- Android逆向之旅---SO(ELF)文件格式详解
第一.前言 从今天开始我们正式开始Android的逆向之旅,关于逆向的相关知识,想必大家都不陌生了,逆向领域是一个充满挑战和神秘的领域.作为一名Android开发者,每个人都想去探索这个领域,因为一旦 ...
- Android ELF文件解析
0X01 ELF初认识 elf文件是linux下的二进制文件,相当于windows下的PE文件,Android系统里的dll. 解析elf文件两个用处:1.so加固:2.frida(xposed)检 ...
- ELF文件格式学习总结
ELF文件格式学习总结 ELF文件格式学习总结1. 概述2. 目标文件结构3. ELF文件头3.1 魔数3.2 文件类型3.3 机器类型4. ELF文件内容4.1段表4.2字符串表(.**strtab ...
- 实践2.4 ELF文件格式分析
实践2.4 ELF文件格式分析 1.ELF文件头 查看/usr/include/elf.h文件: #define EI_NIDENT (16) typedef struct { unsigned ch ...
- ArcGIS三大文件格式解析
原文:ArcGIS三大文件格式解析 Shape数据 Shapefile是ArcView GIS 3.x的原生数据格式,属于简单要素类,用点.线.多边形存储要素的形状,却不能存储拓扑关系,具有简单.快速 ...
- ELF文件格式
ELF--Linux下可执行文件格式 1.类型 常见的ELF格式文件包括: ...
随机推荐
- 第一章 对程序员来说CPU是什么
章节标题下方有几个问题,看完后便对第一章的内容有了大概的了解. 第一章观后感想: 第一章解释了CPU是什么,CPU相当于计算机的大脑,它的内部由数百万至数亿个晶体管构成. CPU所负责的就是解释和运行 ...
- HTML基础知识学习
一.HTML概述 1.系统结构: ①.B/S架构 Browser Server(浏览器/服务器的交互形式.) Browser支持哪些语言:HTML CSS Javascript S是服务器端Serve ...
- 10.10 2020 实验 6:OpenDaylight 实验——OpenDaylight 及 Postman 实现流表下发
一.实验目的 熟悉 Postman 的使用:熟悉如何使用 OpenDaylight 通过 Postman 下发流表. 二.实验任务 推荐阅读:SDNLAB 文章:OpenFlow 协议超时机制简介 ...
- Openssl自签证书|Nginx配置全站HTTPS,包括WSS(websocket)
一.生成自签证书 如果有购买证书的,可忽略此步骤. 生成方法一: openssl genrsa -des3 -out ca.key 1024 openssl rsa -in ca.key -out c ...
- Httpt请求
在c#中常见发送http请求的方式如下 HttpWebRequest: .net 平台原生提供,这是.NET创建者最初开发用于使用HTTP请求的标准类.使用HttpWebRequest可以让开发者控制 ...
- nvm的下载安装
nvm下载地址:https://github.com/coreybutler/nvm-windows/releases 下载包,双击安装,选取路径, 注意:如果按默认的,安装在c盘的话,那之后的切换版 ...
- GitHub远程仓库与本地仓库链接问题
git clone ...时,Failed to connect to 127.0.0.1 port 1080: Connection refused 步骤1------git查看: 查询动态代理 g ...
- 【Beat】Scrum Meeting 4
时间:2021年6月29日 1.各个成员今日完成的任务以及贡献小时数 姓名 今日完成任务 贡献小时数 鑫 继续进行bug的修改 4 荣娟 继续进行bug的修改 4 亚楠 继续进行bug的修改 4 桂婷 ...
- group by和union,Laravel分页
$res3 = DB::table('users') ->join('user_folow_boutiques', 'user_folow_boutiques.user_id', '=', 'u ...
- ElementPlus 表单 resetFields 无效问题解决方法
最近在写一个项目,一个表单递交或者使用resetFields关闭后,再打开,原来的值还存在,后查了一下网上的方法,确定是el-form-item,必须要加prop,其值要与model相同,此问题得到完 ...