利用缓冲区溢出导致段错误

信息安全 缓冲区溢出 C
2021-09-05 11:15:41

我正在尝试利用简单的堆栈溢出漏洞。我在c中有一个基本代码:

#include <cstring>
int main( int argc, char** argv )
{
        char buffer[500];
        strcpy(buffer, argv[1]);
        return 0;
}

编译使用-fno-stack-protector. 我已经计算出缓冲区长度,并且成功覆盖了 EBP 和 EIP 寄存器。我注入了大量的 NOP,然后是这个 shell 代码,最后插入了一个注入的 NOP 所在的地址,以便执行代码。

现在的问题。在所附图片上,您可以看到 gdb 输出。如果我用恶意输入运行我的程序,它会得到一个 SIGSEGV。转储地址0xbffff880,您可以看到有很多 NOP 后跟 shell 代码(粉红色框),最后是地址(蓝色框)。

我认为这将按如下方式工作:起初0x90909090s 和 shellcode 被视为简单数据。在这些之后(经过粉红色的框)有一个地址0xbffff880我对 CPU 说“嘿,现在请执行正在执行的操作0xbffff880”。cpu 获取地址上的内容并执行所有 NOP 和 shellcode 本身。然而,这并没有发生并且 SIGSEGV 发生了。

我错在哪里?

gdb 输出

我试图在关闭 ASLR 的 32 位 Ubuntu 14.04 Linux 3.13.0-39-generic i686 的 Virtualbox 实例上实现这一点。

2个回答

您的内存地址0xbffff880很可能是不可执行的,但只能读/写。有几种方法可以克服这个问题。

  1. 如果那是您可以-z execstack在编译时使用的堆栈地址。这实际上将使整个堆栈内存可执行。
  2. 要获得更强大的解决方案,您可以编写 shellcode 以在您正在写入的地址上调用mprotect 。

例如,以下行将地址标记0xbffff880为读/写/可执行。

mprotect((void*) 0xbffff880, buffer_len, PROT_READ | PROT_WRITE | PROT_EXEC);

-fno-stack-protector并不意味着堆栈将是可执行的。它只会禁用其他安全功能,例如金丝雀或堆栈 cookie如果这些值在检查时被覆盖(缓冲区溢出),程序将失败。不会启用缓冲区的执行。

正如 RoraZ 所说,您的堆栈不可执行。为了扩展这一点,除非编译二进制文件以允许这种恶作剧,否则像这样的缓冲区溢出利用将无法在现代 Linux 机器上工作。您将需要禁用一些安全功能;RELRO,堆栈金丝雀,NX,馅饼。

有一个名为 checksec.sh ( http://www.trapkit.de/tools/checksec.html ) 的漂亮 bash 脚本可以帮助您检查二进制文件,例如:

在此处输入图像描述

我为 x86 缓冲区溢出测试编译二进制文件的方式:

gcc -m32 -g -mpreferred-stack-boundary=2 -no-pie -fno-stack-protector -Wl,-z,norelro -z execstack ./program.c
  1. -no-pie:禁用 PIE(与位置无关的可执行文件)
  2. -z execstack:禁用 NX(使堆栈可执行)
  3. -Wl,-z,norelro:禁用 RELRO(只读重定位)
  4. -fno-stack-protector:移除堆栈保护(堆栈溢出安全检查)

为了方便起见:

-g:添加调试

-mpreferred-stack-bounary=2:在 4 字节边界上对齐堆栈