编程中的堆栈溢出和缓冲区溢出有什么区别?
10 回答
堆栈溢出专门指执行堆栈增长超出为其保留的内存的情况。例如,如果您调用一个函数,该函数在没有终止的情况下递归调用自身,您将导致堆栈溢出,因为每个函数调用都会创建一个新的堆栈帧,并且堆栈最终会消耗比为其保留的内存更多的内存。
缓冲区溢出是指程序写入超出为任何缓冲区分配的内存末尾的任何情况(包括在堆上,而不仅仅是在堆栈上)。例如,如果你写超出了从堆中分配的数组的末尾,就会导致缓冲区溢出。
关键区别在于知道堆栈和缓冲区之间的区别。
堆栈是为正在执行的程序保留的空间。当你调用一个函数时,它的参数和返回信息都放在堆栈上。
缓冲区是用于单一目的的通用内存块。例如,一个字符串就是一个缓冲区。它可以通过向字符串写入比分配更多的数据来运行。
堆栈溢出:对于分配给当前线程的内存,你在堆栈上放了太多东西
缓冲区溢出:您已超出当前分配的缓冲区的大小,并且尚未调整其大小以适应(或无法进一步调整其大小)。
堆栈溢出是指线程的堆栈大小超过该线程允许的最大堆栈大小。
缓冲区溢出是指将值写入程序当前未分配的内存中。
你不是想说“堆栈和缓冲区有什么区别吗?” ——这将使您更快地获得更多洞察力。一旦你做到了这一点,你就可以考虑溢出这些东西意味着什么。
缓冲区溢出通常代表任何时候内存缓冲区被访问超出其边界,无论是堆栈还是堆。堆栈溢出意味着堆栈已超出其分配的限制,并且在大多数机器/操作系统上都在堆上运行。
1. 基于堆栈的缓冲区溢出
• 当程序在预期数据结构(固定长度缓冲区)之外的程序调用堆栈上写入内存地址时发生。• 基于堆栈编程的特点 1. “堆栈”是分配自动变量的内存空间。2、函数参数是在栈上分配的,不会被系统自动初始化,所以在初始化之前都有垃圾。3. 一旦函数完成其循环,对堆栈中变量的引用将被删除。(即,如果函数被多次调用,则每次调用和退出函数时都会重新创建和销毁其局部变量和参数。)
• 攻击者利用基于堆栈的缓冲区溢出,通过覆盖以各种方式操纵程序
1. 靠近堆栈内存中缓冲区的局部变量,用于更改可能有利于攻击者的程序行为。
2. 返回栈帧中的地址。一旦函数返回,执行将在攻击者指定的返回地址处恢复,通常是用户输入填充的缓冲区。3. 随后执行的函数指针或异常处理程序。• 克服漏洞利用的因素是
1. 地址中的空字节 2. shell 代码位置的可变性 3. 环境之间的差异 Shell 代码是用于利用软件漏洞的一小段代码。
2. 堆缓冲区溢出
• 发生在堆数据区。• 当应用程序将更多数据复制到缓冲区中时,会发生溢出,该缓冲区超出了缓冲区的设计容量。• 如果将数据复制到缓冲区而不首先验证源是否适合目标,则很容易被利用。• 基于堆栈和基于堆的编程的特点: • “堆”是一个“空闲存储”,即分配动态对象时的内存空间。• 堆是动态分配的内存空间 new()、malloc() 和 calloc() 函数。• 动态创建的变量(即声明的变量)在执行前在堆上创建并存储在内存中,直到对象的生命周期完成。• 执行利用 • 通过破坏数据来覆盖内部结构,例如链表指针。• 指针交换以覆盖程序功能
大多数提到缓冲区溢出的人意味着堆栈溢出。但是,溢出可能发生在任何区域,而不仅限于堆栈。比如堆或者bss。堆栈溢出仅限于覆盖堆栈上的返回地址,但不覆盖返回地址的正常溢出可能只会覆盖其他局部变量。