CTF权威指南 笔记 -第二章二进制文件- 2.2 -ELF文件格式

news2024/11/25 4:18:44

目录

ELF的文件类型

ELF文件的结构

 ELF文件头

 节头表

代码节

数据节和只读数据节

 bss节

字符串表

 符号表

重定位

可执行文件的装载

常见的段


ELF就是可执行可连接格式 为linux运行文件格式

ELF的文件类型

我们使用复杂的例子进行演示

#include<stdio.h>

int global_init_var = 10;
int global_uninit_var;
定义全局变量

void func(int sum){
    printf("%d\n",sum);
}
定义func函数

void main(void){
    static int local_static_init_var=20;
    static int local_static_uninit_var;
局部变量
只能在main函数中访问
    int local_init_val=30;
    int local_uninit_var;

    func(global_init_var + local_init_val + local_static_init_var);
打印这个的值    10+20+30
}

发现确实是60 

gcc elfDemo.c -o elfDemo.exce

这里把他编译成windows 的pe文件 exe文件类型

gcc -static elfDemo.c -o elfDEmo_static.exec

这里也是windows的但是是静态链接的


gcc -c elfDemo.c -o elfDemo.rel

这里编译成 rel文件  为 可重定位文件 这里就是之前的汇编阶段


gcc -c -fPIC elfDemo.c -o elfDemo_pic.rel && gcc -shared elfDemo_pic.rel -o elfdemo.dyn

这里把文件编译 为pic类型 位置独立代码 就是 代码可以是在不固定的虚拟内存区域 我们无法预测

同时前面成功的话编译一个 共享库的这个文件 名为 .dyn


&&是前面成功 才执行后面的
 这样可以实现代码函数的共享和重用

 这里可以发现 ELF文件 分为3类

可执行文件 exec :经过链接 可执行的目标文件  叫做程序

可重定位文件 : 预编译文件编译但没有实现链接的文件 .o结尾 通常是PIC类型 

共享目标文件 :动态链接库文件 用于在链接过程中和其他共享库进行链接 构建目标文件
或者在可执行文件运行的时候 链接到进程中 成为运行代码 的一部分

ELF文件的结构

在看目标文件的两个视角

链接视角 通过节进行划分

运行视角 通过段进行划分 

节和段 

节是一种逻辑的划分 一个程序中 具有很多节 可以是代码 调试信息等
段是一种物理的划分 一个段中 具有一组节 段又可以分为代码段 数据段等

这里section header tables 为节头表 用来保存节的信息 内容等

而我们例子的链接视角为

 ELF文件头

文件头是在目标文件最开始的位置 包含着基本信息

ELF文件类型 版本 目标机器 程序入口 段表和节表的位置和长度等

ELF的魔术字符 和jpg的文件头字符一样 遇到就说明是这个类型

7f 45 4c 46   \177ELF

我们可以使用readelf来查看文件头

readelf -h elfDemo.rel

 

 节头表

一个文件包含很多个节 这些节的信息存放在节头表中 这个表的每一个项都是 Elf64_Shdr结构体

记录着 节的名字 长度 偏移 读写权限等信息  

节头表的位置记录在e_shoff域中

但是节头表在程序中并不是必须的

所以一些会除去节头表来增加反编译的难度

我们通过readelf查看

readelf -S elfDemo.rel

我们进行深入查看节头表的.text , .data, .bss节

代码节

objdump -x -s -d elfDemo.rel


-x 列出完整的头部信息

-s 显示每一个节的大小

-d  把符号的地址和名字列出来

 我们只看text

 

 先看这个 这个内容为

Contents of section .text:

是text数据的十六进制形式 总共有 0x4e个字节 4个算一个字节

最左边为偏移量 中间为内容 最右边为ASCII表示

 这里是反汇编的结果

数据节和只读数据节

data节保存着初始化的全局变量和局部静态变量

global_init_var  (0a000000)
全局变量

local_static_init_var  (14000000)
局部静态变量

每一个变量4个字节 一共8个字节

.rodata为只读数据 包括只读变量和字符串常量

源代码中调用printf函数 用到了字符串常量 "%d\n" 这是一种只读数据

所以保存在rodata中

 bss节

 这个节用于保存 未初始化的全局变量和局部静态变量 这个节在文件中其实不存在

