ELF文件格式分析(一)

news/2025/3/15 22:45:35/

目录

  • 一、ELF 格式介绍
  • 二、ELF组成部分
    • 2.1) ELF Header
    • 2.2) Program Headers
    • 2.3)Section Headers Table
    • 2.3.2) Section

此篇文章介绍了ELF文件由哪些部分组成,他们的功能是什么,并在文章末尾给出了一份ELF文件解析的参考资料。

一、ELF 格式介绍

ELF(Executable and Linkable Format)即可执行的和可链接的格式。
出于方便性和效率考虑,ELF文件提供了两种并行视图,即链接视图,执行视图。
img

二、ELF组成部分

下面我们使用 readelf 来读取ls的文件信息

2.1) ELF Header

以Magic Str开头,描述文件类型,abi, version等信息,并提供到Program Header Table*和 Section Header Table的索引。

[root@localhost tgt]# readelf -h  /bin/ls
ELF 头:Magic:  7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00类别:                              ELF64数据:                              2 补码,小端序 (little endian)Version:                           1 (current)OS/ABI:                            UNIX - System VABI 版本:                          0类型:                              DYN (共享目标文件)系统架构:                          AArch64版本:                              0x1入口点地址:              0x5914程序头起点:              64 (bytes into file)Start of section headers:          197648 (bytes into file)标志:             0x0Size of this header:               64 (bytes)Size of program headers:           56 (bytes)Number of program headers:         9Size of section headers:           64 (bytes)Number of section headers:         28Section header string table index: 27

2.2) Program Headers

存在于可执行文件或共享库中,是一个结构体组成的数组。一般在ELF Header之后。每个数组元素描述一个段(segment)或者其他程序执行时需要的信息;该结构用于执行阶段。

[root@localhost tgt]# readelf -l  /bin/lsElf 文件类型为 DYN (共享目标文件)
Entry point 0x5914
There are 9 program headers, starting at offset 64程序头:Type           Offset             VirtAddr           PhysAddrFileSiz            MemSiz              Flags  AlignPHDR           0x0000000000000040 0x0000000000000040 0x00000000000000400x00000000000001f8 0x00000000000001f8  R      0x8INTERP         0x0000000000000238 0x0000000000000238 0x00000000000002380x000000000000001b 0x000000000000001b  R      0x1[Requesting program interpreter: /lib/ld-linux-aarch64.so.1]LOAD           0x0000000000000000 0x0000000000000000 0x00000000000000000x0000000000020780 0x0000000000020780  R E    0x10000LOAD           0x000000000002ef30 0x000000000003ef30 0x000000000003ef300x0000000000001380 0x0000000000002648  RW     0x10000DYNAMIC        0x000000000002f948 0x000000000003f948 0x000000000003f9480x0000000000000220 0x0000000000000220  RW     0x8NOTE           0x0000000000000254 0x0000000000000254 0x00000000000002540x0000000000000044 0x0000000000000044  R      0x4GNU_EH_FRAME   0x000000000001c914 0x000000000001c914 0x000000000001c9140x000000000000093c 0x000000000000093c  R      0x4GNU_STACK      0x0000000000000000 0x0000000000000000 0x00000000000000000x0000000000000000 0x0000000000000000  RW     0x10GNU_RELRO      0x000000000002ef30 0x000000000003ef30 0x000000000003ef300x00000000000010d0 0x00000000000010d0  R      0x1Section to Segment mapping:段节...0001     .interp02     .interp .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame03     .init_array .fini_array .data.rel.ro .dynamic .got .data .bss04     .dynamic05     .note.gnu.build-id .note.ABI-tag06     .eh_frame_hdr0708     .init_array .fini_array .data.rel.ro .dynamic .got

2.3)Section Headers Table

索引每个section的位置,该结构用于链接阶段。

