我对这种行为感到困惑和兴奋,我从我的C代码中获取。我不明白这是怎么发生的!在此之前,我希望展示代码 -
#include <stdio.h>
int main(){
char string[2];
printf("Enter your string here: ");
gets(string);
printf("%s \n", string);
return 0;
}
很明显 - 这里没什么特别的。实际上,这是我的计算机,数据和放大器的分配。网络安全当然,我想要演示 BufferOverflow 。这是我可以创建的最简单的。
当我输入13个字符时,它工作得很好; 15个或更多章程导致所需的 BufferOverflow 。 当我输入正好14个字符时,就会发生灾难。代码开始表现得像一个循环!就像一次又一次地调用main
函数一样 -
我正在使用 CodeBlocks-16.01 和 GNU GCC编译器。我也用命令运行它,得到了相同的结果。我还在TutorialsPoint上执行了代码,但没有在那里遇到这个问题。
我不知道发生了什么。这是 gcc 的问题吗?
答案 0 :(得分:7)
您的代码会生成缓冲区溢出 - 真正的。超过string
的末尾可以覆盖[{1}}在完成时应该返回的[在堆栈上]的返回地址。
如果选择正确,它可以循环回main
或跳转到内存中的任何位置。实际上它取决于编译器,链接器,加载器,程序加载的地址。
和,输入的字符串的值(即)某些字符串将崩溃,其他字符串可能会循环,某些字符串可能会产生愚蠢的结果,但不会产生循环。一个字符串可能在给定环境中执行X行为,在另一个环境中执行Y行为。不同的字符串可能会反转这些结果。
你真正想做的是演示(即模拟)缓冲区溢出,而不做任何会导致程序崩溃的事情。
这是一种安全的方法:
main
<强>更新强>
你应该特别警告不要使用
#include <stdio.h> #define SEED 0xFF // sentinel value // NOTE: using a struct guarantees that over will appear directly after string // (i.e.) over is higher in memory than string struct buffer { char string[4]; // buffer that can overflow unsigned char over[80]; // safe place for the overflow }; int main(void) { struct buffer buf; int idx; int over; // prefill the "overflow detection buffer" with a sentinel value (e.g. one // that can't be input via fgets [under normal circumstances]) for (idx = 0; idx < sizeof(buf.over); ++idx) buf.over[idx] = SEED; printf("Enter your string here: "); fflush(stdout); // NOTE: this fgets will never _really_ cause any harm -- the "10" slop // factor guarantees this fgets(buf.string,sizeof(buf) - 10,stdin); // overflow is anything that ran past string into over over = 0; for (idx = 0; idx < sizeof(buf.over); ++idx) { if (buf.over[idx] != SEED) { over = 1; break; } } if (over) printf("buffer overflowed\n"); else printf("buffer did not overflow\n"); return 0; }
通常,我会。由于这个问题的特殊性,我对此持怀疑态度。
(即使他想要一个缓冲区溢出,你应该添加为什么他可能很好地得到一个他不想使用已移除的
gets
函数)
IMO,在我的示例代码中使用gets
暗示,但可能没有专门推断。所以,够公平......
在我的示例代码中,使用fgets
代替gets(buf.string)
可以/将产生相同的[期望]效果。但是,这将仍然不安全,因为读取的长度仍然没有限制。它可能超过总结构长度fgets
并像以前一样产生真正的缓冲区溢出。
由于您尝试导致缓冲区溢出,因此使用sizeof(string) + sizeof(over)
进行编码更容易,但您会遇到不良行为。
[正如其他人所指出的] gets
因此而被弃用。如果您只是想要正常使用,请将gets
替换为gets(string)
因此,从不使用fgets(string,sizeof(string),stdin)
并始终使用gets
。