只是变量预留的空间

 所以下面没有contents属性

 这里继续给出其他常见的节

字符串表

包括了以 null结尾的字符序列 用来表示符号名和节名

所以引用字符串只需要给出在字符序列中的偏移量即可

字符串表达第一个字符和最后一个字符 都是 null

readelf -x .strtab elfDemo.rel


readelf -x .shstrtab elfDemo.rel

 能发现第一个和最后一个都是 00000000 null

 符号表

是记录了 目标文件中 所需要用到的所有符号信息 分为 .dynsym .dyntab

前者是后者的子集
 .dynsym 保存了引用外部文件的符合 只能在运行的时候被解析
.dyntab 不仅保存了外部 还保存了本地符合 用于调试和链接

索引值都是从 0 开始计数 但是0不具有实际意义

每一个符号都要符号值

readelf -s elfDemo.rel

这里能看见 printf 为 und 说明是外部 需要程序运行才能知道地址

重定位

重定位是连接符号定义和符号引用的过程  

可重定位文件在构建可执行文件和共享目标文件的过程中 需要把节中符号引用转换为这些符号在进程空间的虚拟地址

包含这些转换信息的数据 就是重定位项

readelf -r elfDemo.rel

可执行文件的装载

这里是从运行视角进行审视

运行一个可执行文件

 将该文件和动态链接库 装载到进程空间中 形成进程镜像
每一个进程都有自己的独立虚拟地址空间  这个空间如何布局是段头表中的程序头决定
readelf -l elfDemo.exce
root@lxz-virtual-machine:~/下载# readelf -l elfDemo.exce

Elf 文件类型为 DYN (Position-Independent Executable file)
Entry point 0x1060
There are 13 program headers, starting at offset 64

程序头:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                 0x00000000000002d8 0x00000000000002d8  R      0x8
  INTERP         0x0000000000000318 0x0000000000000318 0x0000000000000318
                 0x000000000000001c 0x000000000000001c  R      0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000628 0x0000000000000628  R      0x1000
  LOAD           0x0000000000001000 0x0000000000001000 0x0000000000001000
                 0x00000000000001b1 0x00000000000001b1  R E    0x1000
  LOAD           0x0000000000002000 0x0000000000002000 0x0000000000002000
                 0x0000000000000114 0x0000000000000114  R      0x1000
  LOAD           0x0000000000002db8 0x0000000000003db8 0x0000000000003db8
                 0x0000000000000260 0x0000000000000270  RW     0x1000
  DYNAMIC        0x0000000000002dc8 0x0000000000003dc8 0x0000000000003dc8
                 0x00000000000001f0 0x00000000000001f0  RW     0x8
  NOTE           0x0000000000000338 0x0000000000000338 0x0000000000000338
                 0x0000000000000030 0x0000000000000030  R      0x8
  NOTE           0x0000000000000368 0x0000000000000368 0x0000000000000368
                 0x0000000000000044 0x0000000000000044  R      0x4
  GNU_PROPERTY   0x0000000000000338 0x0000000000000338 0x0000000000000338
                 0x0000000000000030 0x0000000000000030  R      0x8
  GNU_EH_FRAME   0x0000000000002008 0x0000000000002008 0x0000000000002008
                 0x000000000000003c 0x000000000000003c  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x0000000000002db8 0x0000000000003db8 0x0000000000003db8
                 0x0000000000000248 0x0000000000000248  R      0x1

 Section to Segment mapping:
  段节...
   00     
   01     .interp 
   02     .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt 
   03     .init .plt .plt.got .plt.sec .text .fini 
   04     .rodata .eh_frame_hdr .eh_frame 
   05     .init_array .fini_array .dynamic .got .data .bss 
   06     .dynamic 
   07     .note.gnu.property 
   08     .note.gnu.build-id .note.ABI-tag 
   09     .note.gnu.property 
   10     .eh_frame_hdr 
   11     
   12     .init_array .fini_array .dynamic .got 

 这里我们可以从段节发现 一个段中出现了很多的节

段的出现就是对这些节进行分类

实际上 系统并不关心这些节的内容 而是关心这些的读写执行权限

那么就将不同权限的节分组 这样就可以同时装载多个节

