ASLR-PIC-PIE

如何生成动态库

Posted by 汤汤 on January 3, 2024

来自《深入理解计算机系统》

写在前面

ELF可重定位目标文件的格式

ELF(executable and linkable format)
常见的文件类型包括:可执行文件、共享库.so、目标文件.o和core文件

动态链接共享库

共享库.so是一个目标模块,在运行或加载时,可以加载到任意的内存位置,并和内存中的程序链接,整个过程称为 动态链接

ASLR

address space layout randomization

缓冲区溢出漏洞

在一些内存不安全的编程语言(如C语言)中,存在缓冲区溢出漏洞,一般是👨‍💻没注意验证用户输入数据大小是否超出合法范围导致的

漏洞利用需要知道可执行文件(executable)在内存中的实际位置location

ASLR技术

ASLR选项可以影响指定存储区域的全部存储分配。

启动ASLR选项

默认情况下,ASLR选项是关闭的🚫

  • 方法1️⃣:在系统进行初始程序装入(IPL)时,使用DIAGxx指定ASLR选项
  • 方法2️⃣:在IPL之后,设置SET DIAG=xx命令
    • 此时只会影响在启动ASLR选项之后启动的程序,不会影响先前已经启动的

安全编译选项 PIC

position indenpendent code 位置无关代码

  • PIC,即,那些可以在主存不同位置执行的目标代码,常常用在共享库中。
    • -fPIC: 编译选项
  • Linux编译共享库时,必须加上-fPIC参数

如何理解这里的“位置无关”: 多个进程可以公用共享库的代码段,而无需要拷贝副本
共享库中的变量通过.got表访问
共享库中的函数通过.plt.got解析函数实际地址进行调用

安全编译选项 PIE

position independent executables

  • PIE本身的目的:生成位置无关的可执行程序。
    • -fPIE 编译选项
    • -pie 链接选项
  • PIE是由PIC组成的可执行二进制文件
PIE生成动态库

-fPIE-share一起使用时,生成的结果可以作为可执行程序,也可以作为动态共享库

注意以下问题:🛎️🛎️🛎️

  • PIE编译生成动态库时,不会为全局变量在GOT表中创建对应的entry
  • 指定-fPIE参数生成共享库时,必须保证共享库中不包含main函数且不存在对外输出的全局变量 ·
    • 对外输出的全局变量会和PIC矛盾
  • 若指定-fPIE但不指定-share,只能生成可执行程序,故必须包含main函数

如何理解“PIE生成共享库时若存在对外输出的全局变量,会和PIC矛盾”
-fPIE不会为全局变量在GOT表中创建对应entry,在链接时所有变量都已确定(PIE最初的目的就是要生成位置无关的可执行程序的,而不是共享库)
一旦存在对外可见的全局变量,

  1. 作为共享库,该变量地址被认为是可重定位的
  2. 作为可执行程序,该变量地址被认为是固定的
    相矛盾