fPIE是什么
以下内容来自gcc编译选项fpic/fPIC, fpie/fPIE的说明_一点点-CSDN博客
-shared; Create a shared library /* 创建共享库时需要添加的编译选项 */
因为共享库的代码都是位置无关的,所以通常还需要添加编译选项-fPIC。
-fPIC; Generate position-independent code if possible (large mode)
-fpic; Generate position-independent code if possible (small mode)
编译共享库时使用;
-fPIE; Generate position-independent code for executables if possible (large mode)
-fpie; Generate position-independent code for executables if possible (small mode)
编译可执行程序时使用
还需要在ld时增加-pie选项才能产生这种代码。即gcc -fpie -pie来编译程序。单独使用哪一个都无法达到效果。
-pie; Create a position independent executable
================================================================================================
关于large mode和small mode
“mcmodel=” Use given x86-64 code model [仅适用于x86_64环境]
-mcmodel=small
Generate code for the small code model: the program and its symbols must be linked in the lower 2 GB of the address space. Pointers are 64 bits. Programs can be statically or dynamically linked. This is the default code model.
[默认值]程序和它的符号必须位于2GB以下的地址空间。指针仍然是64位。程序可以静态连接也可以动态连接。
-mcmodel=kernel
Generate code for the kernel code model. The kernel runs in the negative 2 GB of the address space. This model has to be used for Linux kernel code.
内核运行于2GB地址空间之外。在编译linux内核时必须使用该选项!
-mcmodel=medium
Generate code for the medium model: The program is linked in the lower 2 GB of the address space. Small symbols are also placed there. Symbols with sizes larger than ‘-mlarge-data-threshold’ are put into large data or bss sections and can be located above 2GB. Programs can be statically or dynamically linked.
程序必须位于2GB以下的地址空间,但是它的符号可以位于任何地址空间。程序可以静态连接也可以动态连接。
注意:共享库不能使用这个选项编译!
-mcmodel=large
Generate code for the large model: This model makes no assumptions about addresses and sizes of sections.
对地址空间没有任何限制。
为什么需要fPIE
以下内容来自GCC -fpie选项生成文件分析_softee的专栏-CSDN博客
Linux系统下,ELF格式的可执行文件的各个段都会被分配到不同的虚拟内存空间中。在操作系统实现地址随机化机制(Address Space Layout Randomization)之前,程序在任意一次执行下,所使用的虚拟空间的地址往往是相同的。这就给恶意攻击者的攻击行为提供了很大的便利(见Stack Smashing for Fun and Profit)
不使用fPIE的时候:
程序exam1的代码段和数据段分别对应的虚拟地址为00400000-00401000和00600000-00601000,而且在两次不同的执行中,地址不变。
堆栈段(stack)在两次执行中则有了变化,第一次为7fff783b9000-7fff783da000,第二次为7fff7f27a000-7fff7f29b000。这是因为操作系统的地址随机化机制,把堆栈段的地址随机化了,每次不同的执行都对应不同的堆栈段。
使用fPIE的时候:
elf文件中的代码段被映射到了不同的虚拟内存地址上,这是因为编译器在该选项下可以生成位置无关的代码,从而在执行时,可以被装载到不同的地址空间。当代码、数据、stack和heap在每次执行时,都被随机化分配到不同的空间的时候,攻击者的难度无疑大大增加了。