3台机器上的C ++缓冲区溢出不同

时间:2013-09-16 21:02:39

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

我在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(CodeBlocks)上测试它时(逻辑上) 输入超过5个字符溢出并重写admin变量的字节

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

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

为什么他们差异很大?

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

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

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

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

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

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

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

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