汇编语言简易教程(13):栈缓存溢出
标签:13,缓存,函数,汇编语言,程序,寄存器,堆栈,溢出 From: https://www.cnblogs.com/pDJJq/p/18134103/simple-tutorial-of-assembly-language-13-stack-cac当程序溢出基于堆栈的动态变量时,可能会发生堆栈缓冲区溢出。 例如,如果一个程序分配并使用一个基于堆栈的本地数组,该数组包含 50 个元素,并且数组中存储了 50 个以上的元素,则会发生溢出。 这种溢出通常是坏的,通常会导致程序错误,甚至可能使程序崩溃。
堆栈将包含其他重要信息,例如其他变量、保留的寄存器、帧指针、返回地址和/或基于堆栈的参数。 如果此类数据被覆盖,则可能会导致难以调试的问题,因为症状可能与问题实际发生的位置无关.
什么是栈缓存溢出
什么是栈缓存溢出
当程序调用函数时,标准调用约定为如何传递参数、如何保存返回地址、如何保留寄存器以及必须保留哪些寄存器以及如何分配基于堆栈的局部变量提供了指导
例如:
expFunc(arg1, arg2, arg3)
此外,我们将假设函数 expFunc() 从用户那里读取一行文本并将其存储在本地声明的数组中。 局部变量包括 48 字节的数组和一个四字局部变量(8 字节)。 这可以用高级语言轻松完成,也可以像“系统服务”, 控制台输入中那样完成.
栈帧分布如上.
当函数完成时,调用帧的所有元素都会被移除。保存的寄存器会恢复到它们原来的内容,局部变量会被移除,返回地址会从栈中复制出来并放入rip寄存器中,这会导致跳回到原始的调用例程。如第12章“函数”所述,这种布局支持多级函数调用,包括递归。
在第13章的示例中,读取用户输入的字符并将它们输入到数组中时,明确检查了字符计数以确保计数不会超过缓冲区大小。很容易忘记执行这个重要的检查。确实,一些C函数,如strcpy(),不执行尺寸验证,因此被认为是不安全的,或被描述为一个不安全的函数。
在这个例子中,覆写48字符的缓冲区将破坏栈的内容,这个栈包含了rbp寄存器的原始值,可能还包括rip寄存器。如果rip寄存器的原始值的栈内容以任何方式被修改或损坏,函数将无法返回到调用例程,并会尝试跳转到某个随机位置。如果随机位置在程序范围之外,这是很可能的,程序将生成一个段错误(即“段错误”或程序崩溃)。
调试这种类型的错误可能是一个重大挑战。错误出现在函数的最后(在返回时)。问题实际上出现在函数的主体中,事实上可能是由于没有包括的代码(与存在的错误代码相对)。
测试程序是否存在这种漏洞将涉及在提示输入时输入远远超出预期的字符。例如,如果提示输入名称,输入200个字符(可能是通过按住一个键),程序崩溃将是这种漏洞存在的迹象。错误消息将表明这种漏洞不存在。虽然直接,但这种类型的测试经常没有被彻底检查,甚至完全被省略。