动态调试方法:深入理解堆栈和堆栈溢出原理

示例环境:

  • 操作系统:Windows 7 Professional Service Pack 1
  • 编译器:VC++ 6.0

目的:

掌握动态调试方法,理解函数调用过程中堆栈和关键寄存器的变化以及堆栈溢出原理。

重点:

  • 堆栈的概念

'堆栈' 是一个在计算机科学中经常使用的抽象数据类型。堆栈中的物体具有一个特性:最后一个放入堆栈中的物体总是被最先拿出来,这个特性通常称为后进先处 (LIFO) 队列。堆栈中定义了一些操作,两个最重要的是 PUSH 和 POP。PUSH 操作在堆栈的顶部加入一个元素。POP 操作相反,在堆栈顶部移去一个元素,并将堆栈的大小减一。

  • 堆栈缓冲区溢出原理

函数调用时,返回地址存放在堆栈中,局部变量也存放在堆栈中;如果局部变量中有一个字符数组,并且该程序使用了危险的函数来操纵该字符数组,那么就可以通过向该程序传递超长的字符串来使得该字符数组'溢出',从而达到覆盖返回地址、执行恶意代码的目的。

  • 防范措施:
  1. 引入新的安全的函数,取代旧的、有缺陷的函数。较新的 c 库中都带有 strncpy, fgets, sscanf 等函数。
  2. 插入保护码,这些保护码被称为'金丝雀'。某些程序包可以与编译器配套使用,在返回地址与局部变量之间插入一些保护代码,导致入侵者在覆盖返回地址的时候,首先覆盖了保护代码。程序运行时会检测这些保护码,如果这些代码被改变,程序就会马上终止。检测保护码的代码是编译器加进去的,程序员无需为此操心。
  3. 真正有威胁的攻击来自 shell2 code,但 shell2code 通常要求在堆栈中植入一段代码并执行,这就需要堆栈是可执行的。一些操作系统 (如新版的 Solaris) 可以将堆栈设置为不可执行的。Intel 的 Itanium 处理器采用了一种与众不同的途径来避免基于堆栈的缓冲区溢出攻击,即为返回地址设置了一个寄存器,使返回地址不再放到堆栈中,所以无论如何溢出,也不会影响返回地址的值。

原文地址: https://www.cveoy.top/t/topic/nWU7 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录