缓冲区溢出与缓冲区溢出攻击
缓冲区与缓冲区溢出问题
标签(空格分隔): C C字符串
注意:单个字符用单引号!字符串才用双引号!不然不能通过编译!!!
缓冲区溢出是指用有安全隐患的字符串处理函数,在输入超出规定字符串长度的字符之后,对该数组末尾的内存单元的覆盖。
例如
#include <stdio.h>
#include <string.h>
int main()
{
char str[8],*pstr=NULL,password[8];
password[8]="secret";
while(1)
{
gets(str);
if (strcmp(str,password)==0)
{
printf("Welcome!\n");
break;
}
else
printf("Sorry!\n");
}
return 0;
}
由于gets()函数并不限制字符串的输入长度,所以如果输入的字符多于8个,多余的部分就会把str末尾的内存单元中的数据覆盖。打开内存观察窗我们会发现,这部分恰好是password。如果我们第一次输入‘12345678me’,第一次会输出‘sorry!’,但是之后,me和其末尾的空字符会将password修改为‘me\000ret\000’(\000其实只表示一个’\0’字符)。接下来,我们输入me,程序就会输出’welcome!’,我们便获得了用户权限。
解决办法是什么呢?有好几个解决方案
我们可以用fgets()函数。格式如下
fgets(字符数组名,输入字符串长度,读取位置);
这表示读取“输入字符串长度”个输入字符。当我们用键盘输入时,读取位置填”stdin”。那么原程序可以改为
fgets(str,sizeof(str),stdin);
但是不同于gets()将换行符读入为”\0”,这个函数会将换行符当做字符一并读入,所以我们要么将口令末尾加一个换行符,成为”secret\n”,要么将换行符修改为”\0”,可以用下面的代码修改:
fgets(str,sizeof(str),stdin); for (i=0;str[i]!='\0';i++) { if (str[i]=='\n') { str[i]='\0'; break; } }
还有一个更简单的办法:
fgets(str,sizeof(str),stdin); for (i=0;str[i]!='\n';i++) //意为将指针移到换行符所在的位置 { ; } str[i]='\0'; //意为将换行符修改为空字符
此处假设输入字符串长度为7,则可以用
scanf("%7s",str);
表示仅仅读取输入数据的前七位,剩余数据从缓冲区清除
3.