return 使用函数指针对 libc 进行攻击

return to libc attack using a function pointer

我应该如何在以下代码中格式化我的 return 到 libc 攻击的输入:

void example_function(int x, const char *name)
{
    void (*foo)(int, const char *) = http_serve_none;
    char buf[1024];

    sprintf(buf, name);

    foo(x, buf);
}

鉴于堆栈不可执行。我想通过将 foo 函数指针更改为 libc 中的系统而不是通过更改 example_function 的 return 地址来对 libc 进行 return 攻击。到目前为止我所做的是使用传统的输入方法:

padding + address of system ( at foo function's address ) + address of exit + ptr to string ( string = "/bin/sh" )

但是这是行不通的。我不知道如何在系统调用的输入字符串中格式化我的参数。我在互联网上搜索了很多,但到处都看到只使用 return 地址调用 system() 。

额外假设:

系统调用地址中没有'0'。机器是 32 位的,sprintf 工作正常,即将名称存储到缓冲区 buf[1024].

首先,确保您的 sprintf 实际上是 sprintf 而不是 __sprintf_chk ,后者会试图阻止您的溢出。你可以说它是强化版本,因为你会得到一个 SIGABRT 而不是其他东西(比如 SIGSEGV)。您可以全局关闭强化,但您也可以像这样避免使用宏:

(sprintf)(buf, name);

你的下一个问题是零。如果 system 的地址中有任何零字节,那么 sprintf 将在该点停止复制。这既是 "well, there are an awful lot of 64-bit addresses with zeros in them," 也是故意的。它被称为 ASCII 装甲,在某些平台上,重要的 libc 函数被确保在它们中有零以准确地阻止这种攻击。 (有关更多信息,请参阅 Writing a return-to-libc attack, but libc is loaded at 0x00 in memory。)

您可能想使用程序中的一个函数(即不是 libc)来探索这种攻击,您已确保其中没有零。如果您为 32 位构建,这会更容易一些。当然,您可能想关闭强化和堆栈保护以及编译器为停止此操作所做的所有其他事情:D(至少在您有一个基本版本工作之前;然后您可以一次打开它们时间)。

我终于解决了...我只是在 x 的地址传递了指向字符串“/bin/sh”的指针,它对我有用