什么是PIE?

PIE全称是position-independent executable,中文解释为地址无关可执行文件,该技术是一个针对代码段(.text)、数据段(.data)、未初始化全局变量段(.bss)等固定地址的一个防护技术,如果程序开启了PIE保护的话,在每次加载程序时都变换加载地址。

如何开启PIE?

在用gcc编译时,使用如下命令:

1
2
3
4
5
6
7
8
9
gcc -o test test.c // 默认情况下,不开启PIE

gcc -fpie -pie -o test test.c // 开启PIE,此时强度为1

gcc -fPIE -pie -o test test.c // 开启PIE,此时为最高强度2

gcc -fpic -o test test.c // 开启PIC,此时强度为1,不会开启PIE

gcc -fPIC -o test test.c // 开启PIC,此时为最高强度2,不会开启PIE

另外,只有在系统随机化功能开启的时候,PIE才真正的开启。否则,每次运行程序时,程序的装载地址都是固定不变的。

可以通过如下命令查看当前系统随机化功能的状态:

1
$ cat /proc/sys/kernel/randomize_va_space

其中,返回值有如下含义:

  • 0 = 关闭
  • 1 = 半随机。共享库、栈、mmap() 以及 VDSO 将被随机化。
  • 2 = 全随机。除了1中所述,还有heap。

可以通过如下命令修改为全随机(具体可参考https://blog.csdn.net/counsellor/article/details/81543197):

1
$ sudo sysctl -w kernel.randomize_va_space=2

PIE绕过

  1. 直接leak出地址。
  2. 通过覆盖低位实现有范围限制的任意执行。(最低3/2个byte值为固定的,即在偏移0x000~0xfff任意处执行,必要时可以选择爆破,概率也不算太低)
  3. 直接调用vsyscall。