栈溢出

Posted ying-hack

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈溢出相关的知识,希望对你有一定的参考价值。

栈溢出基础

C语言函数调用栈

  • 函数调用栈是指程序运行时内存一段连续的区域
  • 用来保存函数运行时的状态信息,包括函数参数与局部变量等
  • 称之为‘栈’是因为发生函数调用时,调用函数的状态被保存在栈内,被调用函数的状态被压入调用栈的栈顶
  • 在函数调用结束时,栈顶的函数状态被弹出,栈顶恢复到调用函数的状态
  • 函数调用栈在内存中从高地址向低地址生长,所以栈顶对应的内存地址在压栈时变小,退栈时变大。
  • 在这里插入图片描述在这里插入图片描述
  • stack frame pointer 是父函数的栈底的值。当ebp返回的时候会退到这个值上去。在本栈帧的ebp的上一个字长记录上一个栈帧的栈底指针的值。
  • 局部变量保存在栈帧的局部变量区,发生栈溢出的地方也是这里。
  • 子函数所用到的参数保存在父函数的arguments区域里面
    在ebp和esp中间是一个栈帧。紧邻高地址就是父函数的栈帧。

在这里插入图片描述

  • 函数状态主要涉及三个寄存器—esp,ebp,eip。
    • esp用来存储函数调用栈的栈顶地址,在压栈和退栈时发生变化。
    • ebp用来存储当前函数状态的基地址,在函数运行时不变,可以用来索引确定函数参数或局部变量的位置。
    • eip用来存储即将执行的程序指令的地址。cpu依照eip的存储内容读取指令并执行,eip随之指向相邻的下一指令,如此反复,程序就得以连续执行指令。
  • 发生函数调用时,栈顶函数状态以及上述寄存器的变化。变化的核心任务是将调用函数的状态保存起来,同时创建被调用函数的状态。
  • 首先将被调用函数的参数按照逆序依次压入栈内。如果被调用函数不需要参数,则没有这一步骤。这些参数仍会保存在调用函数的函数状态内,之后压入栈内的数据会作为被调用函数的函数状态保存起来。
  • 再将当前的ebp寄存器的值(也就是调用函数的基地址)压入栈内,并将ebp寄存器的值更新为当前栈顶的地址。这样调用函数的ebp(基地址)信息得以保存。同时,ebp被更新为被调用函数的基地址
  • 再然后是将被调用函数的局部变量等数据压入栈内

然后就可以执行函数

  • 弹栈,只需要将esp的值加大就可以,不删除内容。之后再用的时候直接覆盖原来的内容就行。
  • 首先将局部变量弹栈,esp-1字长
  • 将调用的函数的基地址弹栈,并将值保存在ebp寄存器中,esp-1字长
  • 再将返回地址弹出来保存到eip寄存器中,这样程序的eip信息得已恢复

ret2text

缓冲区溢出(Buffer overflow)
本质是向定长的缓冲区写入超长的数据,导致超长的数据复写了合法的内存区域。
- 栈溢出
-最常见,漏洞比率最高,危害最大的二进制漏洞
- 在CTF PWN中往往是漏洞利用的基础
- 堆溢出
- 现实中的漏洞占比不高
- 堆管理器复杂利用花样繁多
- CTF PWN中的常见题型
- BSS溢出
- 现实中与CTF比赛中占比都不高
- 攻击效果依赖于BSS上存放了何种控制数据
在这里插入图片描述开辟了一个8字节的缓冲区,但是输入16字节。会导致字符将return address覆盖达到控制执行流的操作

篡改程序的返回地址到已有的后门函数。(system("/bin/sh"))

适用范围:

程序中有后门函数,直接返回这个后门函数
可以控制执行流

ret2shellcode

  • 篡改栈帧上的返回地址为攻击者手动传入的shellcode所在缓冲区地址
  • 初期往往将shellcode直接写入栈缓冲区
  • 目前由于 the NX bits保护措施(把栈的可执行权限给禁掉)的开启,栈缓冲区不可执行。所有当先常用的手段变为向bss缓冲区写入shellcode或向堆缓冲区写入shellcode并使用mprotect赋予其可执行权限。

以上是关于栈溢出的主要内容,如果未能解决你的问题,请参考以下文章

在windows数据栈溢出,在linux系统就没有栈溢出,为啥

栈溢出的思考

构建ROP链实现远程栈溢出

五种内存溢出案例总结:涵盖栈深度溢出永久代内存溢出本地方法栈溢出JVM栈内存溢出和堆溢出

五种内存溢出案例总结:涵盖栈深度溢出永久代内存溢出本地方法栈溢出JVM栈内存溢出和堆溢出

C语言读取大量文件进行计算栈溢出怎么解决