[root@localhost tgt]# readelf -S  /bin/ls
There are 28 section headers, starting at offset 0x30410:节头:[] 名称              类型             地址              偏移量大小              全体大小          旗标   链接   信息   对齐[ 0]                   NULL             0000000000000000  000000000000000000000000  0000000000000000           0     0     0[ 1] .interp           PROGBITS         0000000000000238  00000238000000000000001b  0000000000000000   A       0     0     1[ 2] .note.gnu.build-i NOTE             0000000000000254  000002540000000000000024  0000000000000000   A       0     0     4[ 3] .note.ABI-tag     NOTE             0000000000000278  000002780000000000000020  0000000000000000   A       0     0     4[ 4] .gnu.hash         GNU_HASH         0000000000000298  000002980000000000000040  0000000000000000   A       5     0     8[ 5] .dynsym           DYNSYM           00000000000002d8  000002d80000000000000c90  0000000000000018   A       6     3     8[ 6] .dynstr           STRTAB           0000000000000f68  00000f6800000000000005e4  0000000000000000   A       0     0     1[ 7] .gnu.version      VERSYM           000000000000154c  0000154c000000000000010c  0000000000000002   A       5     0     2[ 8] .gnu.version_r    VERNEED          0000000000001658  000016580000000000000070  0000000000000000   A       6     3     8[ 9] .rela.dyn         RELA             00000000000016c8  000016c800000000000016f8  0000000000000018   A       5     0     8[10] .rela.plt         RELA             0000000000002dc0  00002dc00000000000000a98  0000000000000018  AI       5    22     8[11] .init             PROGBITS         0000000000003858  000038580000000000000014  0000000000000000  AX       0     0     4[12] .plt              PROGBITS         0000000000003870  000038700000000000000730  0000000000000010  AX       0     0     16[13] .text             PROGBITS         0000000000003fa0  00003fa00000000000013fa8  0000000000000000  AX       0     0     8[14] .fini             PROGBITS         0000000000017f48  00017f480000000000000010  0000000000000000  AX       0     0     4[15] .rodata           PROGBITS         0000000000017f60  00017f6000000000000049b4  0000000000000000   A       0     0     16[16] .eh_frame_hdr     PROGBITS         000000000001c914  0001c914000000000000093c  0000000000000000   A       0     0     4[17] .eh_frame         PROGBITS         000000000001d250  0001d2500000000000003530  0000000000000000   A       0     0     8[18] .init_array       INIT_ARRAY       000000000003ef30  0002ef300000000000000008  0000000000000008  WA       0     0     8[19] .fini_array       FINI_ARRAY       000000000003ef38  0002ef380000000000000008  0000000000000008  WA       0     0     8[20] .data.rel.ro      PROGBITS         000000000003ef40  0002ef400000000000000a08  0000000000000000  WA       0     0     8[21] .dynamic          DYNAMIC          000000000003f948  0002f9480000000000000220  0000000000000010  WA       6     0     8[22] .got              PROGBITS         000000000003fb68  0002fb680000000000000498  0000000000000008  WA       0     0     8[23] .data             PROGBITS         0000000000040000  0003000000000000000002b0  0000000000000000  WA       0     0     8[24] .bss              NOBITS           00000000000402b0  000302b000000000000012c8  0000000000000000  WA       0     0     8[25] .gnu.build.attrib NOTE             0000000000041578  000302b00000000000000024  0000000000000000           0     0     4[26] .gnu_debuglink    PROGBITS         0000000000000000  000302d40000000000000028  0000000000000000           0     0     4[27] .shstrtab         STRTAB           0000000000000000  000302fc0000000000000113  0000000000000000           0     0     1
Key to Flags:W (write), A (alloc), X (execute), M (merge), S (strings), I (info),L (link order), O (extra OS processing required), G (group), T (TLS),C (compressed), x (unknown), o (OS specific), E (exclude),p (processor specific)

2.3.2) Section

节区名介绍
[.text].text 节是保存了程序代码指令的代码节。一段可执行程序,如果存在Phdr,.text 节就会存在于text 段中。由于.text 节保存了程序代码,因此节的类型为SHT_PROGBITS。
[.dynsym]保存了引用来自外部文件符号的全局符号,如printf 这样的库函数。.dynsym 是被标记了ALLOC 的,在运行时分配并装载进入内存,因此动态链接可执行文件的执行来说是必需的。该节保存在text 段中,节类型被标记为SHT_DYNSYM。
[.rodata].rodata 节保存了只读的数据,如一行C 语言代码中的字符串。下面这条命令就是存放在.rodata 节中的:
printf(“Hello World!\n”);因为.rodata 节是只读的,所以只能存在于一个可执行文件的只读段中。因此,只能在text 段(不是data 段)中找到.rodata 节。由于.rodata 节是只读的,因此节类型为SHT_PROGBITS。
[.plt]程序链接表(Procedure Linkage Table,PLT)包含了动态链接器调用从共享库导入的函数所必需的相关代码。由于其存在于text 段中,同样保存了代码,因此节类型为SHT_PROGBITS。
[.data]不要将.data 节和data 段混淆了,.data 节存在于data 段中,保存了初始化的全局变量等数据。由于其保存了程序的变量数据,因此类型被标记为SHT_PROGBITS。
[.bss].bss 节保存了未进行初始化的全局数据,是data 段的一部分,占用空间不超过4 字节,仅表示这个节本身的空间。程序加载时数据被初始化为0,在程序执行期间可以进行赋值。由于.bss 节未保存实际的数据,因此节类型为SHT_NOBITS。
[.got.plt].got 节保存了全局偏移表。.got 节和.plt 节一起提供了对导入的共享库函数的访问入口,由动态链接器在运行时进行修改。如果攻击者获得了堆或者.bss 漏洞的一个指针大小的写原语,就可以对该节任意进行修改。.got.plt 节跟程序执行有关,因此节类型被标记为SHT_PROGBITS。
[.symtab].symtab 中保存了可执行文件的本地符号,如全局变量,或者代码中定义的本地函数等。只是用来进行调试和链接的,有时候为了节省空间,会将.symtab 符号表从生产二进制文件中删掉