.data .bss 具有读写权限

.text .plt.got 具有读和执行权限

常见的段

可执行文件至少有一个 PT_LOAD类型的段 用于描述可装载的节
而动态链接的可执行文件包含两个  .data 和 .plt 分开存放
动态段 PT_DYNAMIC包含动态链接器所必须的信息 
例如 动态共享库 GOT表 和 重定位表等
PT_NOTE 类型的段 保存了系统相关的附加信息 
但是程序运行不需要这个内容
PT_INTERP段 将位置和大小信息存放在一个字符串中 
是对程序解释器的位置描述
PT_PHDR段保存了 程序头本身的位置和大小

在进程中 使用段是不够的  还需要使用到栈堆vDSO等空间

动态链接的可执行文件装载后  还需要进行动态链接才可以顺利执行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/478464.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

成功解决长时间挂起虚拟机后再次打开无法连接网络,并提示网络激活失败(亲测有效)

成功解决长时间挂起虚拟机后再次打开无法连接网络&#xff0c;并提示网络激活失败&#xff08;亲测有效&#xff01;&#xff09; 之前做区块链的一个虚拟机很久没打开&#xff0c;一直处于挂起状态&#xff0c;一直提示网络连接激活失败。试了很多种方法没解决&#xff0c;更…

人力资源管理系统有哪些推荐?

人力资源管理系统是现代企业管理中必不可少的工具&#xff0c;它可以帮助企业高效地管理人员的入职、离职、考勤、绩效、薪酬等方面的信息。 然而&#xff0c;市场上的HRM系统琳琅满目&#xff0c;选择一款合适的系统并不容易。 今天就来给大家介绍六款好用的人力资源管理系统…

自动化运维工具---Ansible Playbook语法实战(一)

目录 一、Ansible Playbook剧本初识 1.1 Ansible Playbook 基本概述 1.1.1 什么是playbook 1.1.2 Ansible playbook 与AD-Hoc的关系 1.2 Ansible Playbook 书写格式 1.2.1安装NFS 服务 1.3 Playbook变量详解 1.3.1 使用 vars定义变量 1.3.2 使用 vars_flies定义变量 …

中国平安将在2023年出现转机,复苏才刚刚开始

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 在解封后股价出现短暂反弹之后&#xff0c;由于市场担忧中国平安&#xff08;02318&#xff09;人寿保险部门新业务NBV&#xff08;用于衡量寿险公司新业务价值的一个重要指标,当一家保险公司的NBV指标越高,那么说明每新增…

码出高效:Java开发手册笔记(线程安全)

并发与并行的目标都是尽可能快地执行完所有任务。以医生坐诊为例&#xff0c;某个科室有两个专家同时出诊&#xff0c;这就是两个并行任务&#xff0c;其中一个医生&#xff0c;时而问诊&#xff0c;时而查看化验单&#xff0c;然后继续问诊&#xff0c;突然又中断去处理病人的…

总线、I/O总线、I/O接口

总线是计算机内数据传输的公共路径&#xff0c;用于实现两个或以上部件之间的信息交换。计算机系统中有多种总线&#xff0c;它们在各个层次上提供部件之间的连接和信息交换通路。 核内总线&#xff1a;在处理器核内部各元件之间连线的总线称为核内总线&#xff0c;可连接核内…

Java-数据结构-并查集<二>

一.并查集的简单介绍 二. 并查集的主要构成和实现方式 三.HashMap模板和数组模板 由于在下文的模板基本一致&#xff0c;不再每次都罗列&#xff0c;大体的模板如下&#xff0c;若有错误可以在leetcode找到对应的题目解答&#xff0c;已经附上连接。 HashMap class UnionFi…

本周大新闻|苹果首款MR没有主打卖点;Meta认为AI是AR OS的基础

​本周XR大新闻&#xff0c;AR方面&#xff0c;苹果首款MR或没有主打卖点&#xff0c;反而尽可能支持更多App和服务&#xff1b;扎克伯格表示基于AI的AR眼镜操作系统是下一代计算平台的基础&#xff1b;微软芯片工程VP Jean Boufarhat加入Meta芯片团队&#xff1b;Humane展示了…

