解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。
尾递归,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。
扩展资料
针对堆栈溢出可能造成的计算机安全问题,通常有以下这些防范措施:
1、强制按照正确的规则写代码。
2、通过 *** 作系统使得缓冲区不可执行,从而阻止攻击者植入攻击代码。但由于攻击者并不一定要通过植入代码来实现攻击,同时linux在信号传递和GCC的在线重用都使用了可执行堆栈的属性,因此该方法依然有一定弱点。
3、利用编译器的边界检查来实现缓冲区的保护。该方法使得缓冲区溢出不可能出现,完全消除了缓冲区溢出的威胁,但代价较大,如性能速度变慢。
4、程序指针完整性检查,该方法能阻止绝大多数缓冲区溢出攻击。该方法就是说在程序使用指针之前,检查指针的内容是否发生了变化。
参考资料来源:百度百科-堆栈溢出
参考资料来源:百度百科-栈溢出
栈溢出指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,因而导致与其相邻的栈中的变量的值被改变。这种问题是一种特定的缓冲区溢出漏洞,类似的还有堆溢出,bss 段溢出等溢出方式。栈溢出漏洞轻则可以使程序崩溃,重则可以使攻击者控制程序执行流程。此外,我们也不难发现,发生栈溢出的基本前提是.
最典型的栈溢出利用是覆盖程序的返回地址为攻击者所控制的地址,当然 需要确保这个地址所在的段具有可执行权限 。
这个程序的主要目的读取一个字符串,并将其输出。 我们希望可以控制程序执行 success 函数。
因为 gets 是一个非常危险的函数,它从不检查输入字符串的长度,以回车判断输入是否结束.
gcc编译指令中, -m32 指的是生成32位程序, -fno-stack-protector 指的是不开启堆栈溢出保护,即不生成 canary。 -no-pie 避免加载基址被打乱.
2.IDA反编译
字符串s距离ebp的长度为0x14,所以栈结构s是
[外链图片转存失败(img-zPyIZk71-1564741311529)(../images/2018-12-10-16-30-04.png)]
而且我们可以可以获得 success 函数的返回地址为 08049192
所以我们输入的字符串就是 0x14*'a'+'bbbb'+success_addr .14个 a 覆盖了字符串数组,4个 b 覆盖ebp的地址,然后将 success 的地址覆盖到返回地址上.
通过交互成功实现了栈溢出
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)