【发布时间】:2013-07-09 12:32:33
【问题描述】:
考虑以下易受攻击的代码/程序:
#include <string.h>
int main(int argc, char *argv[]) {
char buf[16];
strcpy(buf, argv[1]);
return 0;
}
在 IA-32(x86,32 位)上运行 Linux 并启用 NX 和 ASLR,我将使用 GOT 覆盖技术来利用这一点,该技术主要包括以下步骤:
- 溢出缓冲区直到 RIP
- 用
strcpy@plt的地址覆盖RIP - 使用来自
.text的干净小工具,例如pop edi ; pop ebp ; ret,作为strcpy的返回地址 - 为
strcpy写入参数:&bss-address 作为目标地址和/bin/sh的一个字节,使用.text - 重复步骤 2-4,直到
/bin/sh完全写入&bss - 用
system覆盖strcpy的 GOT 条目(使用偏移量,需要了解使用的 Libc 版本 - 我们在此忽略) - 在堆栈上写入
strcpy@plt,然后是一些4字节的块,最后是&bss的地址,它指向/bin/sh - 利润
我想在启用相同缓解措施的情况下在 x86-64 上利用它。但这比想象的要困难得多。主要有以下几个原因:
- x86-64 基于寄存器的调用约定:函数参数使用寄存器而不是堆栈传递。因此,需要一些额外的 ROP-gadgets 将参数从堆栈传输到适当的寄存器。这是一个小问题,但也会受到以下问题的影响:
-
64 位返回地址:x86-64 中的 RIP 指向
.text,它甚至不是 32 位长。因此,必须将 NULL 字节写入堆栈以链接函数调用。基本上,可以使用对strcpy的链式调用并利用strcpyalways 写入的 NULL 终止字符来根据需要写入尽可能多的 NULL 字节。但是一个人只能通过覆盖 RIP 的最低有效字节来调用一次strcpy。|0x00000000| (most significant bytes) |0x00deadbe| <- RIP (least significant bytes) |0x41414141| |0x41414141| <- SFP | ... |
这些是我在启用 NX 和 ASLR 的 x86-64 上利用该程序时遇到的主要问题。有什么技术可以解决这些问题吗?或者 x86-64 真的能阻止一个有效的、打开 shell 的漏洞利用吗?
【问题讨论】:
-
如果 RIP 应该代表返回地址,您需要 x86-64 的新术语。就像 EAX 扩展为 RAX 一样,EIP(当前指令指针)扩展为 RIP。所以在 x86-64 中,RIP 是一个寄存器名称,并且(本身)不会为 RET 将读取的返回地址命名。
标签: linux x86-64 buffer-overflow aslr dep