【问题标题】:C++ buffer overflow different on 3 machinesC++ 缓冲区溢出在 3 台机器上不同
【发布时间】:2013-09-16 21:02:39
【问题描述】:

我正在用 C++ 测试一个简单的缓冲区溢出。该示例是一个测试,如果没有进行检查,恶意用户可以使用缓冲区溢出覆盖变量。

该示例定义了一个缓冲区,然后是一个变量,这意味着应该为缓冲区分配空间,然后为变量分配空间。该示例从 cin 读取长度为 5 的缓冲区,然后检查 admin 变量是否设置为 0 以外的值,如果是,则用户在概念上获得了管理员访问权限。

#include <iostream>
using namespace std;

int main()
{
    char buffer[5];
    int admin = 0;

    cin>>buffer;
    if(strcmp(buffer,"in") == 0)
    {
        admin = 1;
        cout<<"Correct"<<endl;
    }
    if(admin != 0)
        cout << "Access" << endl;
    return 0;
}

我有 3 台机器,1 个 Windows 和 2 个 Linux 系统。

当我在 Windows(代码块)上测试它时(逻辑上) 输入超过 5 个字符会溢出并重写 admin 变量的字节

现在我的第一个 linux 系统也可以工作,但只有当我输入 13 个字符时,这是否与不同的编译器以及它们如何为程序分配内存有关?

我的第二台 linux 机器根本无法溢出。只有在第 13 个字符之后才会出现转储错误。

为什么它们差别这么大?

【问题讨论】:

  • 我从没想过 Windows 和 Linux 机器之间会有任何相似的行为。 Linux 系统之间的差异可以通过架构差异(内存映射)或组成程序或操作系统版本的元素的版本控制来解释......

标签: c++ compiler-construction buffer-overflow


【解决方案1】:

您应该检查反汇编。从那里你会看到究竟发生了什么。

一般来说,有两点需要考虑:

  1. 编译器为对齐堆栈变量而完成的填充。

  2. 编译器对堆栈变量的相对放置。

第一点:您的数组char buffer[5]; 将被填充,因此int admin; 将在堆栈上正确对齐。我希望它通常在 x86x64 上填充到 8 个字节,因此要覆盖 9 个符号。但是编译器可能会根据它认为合适的方式做不同的事情。尽管如此,似乎 Windows 和 Linux 机器是 x86(32 位)。

第二点:编译器不需要按照声明的顺序将栈变量放入栈中。在 Windows 和第一个 Linux 机器上,编译器确实将 char buffer[5]; 放在 int admin; 下面,所以你可以溢出到它里面。在第二台 Linux 机器上,编译器选择以相反的顺序放置它,因此在写入超出为char buffer[5]; 分配的空间后,您正在破坏main() 调用者的堆栈帧,而不是溢出到int admin;

这是我自己对类似问题的回答的无耻链接 - an example of examining of such overflow

【讨论】:

  • 谢谢,这正是我想要的。因为我认为 char 数组会收到 5 个字节,而 int 会收到 4 个字节。然后当溢出发生时,它会进入 int 的空间。我还读到分配工作在字中,如您所说,char 数组将是 8 字节。
  • @user2715411 好吧,当您的“输入”缓冲区大于它被复制到的堆栈变量(数组)时,发生溢出是绝对正确的。只是需要考虑一些内部因素,例如堆栈对齐、填充、变量放置——所有这些都会以稍微不同的行为表现出来(溢出或堆栈损坏的长度不同)。除此之外 - 这就是你所描述的。
【解决方案2】:

正如您所发现的,未定义的行为是未定义的。试图解释它通常不会很有成效。

在这种情况下,这几乎可以肯定是由于您的堆栈的排列和插入的/在编译器/系统之间的局部变量之间的填充字节。

【讨论】:

  • 对不起,但这不应该是“未定义的行为”,编译器是一个程序,因此在编译程序时应该遵循一组定义的步骤。如果 OP 说的是真的,那么两台可能都运行 gcc 的 linux 机器应该可以提供相同的可执行文件并获得相同的结果
  • @Chaosekie 该语言明确地为编译器提供了在不同机器上做不同事情的余地,更不用说在同一台机器上进行不同的编译了。
  • 能否请您参考一下这是在哪里定义的?而且似乎 OP 在 3 台不同的机器上始终获得相同的结果(他也花时间计算溢出所需的字符数)
猜你喜欢
  • 2012-02-05
  • 1970-01-01
  • 2011-07-02
  • 2011-09-07
  • 1970-01-01
  • 2015-12-16
  • 1970-01-01
  • 2010-11-11
  • 1970-01-01
相关资源
最近更新 更多