缓冲区溢出如何成为黑客的漏洞?

How can a buffer-overflow be an exploit for hackers?

我看过一个关于 "Buffer overflow exploit" 的视频,视频中的那个人写入的字节数超过了数组的容量,例如:

int foo(const char* cp){
    char sz[10];
    strcpy(sz, cp); // consider cp is a pointer to 20 characters
    return x; // some valid return statement here
}

以上如果 foo 使用 20 个字符的参数调用,那么我确定它是未定义的行为。但他为什么说这可能是一种利用,又是如何利用的?

这可能是一个漏洞,有很多条件,列出所有条件会让我们在这个网站上走得太远。基本情况非​​常简单,但当然有很多保护措施使得很难将其实际用作漏洞利用。要使缓冲区变得可利用,必须满足以下条件。

  • 加载到缓冲区中的内容使得代码指针最终遍历缓冲区的内容。这通常意味着它很大,有很多 NOP。
  • 缓冲区的内容包含有效的机器代码。否则你只会得到一个异常和程序崩溃,呃。

  • 启动可利用代码的应用程序具有对利用感兴趣的特权。 OS'es 有很多层,旨在阻止未经验证或未签名的代码。

  • 内存使用是可预测/可训练的。现代 OS 重定位内存,因此应用程序不再保证固定指针地址
  • 处理器控制流程是可预测/可训练的。有时,漏洞需要 'train' 处理器分支到特定条件状态。

But Why he said it can be an exploit and how?

仅举几个例子:

通过简单地覆盖其他有意义内容的内存内容。也许您的缓冲区结构后面有一个 bool 变量,其中包含访问权限标志。覆盖缓冲区可能会设置访问标志,代码将提供访问权限,这不是我们想要的。

破坏堆栈也是一件坏事。也许您的 return 语句在错误的地址上运行更为关键,执行缓冲区的某些内容。

每个搜索引擎都可以找到很多这样的东西!

操纵标志访问的简单示例:

struct Check
{
    char small[4];
    bool accessGranted;
};  

int main()
{   
    Check check{ "", false };

    strcpy( check.small, "12345" );

    if ( check.accessGranted )
    {
        std::cout << "Ubs...!" << std::endl;
    }
}

顺便说一句:我发现这篇论文有点过时但很有用:http://www.cis.syr.edu/~wedu/Teaching/IntrCompSec/LectureNotes_New/Buffer_Overflow.pdf

堆栈不仅包含您的局部变量,还包含您的 return 地址,参见 https://en.wikipedia.org/wiki/Call_stack

通过覆盖堆栈,您可以强制 CPU 跳转到 您选择的 位置,在发生攻击时,该位置是一个内存区域填充了攻击者的恶意代码。

现在计算机以您的权限运行攻击者代码。