软件安全实验二

一、基本概念

1.缓冲区:

缓冲区(buffer)这个中文译意源自当计算机的高速部件与低速部件通讯时,必须将高速部件的输出暂存到某处,以保证高速部件与低速部件相吻合. 后来这个意思被扩展了,成为"临时存贮区"的意思。 一般缓冲区用于跟外设接口,比如输入的键盘、输出到屏幕、输出到文件、串并口、网络等等,主要原因是CPU工作速度和总线传送速度远远快于这些外设的处理速度, 为了不让CPU处于长时间等待状态,通常采用中断方式来处理,但为了提高效率,减少中断的次数,cpu一次把能处理的一批数据传送给外设,然而外设又不能同步处理这些数据,这样就产生了缓冲区,cpu把数据送到缓冲区,外设到缓冲区取数据进行处理,用这种方式来保持cpu跟外设之间的数据交换。

正常情况下,cpu把数据送到缓冲区就认为要求的工作已经处理完了,至于缓冲区的数据什么时候真正被外设处理那是由系统和外设调度决定的,跟cpu处理肯定是不同步的。cpu可能已经处理到输出后好几条指令了,缓冲区里的数据还在处理。以缓冲方式打开一个文件时,往文件里写几个字节,一般不会立即真正把这几个字节写入文件,只有当缓冲区满时才真正写盘。如果想在缓冲区满之前写盘保存,可以做冲刷缓冲区动作。

但要是你的程序里有强制刷新缓冲指令,那cpu就要等缓冲区里数据真正被外设处理完才执行下一条指令。

2.缓冲区溢出

缓冲区溢出是一种非常普遍、非常危险的漏洞,在各种操作系统、应用软件中广泛存在。利用缓冲区溢出攻击,可以导致程序运行失败、系统宕机、重新启动等后果。更为严重的是,可以利用它执行非授权执行,甚至可以取得系统特权,进行各种非法操作。缓冲区溢出(buffer overflow),是针对程序设计缺陷,向程序输入缓冲区写入使之溢出的内容(通常是超过缓冲区能保存的最大数据量的数据),从而破坏程序运行、趁著中断之际并获取程序乃至系统的控制权。

缓冲区在系统中的表现形式是多样的,高级语言定义的变量、数组、结构体等在运行时可以说都是保存在缓冲区内的,因此所谓缓冲区可以更抽象地理解为一段可读写的内存区域,缓冲区攻击的最终目的就是希望系统能执行这块可读写内存中已经被蓄意设定好的恶意代码。按照冯·诺依曼存储程序原理,程序代码是作为二进制数据存储在内存的,同样程序的数据也在内存中,因此直接从内存的二进制形式上是无法区分哪些是数据哪些是代码的,这也为缓冲区溢出攻击提供了可能。

img

进程地址空间分布的简单表示。代码存储了用户程序的所有可执行代码,在程序正常执行的情况下,程序计数器(PC指针)只会在代码段和操作系统地址空间(内核态)内寻址。数据段内存储了用户程序的全局变量,文字池等。栈空间存储了用户程序的函数栈帧(包括参数、局部数据等),实现函数调用机制,它的数据增长方向是低地址方向。堆空间存储了程序运行时动态申请的内存数据等,数据增长方向是高地址方向。除了代码段和受操作系统保护的数据区域,其他的内存区域都可能作为缓冲区,因此缓冲区溢出的位置可能在数据段,也可能在堆、栈段。如果程序的代码有软件漏洞,恶意程序会“教唆”程序计数器从上述缓冲区内取指,执行恶意程序提供的数据代码!

二、实验内容

缓冲区溢出是指当计算机向缓冲区内填充数据位数时超过了缓冲区本身的容量溢出的数据覆盖在合法数据上,理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符,但是绝大多数程序都会假设数据长度总是与所分配的储存空间想匹配,这就为缓冲区溢出埋下隐患操作系统所使用的缓冲区又被称为"堆栈". 在各个操作进程之间,指令会被临时储存在“堆栈”当中,"堆栈"也会出现缓冲区溢出。

通过往程序的缓冲区写超出其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈,使程序转而执行其它指令,以达到攻击的目的。造成缓冲区溢出的原因是程序中没有仔细检查用户输入的参数

三、实验目的

**1.**编程验证缓冲区溢出出现的异常

**2.**缓冲区溢出导致控制流程转移

四、实验环境

*Windows*

*vs2019*

五、实验步骤

根据实验目的编写源代码,在vs2019中进行运行调试:

img

运行程序:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PZ5TcptJ-1649239957733)(https://raw.githubusercontent.com/lmy12367/img/main/imgwpsE75E.tmp.jpg)]

根据程序的运行结果得知:fun函数的入口是0x006E10B4

在main函数中的 overflow(input); 与 overflow 函数中的 strcpy(buf,input); 处打上断点,重新运行程序。

img

在 main 函数中的 overflow(input); 处暂停,打开反汇编窗口,可以看到 main 函数执行时的汇编语言与逻辑地址。

img

进入反汇编界面查看overflow函数的地址:

img

图中006E1A4B call overflow (06E128Ah)一句是overflow的开始语句,紧接着的下一句便是 overflow 函数执行结束之后返回 main 函数继续运行的语句,因此,在 overflow 执行时的堆栈中,函数执行完毕之后的返回地址为:006E1A4B。

继续运行到Strcpy_s的地方,在 overflow 函数中的 strcpy(buf,input); 处暂停,打开内存,在 地址中输入 buf (overflow 中的缓冲区)进行搜索,得到此时栈空间中 buf 的地址与数据。

img

img

修改源代码进行缓冲区溢出攻击

修改源代码中input的值,使修改后的字符串共24个字节,且末尾4个字节是fun函数的入口地址

img

缓冲区溢出攻击成功

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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 函数之后,栈空间中下面的地址已乱,因而出错。缓冲区攻击成功。

八、实验心得

第一次做实验关于缓冲区溢出攻击,还是有很多不懂的地方,参考了学姐的实验步骤,按照步骤一步一步来的;但是我觉得这个东西特别吸引我,不断钻研奋斗,下学期继续选张老师的课学这些内容。

、实验心得**

第一次做实验关于缓冲区溢出攻击,还是有很多不懂的地方,参考了学姐的实验步骤,按照步骤一步一步来的;但是我觉得这个东西特别吸引我,不断钻研奋斗,下学期继续选张老师的课学这些内容。

我们应该已经了解了缓冲区溢出漏洞的原理,它就是因为我们输入了过长的字符,而缓冲区本身又没有有效的验证机制,导致过长的字符将返回地址覆盖掉了,当我们的函数需要返回的时候,由于此时的返回地址是一个无效地址,因此导致程序出错。那么依据这个原理,假设我们所覆盖的返回地址是一个有效地址,而在该地址处又包含着有效的指令,那么我们的系统就会毫不犹豫地跳到该地址处去执行指令。因此,如果想利用缓冲区溢出的漏洞,我们就可以构造出一个有效地址出来,然后将我们想让计算机执行的代码写入该地址,这样一来,我们就通过程序的漏洞,让计算机执行了我们自己编写的程序。以上是我通过这个实验的理解,如果不正确,下学期的课程在和老师进行讨论。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值