缓冲区溢出,C语言缓冲区完全攻略

  • 内容
  • 评论
  • 相关

虽然“缓冲区溢出”对现代操作系统与编译器来讲已经不是什么大问题,但是作为一个合格的 C 程序员,还是完全有必要了解它的整个细节。这里需要特别说明的是,为了更好地演示缓冲区溢出,本节的所有代码示例仅限于在 Windows XP SP3+Visua l C++6.0 环境中演示运行。

简单来说,缓冲区就是一块连续的计算机内存区域,它可以保存相同数据类型的多个实例,如字符数组。而缓冲区溢出则是指当计算机向缓冲区内填充数据位数时超过了缓冲区本身的容量,溢出的数据覆盖在合法数据上。

通常,在理想的情况下,程序检查数据长度并不允许输入超过缓冲区长度的字符。然而,由于 C 语言没有任何内置的边界检查,在写入一个字符数组时,如果超越了数组的结尾就会造成溢出。

与此同时,标准 C 语言函数库提供了一些没有边界检查的字符串处理函数,其中:

  • strcat()、strcpy()、sprintf() 与 vsprintf() 函数对一个 null 结尾的字符串进行操作,并不检查溢出情况;
  • gets() 函数从标准输入中读取一行到缓冲区中,直到换行或 EOF,它也不检查缓冲区溢出;
  • scanf() 函数在匹配一系列非空格字符(%s)或从指定集合(%[])中匹配非空系列字符时,使用字符指针指向数组,并且没有定义最大字段宽度这个可选项,就可能出现问题。

然而,如果这些函数的目标地址是一个固定大小的缓冲区,而函数的另外参数是由用户以某种形式输入,则很有可能被人利用缓冲区溢出来破解。

另一种常见的编程结构是使用 while 循环从标准输入或某个文件中一次读入一个字符到缓冲区中,直到行尾或文件结尾,或者碰到其他什么终止符。这种结构通常使用 getc()、fgetc() 或 getchar() 函数中的某一个,如果这时在 while 循环中没有明确检查溢出,这种程序就很容易被破解。

我们知道,任何一个源程序通常都包括代码段(或者称为文本段)和数据段,这些代码和数据本身都是静态的。为了运行程序,首先要由操作系统负责为其创建进程,并在进程的虚拟地址空间中为其代码段和数据段建立映射。但是只有静态的代码段和数据段是不够的,进程在运行过程中还要有其动态环境。

一般说来,默认的动态存储环境通过堆栈机制建立。所有局部变量及所有按值传递的函数参数都通过堆栈机制自动分配内存空间,分配同一数据类型相邻块的内存区域被称为缓冲区。图 1 展示了程序在内存中的映射。



图 1 程序在内存中的映射

本文标题:缓冲区溢出,C语言缓冲区完全攻略

本文地址:https://www.hosteonscn.com/2781.html

评论

0条评论

发表评论

邮箱地址不会被公开。 必填项已用*标注