来自《深入理解计算机系统》
写在前面
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最初的目的就是要生成位置无关的可执行程序的,而不是共享库)
一旦存在对外可见的全局变量,
- 作为共享库,该变量地址被认为是可重定位的
- 作为可执行程序,该变量地址被认为是固定的
相矛盾