解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。
尾递归,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。
扩展资料
针对堆栈溢出可能造成的计算机安全问题,通常有以下这些防范措施:
1、强制按照正确的规则写代码。
2、通过 *** 作系统使得缓冲区不可执行,从而阻止攻击者植入攻击代码。但由于攻击者并不一定要通过植入代码来实现攻击,同时linux在信号传递和GCC的在线重用都使用了可执行堆栈的属性,因此该方法依然有一定弱点。
3、利用编译器的边界检查来实现缓冲区的保护。该方法使得缓冲区溢出不可能出现,完全消除了缓冲区溢出的威胁,但代价较大,如性能速度变慢。
4、程序指针完整性检查,该方法能阻止绝大多数缓冲区溢出攻击。该方法就是说在程序使用指针之前,检查指针的内容是否发生了变化。
参考资料来源:百度百科-堆栈溢出
参考资料来源:百度百科-栈溢出
栈溢出保护及整数保护
说点什么
之前觉得学习原理很没有用,不如实践去执行
原理很多、很杂,很没用
真正去做时发现,原理是能做、不能做
从根本上指导实践,减少100%的试错时间
知行合一...
Canary原理
Canary是在栈的尾部插入值,函数返回时检测canary是否改变,判断是否溢出
利用gcc编译:
gcc ... -fstack-protector
如果Canary检查到,会调用__stack_chk_failed函数
绕过:
绕过方法1
至少利用两次栈溢出,才可以使用绕过方法1
V3后代表开启canary,所以v3是canary字节
第一次打印canary,第二次利用
buf距离ebp,10C个字节,v3距离ebp,C个字节,所以buf为100个字节
gdb:
dias main
disas vuln
这几个指令代表是有canary,
gdb可以创建随机字符
检测到栈溢出
利用gdb调试
可以看到,canary的末尾值为00
可以看到,ebp-0xC即为canary值,
0xffc66a68就是ebp的值,
0x08048695就是返回地址,所以canary后要有3个字节才是返回地址
sendline函数会添加回车再发送,所以是0x101个字符
收到的4个字符就是canary,减去回车 0xa就是canary。
注意:回车会导致多输入一个字符
Canary会随机变化,但是fork的函数中canary可以进行爆破
绕过方法2
调用多次的canary值和父进程完全一样,因此可以爆破
先填充0x100个字节,接上cannary值,canary4个字节,所以最后1字节是0x00,前三个字节进行爆破,如果接收到被篡改那么输出信息
绕过方法3
修改该函数的got表即可
最多溢出到canary,不能覆盖到ebp与ret地址,所以要利用格式化字符串漏洞,将getshell函数转换到chk_fail函数的got表,使得栈溢出触发getshell函数。
格式化字符串三点:改写的地址,写入的值,格式化字符串是第几个参数
chk_fail函数之前没调用过,所以是plt的第二条指令
get_shel高字节与chk_fail相同,因此只需要改低字节
%%%dc实现输出addr-4个字符, addr-4是因为stack_chk_fail先输出,是4个字节
最后将前面参数对应的数字,写入到第7个参数(buf对应第几个)对应的地址
绕过方法4
v4:buf大小是0x100
IO_gets就是gets,不限长度输入,以0字符截断,将flag地址进行覆盖
注意:本地的flag内容与远程的flag不相同!
找到chk_fail函数的argv[0]与flag地址的偏移,才能覆盖
64位因此参数传递是通过寄存器,rdi,rsi,rdx,rcx,r8,r9
ELF文件如果较小,会有多重映射
因此用find命令寻找字符串与地址
找到初始地址,0x400d20,也就是要修改的地址
0x218是地址偏移,当执行stack_chk_fail时,就会把new_flag_addr的值输出出来
绕过方法5
canary初始值就是TLS结构中stack_guard,
修改stack_guard就可以绕过canary
输入远大于 char s 数组,可以溢出
gdb中如果没有 符号表(striped),调试不方便 ,但是可以结合IDA与gdb进行调试
栈离TLS距离较近,则可以溢出
所以填充(TLScanary地址 - buf起始地址)的无用值
注意溢出时也会有canary,这个canary也要修改成一样的
这道题没有现成getshell,因此需要第一遍获取system地址,第二遍执行/bin/sh
利用read函数读入system函数,产生栈偏移到data段直接执行system函数,再构造read链,
read函数3个参数,因此填充
pop_rdi_ret能够传递参数
leave指令将rbp移动到rsp,因此栈会偏移
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)