是否存在与 PE 基址重定位等效的 ELF?

2023-12-05

我一直在研究一些 ELF 二进制文件的反汇编,我注意到了这一点:

   0000000000401020 <_start>:
      401020:   31 ed                   xor    ebp,ebp
      401022:   49 89 d1                mov    r9,rdx
      401025:   5e                      pop    rsi
      401026:   48 89 e2                mov    rdx,rsp
      401029:   48 83 e4 f0             and    rsp,0xfffffffffffffff0
      40102d:   50                      push   rax
      40102e:   54                      push   rsp
      40102f:   49 c7 c0 30 13 40 00    mov    r8,0x401330
      401036:   48 c7 c1 d0 12 40 00    mov    rcx,0x4012d0
      40103d:   48 c7 c7 72 12 40 00    mov    rdi,0x401272
      401044:   ff 15 a6 2f 00 00       call   QWORD PTR [rip+0x2fa6]        # 403ff0 <__libc_start_main@GLIBC_2.2.5>
      40104a:   f4                      hlt    
      40104b:   0f 1f 44 00 00          nop    DWORD PTR [rax+rax*1+0x0]

When __libc_start_main被调用时,我们通过寄存器将这三个立即值作为参数传递。这些显然是被调用的函数指针__libc_start_main(包括main)。但这些是虚拟地址,我的理解是,二进制文件加载到内存并运行时的实际映射地址不一定相同。因此,这些函数指针可能无法反映它们在内存中的实际位置。

更熟悉PE文件,IMAGE_DIRECTORY_BASERELOC部分为我们提供了IMAGE_BASE_RELOCATION帮助我们调整这些常量值以反映新图像基础的结构。但我没有看到 ELF 文件的任何等效项。我在这里错过了什么吗?当加载 ELF 文件时这些地址是如何固定的?


我的理解是,二进制文件加载到内存并运行时的实际映射地址不一定相同。

不,从这些地址我们可以看到这是一个链接在的非 PIE ELF 可执行文件ld的默认基地址。这是一个位置相关可执行的。

可执行文件本身将始终加载到固定的虚拟地址,因此可以使用 32 位立即数而不是 RIP 相关 LEA 将静态地址放入寄存器中。可执行文件本身的 ASLR 是不允许/不可能的。

libc 是一个 ELF“共享对象”,可以是 ALSRed,因此调用__libc_start_main通过 GOT 中的指针。在这个 CRT 启动代码的 gcc 源代码中,这可能看起来像call *__libc_start_main@GOTPCREL(%rip)(AT&T 语法)。

顺便说一句,我们可以看出这是手写的 asm,因为错过了使用 7 字节的优化mov rdi, sign_extended_imm32(与 RIP 相关 LEA 大小相同)而不是 5 字节mov edi, imm32。 x86-64 System V ABI 中的默认非 PIE 代码模型将所有静态代码/数据放在虚拟地址空间的低 2GiB 中,因此静态地址可以通过零或符号扩展至 64 位来使用。


ELF“可执行文件”can被加载到随机基地址的称为 PIE(位置无关可执行文件)。就 ELF 细节而言,它们使用与共享库相同的 ELF“类型”,因此它们实际上是具有“入口点”并被标记为可执行文件的 ELF 共享对象。

现代 Linux 发行版有 gcc 默认构建 PIE。看x86-64 Linux 中不再允许使用 32 位绝对地址?(可重定位 ELF 共享对象可以重定位在地址空间中的任何位置,不限于低 2GiB,因此没有用于 32 位绝对地址的运行时修复的重定位类型。)

64 位绝对地址有重定位类型,因此(函数/代码指针的)跳转表仍然是可能的,10 字节也是如此mov rdi, imm64,但是即使 ELF 程序加载器或动态链接器不需要修改这些重定位的程序文本,其效率也比 RIP 相关的 LEA 低。

