为什么故意缓冲区溢出不会覆盖变量?

时间:2015-12-05 13:22:35

标签: c++ buffer-overflow

这可能是一个愚蠢的问题,因为我很确定这是不可能的,但如果是,请随时告诉我我做错了什么。 所以我一直在尝试缓冲区溢出,一般来说C / C ++中的内存是如何工作的,但是我遇到了一些非常奇怪的东西。

char arr[16];
char tmp = 33;

strcpy(arr, "AAAAAAAAAA3211f11f2gg233h4h34h43AAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBB");

cout << tmp << endl;

此代码由于某种原因产生“!” (如果转换为unsigned int是33),据我所知, strcpy 调用应该有溢出 arr 并覆盖 tmp (或可能甚至崩溃了程序,因为它是一个非常大的字符串),但它没有做到这一点。

cout << arr[20] << endl;

此代码返回“g”,即使它在技术上超出界限。

2 个答案:

答案 0 :(得分:4)

在给出实际答案之前,我需要承认语言律师的答案:未定义的未定义行为。您询问了未定义行为的意外结果,但对未定义行为的行为应该没有期望。

但实际的答案是典型架构上的堆栈会逐渐向低地址发展。

所以实际的期望是,超越arr[]将从当前函数的条目中删除已保存的寄存器(可能包括返回地址),因此当此函数尝试返回时会发生错误的事情。

但是在结构上晚于arr[]分配在堆栈上的内容将位于较低的地址并且不会超出溢出。在最简单的未经优化的编译器行为中,tmp稍后分配并低于arr,因此是安全的。

tmp安全的原因带有足够的编译器假设,如果tmp不安全,预测tmp会安全或感到惊讶是荒谬的。但tmp安全仍然比那段代码更有可能。 (已保存的功能被删除的寄存器远远超过&#34;更有可能&#34;。但即便如此,您也不可能信任的事情。)

答案 1 :(得分:0)

您的代码正在调用未定义的行为,因为您正在写入未分配的内存。任何事情都可能发生,打印'g',撞坏你的盒子或你的冰箱可能被搜查! :)