栈溢出的思考

Posted

tags:

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

一、系统栈的工作原理

  进程所使用的内存按照功能可以划分为一下4部分:

  1.代码区:代码区用于存放待执行的二进制指令。处理器会到代码区取指令并执行。

  2.数据区:用于存储全局变量。

  3.堆区:堆区为进程分配动态申请的内存,进程在使用之后需要归还。动态分配和回收是堆区的特点。

  4.栈区:用于动态的存储函数之间的调用关系,以保证地子函数执行之后可以继续执行函数。栈区除了存放函数之间的调用关系之外也存放局部变量。

技术分享

 

  栈在计算机科学中是一种数据结构,一种先进后出的数据表;栈最常用的操作时入栈和出栈;栈的标识有两个栈顶和栈底。内存的栈就是系统栈,由操作系统维护。

 

  寄存器和函数栈帧:

   每一个函数都有自己的栈帧空间,称作函数栈。windows32系统中用两个特殊的寄存器来标识系统栈顶端的栈帧。

   ESP: 栈指针寄存器(extended stack pointer),该寄存器中存放一个指针,始终指向系统栈最上面的栈帧的栈顶,也就是当前执行的函数的栈帧顶部。

   EBP: 基址指针寄存器(extended base pointer),该寄存器中存放着一个指针,始终指向系统栈最上部一个栈帧的栈底,即当前函数栈的栈帧底部。

  函数栈帧:ESP和EBP之间的内存空间为当前栈帧,EBP为当前函数栈帧的栈底,ESP为当前函数栈帧的栈顶。

  函数栈中存放的信息:

   (1)局部变量: 为函数局部变量开辟的空间

   (2)栈帧状态值:保存上一个栈帧的信息(顶部和底部,实际上,只保存底部信息,前栈帧的顶部信息可以通过栈帧平衡得到),用于在当前栈帧出栈后恢复上一个栈帧。

   (3)函数返回地址:用于存储函数调用前的指令的位置,便于在函数返回后恢复到之前的代码区中继续执行指令。


  EIP: 指令寄存器(Extended Instruction Pointer),用于存放下一条待执行的指令地址。


 函数调用约定与相关指令

  函数调用过程中,参数入栈顺序和函数返回时恢复栈平衡的位置因不同的操作系统,不同的语言而异,所以需要仔细的去了解。在这里只讨论c语言基于windows平台的参数入栈顺序。

  函数调用的步骤:

   (1)参数入栈

   (2)返回地址入栈

   (3)代码区跳转

   (4)栈帧调整(保存当前栈帧的状态;将当前栈帧切换到新栈帧,即将ESP值装入EBP;给新栈帧分配空间)


  函数返回的步骤:

   (1)保存返回值,通常保存在寄存器EAX中;

   (2)弹出当前栈帧,恢复上一个栈帧;

   (3)跳转。


二、利用栈的状况来搞点事

  看过系统栈的空间分布之后,不由得引发我的思考:倘若正在运行的函数栈中的局部变量的值是从外部输入的,那么输入的数据会不会影响栈中其他的数据?会导致程序怎样的行为?于是,我在书中了解到了一下信息,通过栈溢出,可以实现以下功能:

  1.修改邻接变量的值;

  2.修改返回地址;


修改临邻接变量的原理:

  函数的局部变量在栈中一般是相邻排列的,如果这些局部变量中有数组之类的缓冲区,并且程序存在数组越界的缺陷,那么越界的数组元素就有可能破坏栈中相邻变量的值,甚至破坏栈中EBP的值、返回地址等重要数据。

  ps://函数的局部变量在函数栈中国到底是如何排列的需要通过动态调试来确定。

修改返回地址的原理:

  在上边已经提到,对存在缓冲区溢出的程序进行攻击可能破坏栈中EBP的值、返回地址,当然也可以精心的设计EBP和返回地址中的值,使得程序按照我们的想法来执行。修改返回地址也就是覆盖返回地址中的值,使得程序按照我们的想法来执行,即使程序返回到我们指定的位置来执行。


  在上面提到可以是程序跳转到我们指定的位置去执行,所以说,我们可以在缓冲区中写入待执行的二进制代码,来让程序执行我们写入的代码,即代码注入。这种代码被称作shellcode。


  由于函数栈中保存的数据只有之前函数执行的状态和变量的数据信息,所以,我们能做的也就只有改变变量的值和之前函数的执行状态两件事。在兴奋的时候,居然想起来了操作系统有栈保护的机制,那么,我要如何突破关卡,成功的实现栈溢出呢?同一个程序在不同过的操作系统上地址是不是相同呢?要是不相同,用于修改之前函数执行状态的数据应该怎样写才能实现通用性?shellcode应该如何被精确的定位?大型程序使用动态链接库后,地址是否还能保持相同?忽然发现,我高兴的太早了,真真正正的栈溢出还没有正式开始,所以,关于栈溢出的讨论就先到这里,后续会持续更新。

  在最后,推荐几本书给喜欢抓虫的大大们:

   《深入理解计算机操作系统》

   《0day安全:软件漏洞分析技术》

本文出自 “execute” 博客,请务必保留此出处http://executer.blog.51cto.com/10404661/1775755

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

栈溢出原理

FreeRTOS操作系统例程:任务栈溢出检测

递归调用太深,可能导致栈溢出

如何解决栈溢出

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

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