发布于

PIE

作者

地址无关代码 (Position-Independent Code, PIC) 又称地址无关可执行文件 (PIE, Position-Independent Executable)。这意味着每次运行该文件时,它都会被加载到不同的内存地址中。因此你无法在不知道函数地址和 Gadget 等东西的地址的情况下对它们进行硬编码。

0x01 分析

幸运的是,这并不意味着它无法被利用。PIE 基于相对地址而不是绝对地址。虽然程序的不同部分在内存中的绝对地址是随机的,但它们之间的偏移量是固定的。例如,如果你知道 main 函数总是位于二进制文件基地址之后的 0x128 字节处,如果找到来 main 的地址,可以通过 main 地址减去 0x128 字节获得基地址,进而可以计算出其它函数的地址。

0x02 利用

因此,我们只要找到 一个 固定偏移量函数的地址,就可以推导出基地址和其它地址了。我们可以从栈中泄露这个地址。

我们知道返回地址位于栈上。就像 Canary 一样,我们可以使用格式化字符串(或其它方式)从栈中读取值。这个返回地址的值始终与二进制文件的基地址存在一个固定的静态偏移量,使我们能够绕过 PIE!

0x03 双重检验

由于 PIE 随机化的实现方式,PIE 可执行文件的基地址始终以十六进制字符 000 结尾。这是因为内存中进行随机化的最小单位是页(Page),其标准大小为 0x1000 。操作系统通过页表跟踪每个内存段的位置和权限,类似分段机制。

页表中每个条目都指向一个页大小的内存块。加载 PIE 文件时,会随机映射到某个页面上。地址就被限制在以 0x1000 对齐的边界。因此 PIE 基地址末尾总是 000 ,这是由页大小导致的。

如果你的漏洞利用程序未按预期工作,则检查以 000 结尾的基地址可能是你要做的第一件事情。

0x04 Pwntools,PIE 和 ROP

如这篇 Pwntools ELF 教程 中所示,pwntools 具有许多功能,可让你使漏洞利用半自动化。只需设置 elf.address 就会自动为你更新所有函数和符号的地址,这意味着你不必使用 readelf 或其它工具来获取地址,而是可以动态更新所有内容。

更不用说 ROP 功能 了,它们都非常强大与方便。