一、基本概念
1.缓冲区:
缓冲区(buffer)这个中文译意源自当计算机的高速部件与低速部件通讯时,必须将高速部件的输出暂存到某处,以保证高速部件与低速部件相吻合. 后来这个意思被扩展了,成为”临时存贮区”的意思。 一般缓冲区用于跟外设接口,比如输入的键盘、输出到屏幕、输出到文件、串并口、 络等等,主要原因是CPU工作速度和总线传送速度远远快于这些外设的处理速度, 为了不让CPU处于长时间等待状态,通常采用中断方式来处理,但为了提高效率,减少中断的次数,cpu一次把能处理的一批数据传送给外设,然而外设又不能同步处理这些数据,这样就产生了缓冲区,cpu把数据送到缓冲区,外设到缓冲区取数据进行处理,用这种方式来保持cpu跟外设之间的数据交换。
正常情况下,cpu把数据送到缓冲区就认为要求的工作已经处理完了,至于缓冲区的数据什么时候真正被外设处理那是由系统和外设调度决定的,跟cpu处理肯定是不同步的。cpu可能已经处理到输出后好几条指令了,缓冲区里的数据还在处理。以缓冲方式打开一个文件时,往文件里写几个字节,一般不会立即真正把这几个字节写入文件,只有当缓冲区满时才真正写盘。如果想在缓冲区满之前写盘保存,可以做冲刷缓冲区动作。
但要是你的程序里有强制刷新缓冲指令,那cpu就要等缓冲区里数据真正被外设处理完才执行下一条指令。
2.缓冲区溢出
缓冲区溢出是一种非常普遍、非常危险的漏洞,在各种操作系统、应用软件中广泛存在。利用缓冲区溢出攻击,可以导致程序运行失败、系统宕机、重新启动等后果。更为严重的是,可以利用它执行非授权执行,甚至可以取得系统特权,进行各种非法操作。缓冲区溢出(buffer overflow),是针对程序设计缺陷,向程序输入缓冲区写入使之溢出的内容(通常是超过缓冲区能保存的最大数据量的数据),从而破坏程序运行、趁著中断之际并获取程序乃至系统的控制权。
缓冲区在系统中的表现形式是多样的,高级语言定义的变量、数组、结构体等在运行时可以说都是保存在缓冲区内的,因此所谓缓冲区可以更抽象地理解为一段可读写的内存区域,缓冲区攻击的最终目的就是希望系统能执行这块可读写内存中已经被蓄意设定好的恶意代码。按照冯·诺依曼存储程序原理,程序代码是作为二进制数据存储在内存的,同样程序的数据也在内存中,因此直接从内存的二进制形式上是无法区分哪些是数据哪些是代码的,这也为缓冲区溢出攻击提供了可能。
运行程序:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PZ5TcptJ-1649239957733)(https://raw.githubusercontent.com/lmy12367/img/main/imgwpsE75E.tmp.jpg)]
根据程序的运行结果得知:fun函数的入口是0x006E10B4
在main函数中的 overflow(input); 与 overflow 函数中的 strcpy(buf,input); 处打上断点,重新运行程序。
进入反汇编界面查看overflow函数的地址:
缓冲区溢出攻击成功
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ucQVVy3y-1649239957735)(https://raw.githubusercontent.com/lmy12367/img/main/imgwps2D7A.tmp.jpg)]
六、防止缓冲区溢出的方法
**1.**基于探测方法的防御
研究人员 Crispen Cowan 创建了一个称为 StackGuard 的有趣方法。Stackguard 修改 C 编译器(gcc),以便将一个“探测”值插入到返回地址的前面。“探测仪”就像煤矿中的探测仪:它在某个地方出故障时发出警告。在任何函数返回之前,它执 行检查以确保探测值没有改变。如果攻击者改写返回地址(作为 stack-smashing 攻击的一部分),探测仪的值或许就会改变,系统内就会相应地中止。这是一种有用的方法,不过要注意这种方法无法防止缓冲区溢出改写其他值(攻击者仍然能够 利用这些值来攻击系统)。人们也曾扩展这种方法来保护其他值(比如堆上的值)。Stackguard(以及其他防御措施)由 Immunix 所使用。
IBM 的 stack-smashing 保护程序(ssp,起初名为 ProPolice)是 StackGuard 的方法的一种变化形式。像 StackGuard 一样,ssp 使用一个修改过的编译器在函数调用中插入一个探测仪以检测堆栈溢出。然而,它给这种基本的思路添加了一些有趣的变化。 它对存储局部变量的位置进行重新排序,并复制函数参数中的指针,以便它们也在任何数组之前。这样增强了ssp 的保护能力;它意味着缓冲区溢出不会修改指针值(否则能够控制指针的攻击者就能使用指针来控制程序保存数据的位置)。默认情况下,它不会检测所有函数,而 只是检测确实需要保护的函数(主要是使用字符数组的函数)。从理论上讲,这样会稍微削弱保护能力,但是这种默认行为改进了性能,同时仍然能够防止大多数问 题。考虑到实用的因素,它们以独立于体系结构的方式使用 gcc 来实现它们的方法,从而使其更易于运用。从 2003 年 5 月的发布版本开始,广受赞誉的 OpenBSD(它重点关注安全性)在他们的整个发行套件中使用了 ssp(也称为 ProPolice)。
**2.**非执行的堆栈防御
另一种方法首先使得在堆栈上执行代码变得不可能。 遗憾的是,x86 处理器(最常见的处理器)的内存保护机制无法容易地支持这点;通常,如果一个内存页是可读的,它就是可执行的。一个名叫 Solar Designer 的开发人员想出了一种内核和处理器机制的聪明组合,为 Linux 内核创建了一个“非执行的堆栈补丁”;有了这个补丁,堆栈上的程序就不再能够像通常的那样在 x86 上运行。 事实证明在有些情况下,可执行程序 需要在 堆栈上;这包括信 处理和跳板代码(trampoline)处理。trampoline 是有时由编译器(比如 GNAT Ada 编译器)生成的奇妙结构,用以支持像嵌套子例程之类的结构。Solar Designer 还解决了如何在防止攻击的同时使这些特殊情况不受影响的问题。
七、实验结果分析
在栈内的空间中,本来的main函数调用了overflow函数之后,在该函数执行完成之后本来是要返回到main里面overflow函数的下一行的,但是我们在函数中的将数据写入数组的时候通过计算输入和填充了过长的数据,并让我们输入的数据过长而超出的部分覆盖和替换了原来的overflow执行完成之后要返回的地址,导致了流程的转移,也就是实施了缓冲区溢出攻击。这个流程的转移是overflow 函数执行完毕之后程序跳转到了原本没有被执行的fun 函数的入口地址。执行完 fun 函数之后,栈空间中下面的地址已乱,因而出错。缓冲区攻击成功。
八、实验心得
第一次做实验关于缓冲区溢出攻击,还是有很多不懂的地方,参考了学姐的实验步骤,按照步骤一步一步来的;但是我觉得这个东西特别吸引我,不断钻研奋斗,下学期继续选张老师的课学这些内容。
、实验心得**
第一次做实验关于缓冲区溢出攻击,还是有很多不懂的地方,参考了学姐的实验步骤,按照步骤一步一步来的;但是我觉得这个东西特别吸引我,不断钻研奋斗,下学期继续选张老师的课学这些内容。
我们应该已经了解了缓冲区溢出漏洞的原理,它就是因为我们输入了过长的字符,而缓冲区本身又没有有效的验证机制,导致过长的字符将返回地址覆盖掉了,当我们的函数需要返回的时候,由于此时的返回地址是一个无效地址,因此导致程序出错。那么依据这个原理,假设我们所覆盖的返回地址是一个有效地址,而在该地址处又包含着有效的指令,那么我们的系统就会毫不犹豫地跳到该地址处去执行指令。因此,如果想利用缓冲区溢出的漏洞,我们就可以构造出一个有效地址出来,然后将我们想让计算机执行的代码写入该地址,这样一来,我们就通过程序的漏洞,让计算机执行了我们自己编写的程序。以上是我通过这个实验的理解,如果不正确,下学期的课程在和老师进行讨论。
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!