一、栈溢出原理
什么是栈溢出?栈溢出就是缓冲区溢出的一种。 由于缓冲区溢出而使得有用的存储单元被改写,往往会引发不可预料的后果。程序在运行过程中,为了临时存取数据的需要,一般都要分配一些内存空间,通常称这些空间为缓冲区。如果向缓冲区中写入超过其本身长度的数据,以致于缓冲区无法容纳,就会造成缓冲区以外的存储单元被改写,这种现象就称为缓冲区溢出。缓冲区长度一般与用户自己定义的缓冲变量的类型有关。(PS:摘自百度百科)
简单来说,就是程序没有检查用户输入的数据长度,导致攻击者覆盖栈上不是程序希望写入的地方,比如说返回地址。(PS:本人是这么理解的,如有问题,还请斧正)
在x86中,对于调用一个函数,栈的变化如下:首先,将被调用的函数的参数从右到左依次压入栈中,然后将被调用的函数的返回地址压入栈中,然后跳转到被调用函数的地址去,在被调用的函数中,首先将ebp
(这时的ebp
是调用者的ebp
)压入栈中,最后,将此时的栈顶esp
赋值给ebp
寄存器(此时的ebp
便是被调用函数的栈底了)
以一个实际程序为例,源码如下所示:
对于进入test
函数后,栈的变化情况如下图所示:
接着利用gdb调试验证栈的情况如上图所示,首先在test
函数处打下断点,然后start
命令将程序运行到main
函数开头处,查看一下此时的ebp
寄存器的值和call test
指令后下一条指令的地址,这里可以看到此时ebp
寄存器的值为0xffffd1d8
,call test
指令后的下一条指令地址为0x565561f2
,如下图所示:
然后运行r
命令,进入test
函数内部,使用x
命令查看此时的栈情况,可以发现栈的情况如上图示意图一样,如下图所示:
在test
函数内部,有个ver
字符数组,在上面的源码中,我们对其进行了手动赋值,假如该数组通过strcpy
等函数完成赋值,并且赋值的字符串由用户输入,那么在用户输入的字符串超过12
个字节大小之后,ver
数组就会接着往高地址增长,在这其中,可以覆盖掉tes
支付5UD,阅读全文
还有更多的精彩内容,作者设置为付费后可见