堆栈与堆溢出检测

时间:2011-08-14 09:25:41

标签: c memory gcc stack heap

在像linux这样的需求分页系统中,页面可能比我读取的大约4k,它通过检查堆栈或堆大小是否超过给予每个页面的页数来确保保护。我什么时候创建两个变量

char *s = (char *) malloc(100);   
char sa[100];

在for循环中,我可以写s[i] = 'c';差不多4000次,然后才会出现内存错误 而使用sa[i] = 'c';编辑时:对于大于数组大小的任何内容,我会收到segmentation faultstack smashing错误。

我可以理解在第一种情况下有一个页面错误,它看到没有更多的页面被分配给堆,因此存在内存冲突。但是在第二种情况下会发生什么呢?gcc会在运行时为所有预分配的变量进行检查吗? 编辑:我发布下面的整个代码

int main(int argc,char* argv[]){
char *s = (char *) malloc(20);
char sa[400] = {0};
int i ,count;
printf(" enter the number of chars to write: ");
scanf("%d",&count);
for (i=0;i<count;i++){
printf("%d\n",i);
sa[i] = 'a';
//s[i] = 'a';
}
free(s);

}

1 个答案:

答案 0 :(得分:2)

在许多32位操作系统上,堆栈向下增长。您只在数组中使用正索引,因此它取决于函数调用的嵌套程度。当您从数组中索引时,您将首先覆盖该金丝雀。所以堆栈粉碎错误是第一个。接下来,您将开始覆盖函数参数和返回地址。如果没有金丝雀,那将导致函数返回跳入到永不停歇的地方,通常会产生段错误。并非总是如此,它可能会意外地落在有效代码上,即堆栈缓冲区溢出攻击背后的逻辑。

当你继续前进时,你最终会将堆栈的顶部写入未分配的页面。然后是Segfault。在一个小型测试程序中,很少有嵌套调用快速发生,几千字节给出或接受。

还可以使用负偏移量进行尝试。这可以持续一段时间,因为你写入未分配的堆栈空间,否则不会造成任何不幸。当您写入超过分配的堆栈大小(通常为兆字节)时会出现段错误。在Windows上,您将触发堆栈保护页面,生成一个以此站点命名的异常。