PLT
- PLT(Procedure Linkage Table)是用于动态链接共享库中函数调用的一种数据结构,它在程序运行时起着至关重要的作用。下面是对 PLT 的详细解释:
- 作用:
- PLT 主要用于实现库函数的延迟绑定(dynamic binding)。它负责将程序中对共享库中函数的调用映射到最终的共享库函数的地址上,并且支持共享库的重定位。
- 实现原理:
- 当一个程序调用共享库中的函数时,对应的 PLT 条目会被执行。PLT 条目实际上是一段代码,它的主要功能是在第一次调用函数时进行解析和重定位,以确定函数的实际地址。一旦确定了函数的地址,后续的调用直接跳转到该地址,避免重复解析和重定位。
- PLT 的条目会调用像
dlopen()
和dlsym()
这样的动态链接库函数来查找并解析目标函数的地址,然后将其缓存到 PLT 条目中,从而实现延迟绑定。
- PLT 条目结构:
- PLT 条目一般包含两个部分:GOT(Global Offset Table)和 Procedure Linkage Table。
- GOT 表是一个全局偏移表,保存了动态链接过程中需要的地址,包括函数的地址、全局变量的地址等。
- PLT 表包含了对 GOT 表的间接调用指令,这些指令用于在第一次调用函数时进行解析和重定位。
- 实现细节:
-
当程序调用共享库中的函数时,实际上是首先跳转到了 PLT 的相关条目。这个 PLT 条目会调用动态链接库中的函数
_dl_runtime_resolve()
(或者类似的函数),这个函数会进行符号解析和重定位。总之,PLT 是为了实现共享库的动态链接而设计的一个重要的数据结构。它能够在程序运行时动态地解析共享库函数的地址,从而使得程序在不同的环境中能够正确链接到共享库中的函数。这对于实现共享库的延迟绑定和动态链接非常重要。
-
Sections VS Segments
特性 | Sections(节) | Segments(段) |
---|---|---|
定义 | ELF 文件的基本组成单位,用以组织相似类型的数据和代码。 | 执行时内存映像的基本组成单位,实际反映在进程的地址空间中。 |
类型 | 包含多种类型(例如 .text , .data , .bss , .rodata , .dynamic , .symtab 等)。 | 分为多个类型(如 LOAD , _DYNAMIC , INTERP , PHDR 等)。 |
目的 | 主要用于编译和链接过程,提供静态结构,便于符号查找和重定位。 | 主要用于运行时内存管理,确定如何将 ELF 文件加载到内存中。 |
内容 | 以逻辑组织数据,比如变量、函数、调试信息等。 | 以物理组织,定义了在运行时映射到内存中的实际地址。 |
可见性 | 可以包含仅在链接时处理的信息,不一定包含在可执行文件运行时需要的内容。 | 只包含执行程序实际运行时需要的信息。 |
存储位置 | 在 ELF 文件的 头部 中有记录,分配在文件中的固定位置。 | 在 ELF 文件的 程序头 中有记录,灵活控制加载到内存的方式。 |
重定位信息 | 常用于存放符号表和重定位信息,供链接器和动态链接器使用。 | 通常不包含重定位信息,只包含映射到内存后的地址空间。 |
数量 | 可以有多个 section,通常比较多,依赖于编译的选项和代码的结构。 | 通常较少,由程序头定义,反映执行所需的内存布局。 |
总结
- Sections 是用于静态代码和数据组织的基本单元,主要在编译和链接过程中使用。
- Segments 是用于定位和加载程序在运行时所需的内存布局,涉及内存管理和执行。
摘录:P161
我们很难将 “Segment” 和 “Section” 这两个词从中文的翻译上加以区分,因为很多时候 Section 也被翻译成“段”,回顾第2章,我们也没有很严格区分这两个英文词汇和两个中文词汇“段”和“节”之间的互相翻译。很明显,从链接的角度看,ELF 文件是按“Section”存储的,事实也的确如此;从装载的角度看,ELF 文件又可以按照“Segment” 划分。我们在这里就对“Segment”不做翻译,一律按照原词。
随机地址空间分布技术
随机地址空间分布技术(Address Space Layout Randomization,ASLR)是一种有效的计算机安全机制,用于防止缓冲区溢出等攻击方式。ASLR 通过随机化程序和执行环境的内存地址布局,可以大大增加攻击者成功利用已知漏洞的难度。
ASLR 的工作原理
ASLR 的基本原理是每次程序执行时随机化其关键内存区域的地址。具体来说,ASLR 随机化以下几个主要部分:
-
代码段:
- 动态库和可执行文件的加载地址会随机化,使得程序的代码在每次执行时都处于不同的地址空间。
-
堆区:
- 堆内存的分配也会随机化,使得动态分配的数据以不同的方式安置在内存中。
-
栈区:
- 线程栈的起始地址也是随机的,增加了攻击者通过已知地址进行攻击的难度。
-
共享库:
- 使用的共享库的加载地址也会被随机化,从而限制攻击者利用共享库的已知地址进行攻击的能力。
ASLR 的优点
-
提高了安全性:
- ASLR 增加了攻击者成功利用漏洞的难度,攻击者无法预先知道内存布局,从而降低了利用攻击成功的概率。
-
广泛适用:
- 可以应用于多数操作系统和平台,包括 Windows、macOS 和 Linux 等。
-
与其他安全措施搭配使用:
- ASLR 通常与其它安全技术(如数据执行保护(DEP)或堆栈保护)结合使用,以提供多层次的防护。
ASLR 的挑战
-
性能开销:
- 在某些情况下,随机化可能带来一定的性能开销,尽管这个开销通常是微乎其微的。
-
实现复杂性:
- 开发者需要以某种方式支持 ASLR,特别是在涉及旧版软件时。
-
回退攻击:
- 尽管 ASLR 能够增加攻击难度,但如果攻击者能够通过信息泄漏等手段获取地址信息,仍然可能成功。因此,必须结合其他安全措施使用。
具体实现
在 Linux 和其他 UNIX-like 系统中,ASLR 是通过特定的系统调用实现的。例如,Linux 内核使用了 mmap
系统调用来随机化地址空间。在 Windows 系统中,ASLR 是通过 PE 文件格式的头信息进行控制的。
在很多现代操作系统中,ASLR 是默认启用的,但可以通过系统配置进行调节。例如,在 Linux 中,可以通过检查 /proc/sys/kernel/randomize_va_space
文件来查看和设置 ASLR 的行为:
cat /proc/sys/kernel/randomize_va_space # 查看当前设置
echo 2 > /proc/sys/kernel/randomize_va_space # 启用全部 ASLR
总结
随机地址空间分布技术(ASLR)是现代计算机安全的基石之一,通过随机化程序的内存布局,使外部攻击者难以利用内存漏洞。尽管 ASLR 不是完全的保护,但它显著提高了计算机系统的安全性,降低了成功攻击的机会。它适合与其他安全措施结合使用,以实现更高级别的保护。