如何解决栈溢出

如何解决栈溢出,第1张

解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。

尾递归,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

扩展资料

针对堆栈溢出可能造成的计算机安全问题,通常有以下这些防范措施:

1、强制按照正确的规则写代码。

2、通过 *** 作系统使得缓冲区不可执行,从而阻止攻击者植入攻击代码。但由于攻击者并不一定要通过植入代码来实现攻击,同时linux在信号传递和GCC的在线重用都使用了可执行堆栈的属性,因此该方法依然有一定弱点。

3、利用编译器的边界检查来实现缓冲区的保护。该方法使得缓冲区溢出不可能出现,完全消除了缓冲区溢出的威胁,但代价较大,如性能速度变慢。

4、程序指针完整性检查,该方法能阻止绝大多数缓冲区溢出攻击。该方法就是说在程序使用指针之前,检查指针的内容是否发生了变化。

参考资料来源:百度百科-堆栈溢出

参考资料来源:百度百科-栈溢出

栈溢出漏洞是由于使用了不安全的函数,如 C 中的 scanf, strcpy等,通过构造特定的数据使得栈溢出,从而导致程序的执行流程被控制。

要分析栈溢出漏洞,我们要先了解函数栈帧的结构。

在 C 函数中,每个函数都有一个栈帧,它用来保存这个函数的参数、局部变量、返回地址等信息,是系统栈的一部分。

假设有这样一个函数:

void foo(char *arg1, char *arg2) { int temp = 0char buffer[4]strcpy(buffer, arg1)}

这个函数的栈帧是这样的:

ESP 称为栈顶指针,用来指示当前栈帧的顶部

EBP 称为栈基址指针,用来指示当前栈帧的底部

在调用这个函数时,压栈的顺序为:

由于局部变量 buffer 的长度是 4 个字节,而在使用 strcpy 函数的时候并没有判断参数 arg1 的长度,因此,当传入的 arg1 的长度大于 4 个字节时,多出的字节将会依次覆盖掉局部变量 temp、调用者的 EBP、返回地址等。

通过精心构造 arg1 的值,就可以将返回地址覆盖为任意想要的值,以便于跳到 shellcode

可以将 shellcode 保存在 buffer 中,并将返回地址覆盖为 buffer 的起始地址,如图:

<br />

此外,我们可以采取相对移位的方法,如图:

在很多情况下,要精确定位 buffer 的起始位置是很难的,我们可以采用增大 “落点” 的面积的方式来增加命中的几率,具体做法是使用 nop 填充 buffer,如果落点在 nop,那么系统会一直往下执行直到遇到 shellcode

如果函数返回地址的偏移按 DWORD 不定,可以用一片连续的跳转指令地址来覆盖函数返回地址,如图:

在函数返回时,esp 总是指向返回地址的下一个位置,所以,我们可以通过覆盖多一些栈帧,将 shellcode 写到返回地址之后的位置,并通过跳板指令重新回到栈中,如图:

那么,到哪儿去找跳板指令呢?在早期的 Windows 版本的动态链接库中,存在大量的 jmp esp 指令,而这些库在内存中的地址是相对固定的,如Win2000、XP、Win2003 的 0x7ffa4512

<br />

参考资料:

x86函数调用堆栈的 *** 作

《0day安全 软件漏洞分析技术》


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/8662430.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-19
下一篇 2023-04-19

发表评论

登录后才能评论

评论列表(0条)

保存