osg*_*sgx 77
PIE是支持可执行文件中的地址空间布局随机化(ASLR).
创建PIE模式之前,该程序的可执行文件无法被放置在内存中的随机地址,只有位置无关代码(PIC)动态库会被重新定位到一个随机偏移.它与PIC对动态库的作用非常相似,不同之处在于未创建过程链接表(PLT),而是使用PC相对重定位.
在gcc/linkers中启用PIE支持后,程序体被编译并链接为与位置无关的代码.动态链接器对程序模块执行完全重定位处理,就像动态库一样.通过全局偏移表(GOT)将全局数据的任何使用转换为访问,并添加GOT重定位.
PIE在OpenBSD PIE演示中得到了很好的描述.
x86 pic vs pie
本地全局变量和函数以饼图进行优化
外部全局变量和函数与pic相同
并在此幻灯片中(PIE vs旧式链接)
x86派对无标志(已修复)
局部全局变量和函数类似于fixed
外部全局变量和函数与pic相同
注意,PIE可能与之不兼容 -static
Cir*_*四事件 27
最小的可运行示例:GDB可执行文件两次
对于那些想要看到一些动作的人:
#include <stdio.h>
int main(void) {
puts("hello");
}
Run Code Online (Sandbox Code Playgroud)
对于那个-no-pie,我们看到break main运行之间的变化地址:
#!/usr/bin/env bash
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
for pie in no-pie pie; do
exe="${pie}.out"
gcc -O0 -std=c99 "-${pie}" "-f${pie}" -ggdb3 -o "$exe" main.c
gdb -batch -nh \
-ex 'set disable-randomization off' \
-ex 'break main' \
-ex 'run' \
-ex 'printf "pc = 0x%llx\n", (long long unsigned)$pc' \
-ex 'run' \
-ex 'printf "pc = 0x%llx\n", (long long unsigned)$pc' \
"./$exe" \
;
echo
echo
done
Run Code Online (Sandbox Code Playgroud)
所以在这个例子中,第一次运行的地址是0x401126和第二次运行的地址run.
但是对于那个,两个运行0x401126的地址-pie保持不变0x1139:
Breakpoint 1 at 0x401126: file main.c, line 4.
Breakpoint 1, main () at main.c:4
4 puts("hello");
pc = 0x401126
Breakpoint 1, main () at main.c:4
4 puts("hello");
pc = 0x401126
Run Code Online (Sandbox Code Playgroud)
0x5630df2d6139确保ASLR打开(Ubuntu 17.10中的默认设置):如何暂时禁用ASLR(地址空间布局随机化)?| 问问Ubuntu.
0x55763ab2e139需要GDB,顾名思义,默认情况下关闭进程的ASLR以在运行时提供固定地址以改善调试体验:gdb地址和"真实"地址之间的差异?| 堆栈溢出
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space 开玩笑
此外,我们还可以观察到:
Breakpoint 1 at 0x1139: file main.c, line 4.
Breakpoint 1, main () at main.c:4
4 puts("hello");
pc = 0x5630df2d6139
Breakpoint 1, main () at main.c:4
4 puts("hello");
pc = 0x55763ab2e139
Run Code Online (Sandbox Code Playgroud)
给出实际的运行时加载地址:
readelf -s ./no-pie.out | grep main
Run Code Online (Sandbox Code Playgroud)
而:
64: 0000000000401122 21 FUNC GLOBAL DEFAULT 13 main
Run Code Online (Sandbox Code Playgroud)
只给出一个偏移量:
readelf -s ./pie.out | grep main
Run Code Online (Sandbox Code Playgroud)
通过关闭ASLR(使用set disable-randomization off或者readelf),GDB总是给出randomize_va_space地址:set disable-randomization off,因此我们推断main地址由以下组成:
65: 0000000000001135 23 FUNC GLOBAL DEFAULT 14 main
Run Code Online (Sandbox Code Playgroud)
TODO在Linux内核/ glibc加载器/哪里是硬编码的0x555555554000?如何在Linux中确定PIE可执行文件的文本部分的地址?
在Ubuntu 18.04中测试过.
相关问题:如果使用-fPIC构建目标文件,我怎么能用objdump这样的东西来判断?
| 归档时间: |
|
| 查看次数: |
61397 次 |
| 最近记录: |