e.g. readelf -a /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 (Shared object file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x5ae0
...

请注意类型字段:DYN,与实际库中的相同,例如readelf -a /lib/libc.so.6。入口点是一个相对地址,相对于它映射的基地址。

非 PIE 可执行文件(例如静态链接,或使用-fno-pie -no-pie)看起来像这样:

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:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x401000

请注意Type: EXEC和绝对入口点(在链接时选择ld).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否存在与 PE 基址重定位等效的 ELF? 的相关文章

  • 为什么不能执行 mov [eax], [ebx] [重复]

    这个问题在这里已经有答案了 我可以做这个 mov eax ebx 和这个 mov eax ebx 甚至这个 mov eax ebx 但不是这个 错误C2415 mov eax ebx 只是wtf 为什么 它与 ptr1 ptr2 相同 为什
  • 如何在汇编语言中换行打印多个字符串

    我试图在汇编中的不同行上打印多个字符串 但使用我的代码 它只打印最后一个字符串 我对汇编语言非常陌生 所以请耐心等待 section text global start start mov edx len mov edx len1 mov
  • 奇怪的 MSC 8.0 错误:“ESP 的值未在函数调用中正确保存...”

    我们最近尝试将一些 Visual Studio 项目分解为库 并且在测试项目中一切似乎都编译和构建得很好 其中一个库项目作为依赖项 然而 尝试运行该应用程序给我们带来了以下令人讨厌的运行时错误消息 运行时检查失败 0 ESP 的值未在函数调
  • 近调用/跳转表并不总是在引导加载程序中工作

    一般问题 我一直在开发一个简单的引导加载程序 并在某些环境中偶然发现了一个问题 在这些环境中 此类指令不起作用 mov si call tbl SI Call table pointer call call tbl Call print c
  • 加载器如何引用共享库中的变量?

    我现在了解如何通过过程链接表引用动态函数 如下所示 Dump of assembler code for function foo plt 0x0000000000400528
  • Nasm 打印到下一行

    我用 nasm Assembly 编写了以下程序 section text global start start Input variables mov edx inLen mov ecx inMsg mov ebx 1 mov eax 4
  • 大会,你好世界问题

    我正在 Linux 上学习 asm noobuntu 10 04 我得到了以下代码 http asm sourceforge net intro hello html http asm sourceforge net intro hello
  • 程序集比较标志理解

    我正在努力理解汇编程序中的以下代码片段 if EAX gt 5 EBX 1 else EBX 2 在汇编程序中 可以写如下 根据我的书 模拟jge操作说明 https www felixcloutier com x86 jcc您通常会使用
  • X86 预取优化:“计算 goto”线程代码

    我有一个相当重要的问题 我的计算图有循环和多个 计算路径 我没有制作一个调度程序循环 其中每个顶点将被一一调用 而是将所有预先分配的 框架对象 放置在堆中 代码 数据 这有点类似于线程代码 甚至更好 CPS 只是在堆中跳转 执行代码 每个代
  • 是否可以在VM内使用VMX CPU指令?

    VM guest 内部的进程是否有可能使用 VMX AMD V VT x CPU 指令 然后由外部 VMM 处理而不是直接在 CPU 上处理 Edit 假设外部VM使用VMX本身来管理其虚拟客户机 即它在Ring 1中运行 如果可能的话 是
  • ELF动态符号表

    我有一个关于 ELF 动态符号表的问题 对于 FUNC 类型的符号 我注意到某些二进制文件中的值为 0 但在其他二进制文件中 它具有一些非零值 这两个二进制文件都是由 gcc 生成的 我想知道为什么会出现这种差异 有没有编译器选项来控制这个
  • 在 x86 程序集中存储大量布尔值的最佳方法是什么?

    最近我一直在处理充满布尔值的大型数组 目前 我将它们存储在 bss部分有一个 space指令 它允许我创建字节数组 但是 由于我只需要存储布尔值 因此我希望从数组中逐位读取和写入数据 目前 我能想到的最好方法是有一个 space指令所需存储
  • 为什么 Linux perf 使用事件 l1d.replacement 来处理 x86 上的“L1 dcache misses”?

    在英特尔 x86 上 Linux用途 https stackoverflow com a 52172985 149138事件l1d replacements来实施其L1 dcache load misses event 该事件定义如下 计数
  • 添加冗余赋值可以在未经优化的情况下编译时加快代码速度

    我发现一个有趣的现象 include
  • 为什么X86中没有NAND、NOR和XNOR指令?

    它们是您可以在计算机上执行的最简单的 指令 之一 它们是我亲自实施的第一个指令 执行 NOT AND x y 会使执行时间和依赖链长度和代码大小加倍 BMI1 引入了 andnot 这是一个有意义的补充 是一个独特的操作 为什么不是这个问题
  • PAE(物理地址扩展)如何实现大于4GB的地址空间?

    维基百科文章的摘录物理地址扩展 http en wikipedia org wiki Physical Address Extension x86 处理器硬件架构通过用于选择附加内存的附加地址线进行了增强 因此物理地址大小从 32 位增加到
  • 比“add esp, 4”更小的指令

    又是我 我的程序中有很多 add esp 4 我正在尝试减小它的大小 是否有任何更小的指令可以替代 add esp 4 pop edx 或者您不介意破坏的任何其他整数寄存器 这就是现代编译器实际上所做的 https stackoverflo
  • 汇编语言程序中连续两次相乘

    我正在使用 8086 模拟器以及 DOSBOX 和 MASM 我知道当我们将 8 位与 8 位相乘时 答案将是 16 位 al 8 bit ax 当我们将 16 位与 16 位相乘时 答案将是 32 位 ax 16 bit dx ax 但如
  • 如何使 gcc 为 -fpatchable-function-entry 发出多字节 NOP?

    gcc确实有能力使用多字节用于对齐循环和函数的 NOP 然而当我尝试 fpatchable function entry option https gcc gnu org onlinedocs gcc Instrumentation Opt
  • 为什么 GCC 在堆栈上压入额外的返回地址?

    我目前正在学习汇编的基础知识 在查看 GCC 6 1 1 生成的指令时遇到了一些奇怪的情况 这是来源 include

随机推荐

  • Qt QList 数据库序列化

    我有一个 QList 列表 我想将它插入到数据库中 经过一番谷歌搜索后 我没有找到任何序列化器方法 是否有任何方法 想法来序列化数据库的列表数据 怎么样使用QStringList代替QList
  • 使用 sed 在句点后插入空格

    我有一堆文件 其句子结尾如下 Next sentence 我想在句号后面插入一个空格 并非所有出现的 但是 没有空格 因此我的正则表达式检查句号后的下一个字符是否是大写字母 因为我要检查句点后的一个字符 所以我不能只进行替换 to 并且因为
  • 我可以为空的 Git 存储库创建工作树吗?

    我有一个空的 Git 存储库 即它尚未包含任何提交 有没有办法使用创建工作树git worktree add命令 与 no checkout选项 对于这个回购 我的意思是指示 Git 不要将新创建的工作树与任何HEAD yet In a c
  • 查询/tags/tag-name/media/recent端点,如何避免私人照片

    我目前正在定期访问 tags tag name media recent 端点 并将一些符合特定条件的媒体保存到我自己的数据库中 有时 我会得到一张私人照片 这意味着在我的画廊中 当我显示所述图像时 其中一些图像显示为损坏的链接 因为 In
  • 球体中的平均值

    我正在尝试计算圆内像素的平均值 将来这需要扩展到 3D 但现在 2D 解决方案已经可以帮助我了 从图像中可以看出 有些像素完全位于圆圈内 但有些像素仅部分位于圆圈内 部分位于圆圈内的部分也只需对平均值做出部分贡献 像素是正方形的 我希望这会
  • UILabel高度计算

    I have UILabel文本会根据服务器数据动态更改 有时数据太长 使我UILabel变成多行 有什么方法可以计算我的身高UILabel 你可以使用这个 var labelHeight CGFloat labelHeight theLa
  • 消除警报 XCUITest

    我正在尝试消除我的 XCUITest 套件上的警报 我目前正在使用 app alerts buttons OK tap 使用此功能可以消除警报 但应用程序会继续尝试点击按钮 然后失败并显示错误消息 UI 测试失败 未找到警报匹配项 这是控制
  • 将 JSON 文件对象拆分为多个文件

    我的文件包含太多 JSON 格式的数据对象 格式如下 type FeatureCollection features type Feature properties geometry type Polygon coordinates 37
  • 如何将 Polymer 元素导入到 plunker (plnkr.co)、jsBin 和 jsFiddle 等代码游乐场中?

    问题 In 这个普朗克 我想导入 Polymer 1 0 元素
  • JFreeChart:如何在同一图表上绘制折线图和散点图

    我有两组数据 int x1 1 2 3 4 5 6 7 8 9 10 int y1 1 2 3 5 6 8 9 10 14 11 int x2 1 2 3 4 5 6 7 8 9 10 int y2 0 2 3 5 0 8 9 8 14 1
  • 参考酶导入错误

    我正在尝试使用酶和玩笑为反应本机组件编写基本测试 我收到一条错误 暗示酶未正确导入 SearchPage it starts spinner when page is loading ReferenceError enzyme is not
  • Pandas:如何将列表转换为按列分组的矩阵?

    我有一个 pandas 数据框 其中第一列 CUSTOMER 是客户的姓名 并且客户的姓名对于客户购买的每个产品 Product 重复一次 Customer Product Count John A 1 John B 1 John C 1
  • 为什么 goroutine 中的 fmt.Println 不打印一行?

    我有以下代码 package main import net import fmt import bufio func main conn net Dial tcp irc freenode net 6667 reader bufio Ne
  • 使用 Windows Batch 脚本在 FOR 循环中计数

    谁能解释一下吗 我可以使用 Windows 命令提示符循环计数 使用以下方法 SET A XCOUNT 0 loop SET A XCOUNT 1 echo XCOUNT IF XCOUNT 4 GOTO end ELSE GOTO loo
  • 是否有基于任务的 System.Threading.Timer 替代品?

    我是 Net 4 0 任务的新手 我无法找到我认为是基于任务的计时器替换或实现 例如周期性任务 有这样的事吗 Update 它取决于 4 5 但这有效 public class PeriodicTask public static asyn
  • CakePHP - 删除级联不起作用

    在 CakePHP 中 我有一个模型 Type 和 SpecificType SpecificType 属于一个 Type type id 字段 当我删除SpecificType的条目时 如何才能同时删除Type 我把它作为 this gt
  • .filter() 函数返回未定义而不是过滤数组

    我正在尝试理解 javascriptArray filter方法 为什么下面的代码会返回undefined 我缺少什么 function driversWithRevenueOver driver revenue driver filter
  • 使用OpenGL绘制圆的一部分?

    我只想画一个部门 部分3d 圆的 给出 2 个角度 起点 终点 圆心坐标 半径和宽度 你能帮我做那件事吗 计算圆上点的公式 给定半径 圆心 x0 y0 和角度 以弧度为单位 float x radius cos angle x0 float
  • C++ 高效使用 new 运算符

    当用 new 实例化一个类时 如果不删除内存 我们会通过对象的重用获得哪些好处 新的流程是怎样的 是否发生上下文切换 新的内存被分配了 谁来分配 操作系统 你在这里问了几个问题 Instead of deleting the memory
  • 是否存在与 PE 基址重定位等效的 ELF?

    我一直在研究一些 ELF 二进制文件的反汇编 我注意到了这一点 0000000000401020 lt start gt 401020 31 ed xor ebp ebp 401022 49 89 d1 mov r9 rdx 401025