[英]C++ buffer overflow different on 3 machines
我正在用C ++测试一个简单的缓冲区溢出。 该示例是一个测试,假设没有进行检查,恶意用户可能会使用缓冲区溢出来覆盖变量。
该示例定义了一个缓冲区,然后定义了一个变量,这意味着应该为该缓冲区分配空间,然后为该变量分配空间。 该示例从cin
读取长度为5的缓冲区,然后检查admin变量是否设置为非0的值(如果是),则用户在概念上获得了admin访问权限。
#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个字符之后才会给出转储错误。
为什么它们有那么大的差异?
正如您所发现的,未定义的行为是未定义的。 试图解释它通常不是很有效。
在这种情况下,几乎可以肯定是由于堆栈的安排和由在编译器/系统之间变化的局部变量之间插入的填充字节。
您应该检查反汇编。 从那里您将看到确切发生了什么。
一般来说,有两件事要考虑:
由编译器填充以对齐堆栈变量。
编译器对堆栈变量的相对放置。
第一点:您的数组char buffer[5];
将被填充,以便int admin;
将在堆栈上正确对齐。 我希望它通常在x86或x64上都填充为8个字节,因此要覆盖9个符号。 但是编译器可能会根据自己认为合适的方式进行不同的处理。 尽管如此, 看来 Windows和Linux计算机是x86 (32位)。
第二点:不需要编译器按声明顺序将堆栈变量放在堆栈上。 在Windows和第一个Linux机器上,编译器的确确实放置了char buffer[5];
以下为int admin;
,因此您可以溢出其中。 在第二台Linux机器上,编译器选择以相反的顺序放置它,这样就不会溢出到int admin;
,在超出为char buffer[5];
分配的空间char buffer[5];
写入之后,您正在破坏main()
调用方的堆栈框架char buffer[5];
。
这是我对类似问题自己答案的无耻链接- 研究这种溢出的一个例子 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.