考虑以下易受攻击的代码/程序:
#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
- 用地址覆盖 RIP
strcpy@plt
- 使用一个干净的小工具
.text
,例如pop edi ; pop ebp ; ret
,作为返回地址strcpy
- 写参数
strcpy
:&bss
-address 作为目的地和一个字节的/bin/sh
using.text
- 重复步骤 2-4 直到
/bin/sh
完全写入&bss
strcpy
用 with覆盖 GOT 条目system
(使用偏移量,需要了解使用的 Libc 版本 - 让我们在这里忽略它)- 写入
strcpy@plt
堆栈,然后是一些 4 字节的块,最后是&bss
指向的地址/bin/sh
- 利润
我想在 x86-64 上利用相同的缓解措施来利用它。但这比想象的要困难得多。主要有以下几个原因:
- x86-64 基于寄存器的调用约定:函数参数使用寄存器而不是堆栈传递。因此,需要一些额外的 ROP-gadgets 将参数从堆栈传输到适当的寄存器。这是一个小问题,但也受以下问题的影响:
64 位返回地址:x86-64 中的 RIP 指向的地址
.text
甚至不是 32 位长。因此,必须将 NULL 字节写入堆栈以链接函数调用。strcpy
基本上,使用链式调用并利用strcpy
始终写入的 NULL 终止字符,可以根据需要写入尽可能多的 NULL 字节。strcpy
但是通过只覆盖 RIP 的最低有效字节可能只调用一次。|0x00000000| (most significant bytes) |0x00deadbe| <- RIP (least significant bytes) |0x41414141| |0x41414141| <- SFP | ... |
这些是我在启用 NX 和 ASLR 的 x86-64 上利用该程序时遇到的主要问题。有什么技术可以解决这些问题吗?或者 x86-64 真的能阻止一个有效的、打开 shell 的漏洞利用吗?