缓冲区溢出——栈溢出

1、缓冲区概念
缓冲区(buffer)又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。

使用缓冲区有两个好处:
1、减少实际物理读写次数
2、缓冲区在创建时就被分配内存,这块内存区域一直被重用,可以减少动态分配和回收内存的次数

比如我们从磁盘里取信息,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度。

比如从网上下电影,你不能下一点点数据就写一下硬盘,而是积攒一定量的数据以后一整块一起写,不然硬盘都要被你玩坏了

假设要实现一个功能:接受用户键入的字符串,并赋值给一个字符串变量其过程如下:
1:在内存中开辟一个”键盘缓冲区“接受用户键入的字符串
2:把缓冲区中的字符串copy到程序中定义的字符串变量指向的内存空间(也就是赋值过程)
也就是说,为了完成最终目标:把字符串放入字符串变量指向的空间,需要暂时把字符串放入“键盘缓冲区”的空间。
这里,缓冲区解决的问题不是“时间”,而是“空间”,为数据找一个暂存地。

所以,缓冲区就是一块内存区,它用在输入输出设备和CPU之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。

2、缓冲区溢出概念
缓冲区溢出,简单的说就是计算机对接收的输入数据没有进行有效的检测(理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符),向缓冲区内填充数据时超过了缓冲区本身的容量,而导致数据溢出到被分配空间之外的内存空间,使得溢出的数据覆盖了其他内存空间的数据。操作系统所使用的缓冲区,又被称为“堆栈”,在各个操作进程之间,指令会被临时储存在“堆栈”当中,“堆栈”也会出现缓冲区溢出。所以,栈溢出是缓冲区溢出的一种。

3、栈溢出
栈溢出指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,因而导致与其相邻的栈中的变量的值被改变。栈溢出漏洞轻则可以使程序崩溃,重则可以使攻击者控制程序执行流程。此外,我们也不难发现,发生栈溢出的基本前提是

-程序必须向栈上写入数据。
-写入的数据大小没有被良好地控制。

栈溢出中比较重要的几个步骤

  • 寻找危险函数
    通过寻找危险函数,我们快速确定程序是否可能有栈溢出,以及有的话,栈溢出的位置在哪里。常见的危险函数如下

    • 输入:
      • gets,直接读取一行,忽略’\x00’
      • scanf
      • vscanf
    • 输出:
      • sprintf
      • 字符串
      • strcpy,字符串复制,遇到’\x00’停止
      • strcat,字符串拼接,遇到’\x00’停止
      • bcopy
  • 确定填充长度
    这一部分主要是计算我们所要操作的地址与我们所要覆盖的地址的距离。常见的操作方法就是打开 IDA,根据其给定的地址计算偏移。一般变量会有以下几种索引模式

  • 相对于栈基地址的的索引,可以直接通过查看EBP相对偏移获得

  • 相对应栈顶指针的索引,一般需要进行调试,之后还是会转换到第一种类型。
  • 直接地址索引,就相当于直接给定了地址。

    一般来说,我们会有如下的覆盖要求

  • 覆盖函数返回地址,这时候就是直接看 EBP 即可。
    覆盖栈上某个变量的内容,这时候就需要更加精细的计算了。

  • 覆盖 bss 段某个变量的内容。
  • 根据现实执行情况,覆盖特定的变量或地址的内容。

参考网页:
http://www.cnblogs.com/pricks/p/3821832.html
https://ctf-wiki.github.io/ctf-wiki/pwn/stackoverflow/stackoverflow_basic/

猜你喜欢

转载自blog.csdn.net/lingyuexueai/article/details/81584496