[计算机图形学]高级光线传播与复杂外观建模(前瞻预习/复习回顾)

本篇不涉及技术细节* 一、高级光线传播* 1.有偏和无偏估计 无偏估计&#xff0c;比如我们在之前做路径追踪的时候&#xff0c;我们用许多样本去近似定积分的值&#xff0c;无论我们取的样本数量是多少&#xff0c;它的期望永远是对的&#xff0c;也就是我们真实的定积分的值&…

Python入门(一)Python概述与环境搭建

Python概述与环境搭建 1.概述1.1版本及下载1.2 Python 特点 2.环境搭建3.第一个程序“hello&#xff0c;world”4.可能会存在的问题 1.概述 Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性&#xff0c;相比其他语言…

【WAF】雷池waf升级体验

文章目录 前言一、更新二、功能体验1.仪表板2.自定义规则&#xff1a;3. 通用配置&#xff1a; 更新总结新增优化&#xff1a; 前言 最近雷池有比较大的更新&#xff0c;安装可以参考以前文章雷池waf安装&#xff0c;更新了数据统计也就是仪表板和自定义规则和通用配置还有IP高…

AI行为分析预警系统 opencv

AI行为分析预警系统通过pythonopencv网络模型Ai视觉智能分析技术&#xff0c;AI行为分析预警系统可以对实际场景下如车间、电力场景、化工场景、工业生产场景下的人员作业操作行为规范进行有针对性的定制开发&#xff0c;根据每个项目的不同的识别预警需求。OpenCV可以在不同的…

BEV(0)---Transformer

1 Transformer Transformer是一个Sequence to Sequence model&#xff0c;特别之处在于它大量用到了self-attention&#xff0c;替代了RNN&#xff0c;既考虑了Sequence的全局信息也解决了并行计算的问题。 1.1 self-attention&#xff1a; ①. 输入x1 ~ x4为一个sequence&…

Mysql-SQL优化

SQL优化 插入数据优化1&#xff09;批量插入数据2&#xff09;手动控制事务3&#xff09;主键顺序插入大批量插入数据 主键优化order by优化group by优化limit优化count优化update优化小结 插入数据优化 插入数据优化主要是对于insert进行批量插入时优化&#xff0c;下面我们就…

验证二叉搜索树-递归双指针法

1题目 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 示例 1&#xff1a…

初识springboot【手把手教你搭建springboot项目】+springboot日志详解【超详细】

目录 一.springboot的概念 1.什么是springboot&#xff1f; 二.使用springboot进行开发的优势 springboot的设计原则是什么&#xff0c;使用springboot进行开发具有怎样的优势&#xff1f;&#xff08;M&#xff09; 三.手把手搭建一个springboot项目 ①创建项目并选择依赖…

枚举二进制数的子集

思想&#xff1a; 如1011的二进制子集有1011&#xff0c;1010&#xff0c;1001&#xff0c;1000&#xff0c;0011&#xff0c;0010&#xff0c;0001&#xff0c;0000 思想是每次对当前最小子元素-1与目标x取与运算。枚举到0为止。 成立原因&#xff1a;因为我们是由大到小&a…

Python使用AI photo2cartoon制作属于你的漫画头像

Python使用AI photo2cartoon制作属于你的漫画头像 1. 效果图2. 原理3. 源码参考 git clone https://github.com/minivision-ai/photo2cartoon.git cd ./photo2cartoon python test.py --photo_path images/photo_test.jpg --save_path images/cartoon_result.png1. 效果图 官方…

计算机组成原理 存储器(下)

Cache和主存之间的映射: Cache的基本结构 Cache存储体以块为单位和主存交换信息&#xff0c;地址变换机制是由CPU送往主存的数据转换为Cacche的地址&#xff0c;主存和Cache的大小相同所以 &#xff0c;如果能够建立对应关系&#xff0c;则代表命中。 Cache的读写操作 写操作…

链表:常见面试题-根据大小划分区域

将单向链表按某值划分为左边小、中间相等、右边大的形式 1&#xff09;将链表放入数组里&#xff0c;在数组上做partition&#xff08;类似快排&#xff09;&#xff0c;这是笔试时推荐的写法 2&#xff09;分为小、中、大三部分&#xff0c;再把各个部分之间串起来&#xff…