用到的基础概念:
栈:
概念:
各式各类的代码在被编译后会形成一个二进制文件,代码中的主程序和被调用的函数在这个文件中并不是连续存储的,但指令却是从主程序的开始一条指令一条指令执行到结束,当主程序在执行到要调用其他地址上的函数时,为了深入些理解栈,我们需要思考几个问题:
- 主程序是怎么调用的这些函数的?
- 当调用结束时,如何返回当前位置继续运行接下来的指令?
- 如何将参数传递给将要运行函数?
栈的作用是存储一些暂时用不上,但之后一定会用到的数据。
(1)答:如下图,利用call指令,call这些函数的地址。数据中的E8是call指令的对应编码。
(2)答:call指令执行时,会形成一个栈块,把当前EIP寄存器(本文寄存器标题中有解释,不明白其功能的可以看一下)中存储的地址压入这个栈块中,然后将call指令中的地址交给EIP寄存器,当函数中的指令运行结束时,把栈中的之前压入的EIP地址再弹回给EIP寄存器,实现call指令运行结束后回归主函数继续运算并且放弃当前的栈块,实现这个功能的指令叫做ret,该指令是和call指令配套使用的。
(3)答:在call指令之前,根据使用的调用约定,把要用到的参数按约定顺序压入栈,之后在函数中,利用ESP或者EBP寄存器和参数之间的距离,来获取这个或这些参数。
栈块:
为了方便文章理解,我改一改栈块的概念,不适用于平时理解
在主程序每一次调用函数后,之前的ebp寄存器中的值会被压入栈,此时esp寄存器中的值会交给ebp,然后esp寄存器中的的地址要和ebp中的地址拉开一块差距,两个地址中的差距空间,就是用来存储数据的栈空间了。
每一个函数都会产生这样的栈空间,所以我们姑且把每个函数所产生的的栈空间称为一个栈块吧
寄存器:
EIP:存储接下来要运行指令的地址
ESP:存储当前栈最顶的地址
EBP:储存当前栈块,栈底的地址(当前栈块定义为:一次完整的函数调用生成的栈空间)
栈溢出:
栈溢出是利用程序对于栈的管理不严格实现攻击方式。
原理:
栈是用于存储数据的容器,也是代码注入的点。我们可以利用压入栈块的数据,超出栈块长度的数据接下来覆盖的就是
(未完待续)