参考资料:

  1. ELF文件格式分析-北京大学操作系统实验室.pdf
  2. ELF文件 及 nm & readelf & objdump 使用与对比

http://www.ppmy.cn/news/1045766.html

相关文章

2023年Java核心技术面试第五篇(篇篇万字精讲)

目录 十 . HashMap,ConcurrentHashMap源码解析 10.1 HashMap 的源码解析: 10.1.1数据结构: 10.1.2哈希算法: 10.1.3解决哈希冲突: 10.1.4扩容机制: 10.1.5如何使用 HashMap: 10.2 HashMap 关注…

如何在React项目中动态插入HTML内容

React是一种流行的JavaScript库,用于构建用户界面。它提供了一种声明式的方法来创建可复用的组件,使得开发者能够更轻松地构建交互性的Web应用程序。在React中,我们通常使用JSX语法来描述组件的结构和行为。 在某些情况下,我们可…

使用IText导出复杂pdf

1、问题描述 需要将发票导出成pdf&#xff0c;要求每页都必须包含发票信息和表头行。 2、解决方法 使用IText工具实现PDF导出 IText8文档&#xff1a;Examples (itextpdf.com) 3、我的代码 引入Itext依赖&#xff0c;我这里用的是8.0.1版本 <dependency><groupId>…

【李沐】3.2线性回归从0开始实现

%matplotlib inline import random import torch from d2l import torch as d2l1、生成数据集&#xff1a; 看最后的效果&#xff0c;用正态分布弄了一些噪音 上面这个具体实现可以看书&#xff0c;又想了想还是上代码把&#xff1a; 按照上面生成噪声&#xff0c;其中最后那…

数字化车间mes生产执行管理系统

数字化车间mes是一款基于B/S结构的生产执行管理系统&#xff0c;主要目的是为中小企业提供了高效率、低成本、通用性强的一个MES系统解决方案&#xff0c;能够实时监控当前完成进度。 功能简介&#xff1a; 生产管理 大屏展示&#xff1a;可以从大屏展示页面看到任工序…

(202308)科研论文配图 task1 书籍第一章阅读

《科研论文配图绘制指南——基于python》阅读笔记 第一章阅读笔记 《科研论文配图绘制指南——基于python》阅读笔记序言阅读笔记1.1 绘制基础绘制原则 1.2 配色基础1.2.1 色彩格式1.2.2 色轮配色原理1.2.3 颜色主题1.2.4 配色工具 序言 有幸在这次的组队学习活动中&#xff0…

react之react-redux的介绍、基本使用、获取状态、分发动作、数据流、reducer的分离与合并等

react之react-redux的介绍、基本使用、获取状态、分发动作、数据流、reducer的分离与合并等 一、react-redux介绍二、React-Redux-基本使用三、获取状态useSelector四、分发动作useDispatch五、 Redux 数据流六、代码结构七、ActionType的使用八、Reducer的分离与合并九、购物挣…

ui设计需要学编程吗难不难学习 优漫动游

ui设计需要学编程吗难不难学习&#xff0c;对于基础小白来说学习编程确实有一定难度&#xff0c;所以很想知道零基础学习ui设计需要学编程吗&#xff0c;需不需要写代码呢&#xff0c;这些问题小编来简单的分析分析解决零基础小白的一些困惑&#xff0c;希望对你有帮助。 ui…