程序安全之作业

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

程序安全之作业

一、获取文件overflow.zip,提取Windows可执行文件

1、利用缓冲区溢出,绕过序列号检查

2、正确的序列号

二、如何有效的防范缓冲区溢出

根据缓冲区溢出攻击的步骤,可将常用的缓冲区溢出攻击检测技术分为以下3种类型:基于输入字符串的检测方法,基于保护堆栈中的返回地址的检测方法和基于监视系统调用的检测方法。

1、基于输入字符串的检测方法

对输入的字符串进行检测,确定其为溢出攻击字符串时采取阻拦措施,使攻击者无法注入攻击代码。一般有以下3种方法构建溢出攻击字符串。分别如下图4-1,图4-2,图4-3所示:

图4-1缓冲区大于ShellCode长度

图4-2缓冲区小于ShellCode长度

图4-3将ShellCode放在环境变量里

第1种溢出攻击字符串适用于缓冲区大于ShellCode长度的情况;第2种溢出攻击字符串一般用于缓冲区小于ShellCode长度的情况;第3种方法是将ShellCode放在环境变量里,是目前较为常用的方法。

在第1种和第2种类型的溢出攻击字符串中ShellCode前都加了若干的NOP指令,因为这2种情况下ShellCode的地址无法确定,但只要返回地址指向ShellCode前的任一条NOP指令,ShellCode就可以执行,大大增加了ShellCode执行的可能性。这些NOP指令称为sledge。其他单字节指令如AAA等也可构成sledge。因此缓冲区溢出攻击检测系统可以通过检查输入的字符串中是否含有大量NOP等可构成sledge的指令来判断此字符串是否是溢出攻击字符串。不过这种方法并不适用于检测第3种类型的攻击。但这3种类型的攻击字符串中都含有ShellCode。因此,确定出ShellCode的基本特征,如不含有“0x00”,含有某些特殊的系统调用等,然后利用人工智能、模式匹配、规则匹配等方法检查输入字符串中是否包含ShellCode也可检测出是否有缓冲区溢出攻击发生。这些检测都可以在入侵检测等外围防御系统中实现,优点是实现较为简单,不会增加被保护系统的开销;缺点是漏报率较高,无法检测出无明显特征的溢出攻击字符串。

2、基于保护堆栈中返回地址的检测方法

缓冲区溢出攻击最关键的步骤是要通过修改函数返回地址来改变程序的流程,因此,在函数调用返回前,通过检查返回地址是否被修改可以判断是否有缓冲区溢出攻击发生。该检测的实现可以通过在源码中插入一些约束和判断的模块,然后在编译后的程序运行期间对有关变量和堆栈区域进行监控,检测是否有攻击发生。StackGuard和StackShield就是这一类型的工具,它们都是gcc编译器的扩展工具,用于监控调用的函数返回地址是否正常。StackGuard主要是在内存中的返回地址及缓冲区之间插入一个“Canary”字,如图5所示。在函数调用返回前通过检查“Canary”字来判断返回地址是否已经被修改,如果这个Canary 的值被改变了,说明可能有人正进行缓冲区溢出攻击,程序会立刻响应,发送一则入侵警告消息,然后停止工作。为防止攻击者构造“Canary”字,StackGuard 选用“终止符”和“随机数”作为“Canary”字的值。但由于“Canary”字所在的位置是固定的,因此也可能被绕过。

StackShield对此作了改进,创建了一个新的堆栈用于备份被保护函数的返回地址。它在被保护函数开始处增加一段代码,用来将函数返回地址拷贝到一张特殊的表中;同样在被保护函数的结尾处也增加一段代码,用来将函数返回地址从表中拷贝回堆栈。从而保证函数正确返回。

除这2种工具外,还有其他一些类似的编译器扩展方法和工具,如PointGuard、Snarskii等。这些工具提高了被保护系统的安全性,不过增加了系统开销,降低了系统性能。

3、基于监视系统调用的检测方法

如果攻击者成功注入攻击代码,并改变了程序的执行流程使指令的执行指针指向了ShellCode的入口地址。按照一次缓冲区攻击的3个步骤,还须执行ShellCode来完成攻击目的。因此,通过检测是否有ShellCode运行可以检测是否发生缓冲区溢出攻击。

攻击者既希望ShellCode利用获得的权限启动一个交互式的shell进程来

完成尽量多的事情,又希望ShellCode尽量短小从而更加隐蔽,所以绝大多数ShellCode都会调用系统函数。由于监视所有系统调用会耗费大量系统资源,因

此只对ShellCode常用的系统调用进行监视,根据某些特征判断受监视的系统调用是否为非法调用就可确定被保护系统是否遭到缓冲区溢出攻击。例如,如果发现系统调用的返回地址为堆栈,则可认为其为非法调用,因为很少有程序在堆栈上运行代码。

4、缓冲区漏洞的防范措施

上面三种方法是针对如何检测已经发生的缓冲区漏洞,方法虽然多,但是相对比较麻烦,所以我们最好能从根本上防范它,防止缓冲区漏洞的发生。

首先在编写程序过程中,程序员有责任和义务养成安全编程的思想,应该熟悉那些可能会产生漏洞或需慎用的函数,清楚那些在编程中要小心使用的函数(特别是在使用C语言时),例如:gets()、strcpy()等等。在软件测试阶段,要专门对程序中的每个缓冲区作边界检查和溢出检测。但是,由于程序编写者的经验不足和测试工作不够全面、充分,目前还不可能完全避免缓冲区溢出漏洞,因此这些漏洞在已经使用以及正在开发的软件中还是有存在的可能,还需要在使用软件时,对它做实时的监测。

其次是使用安全语言编写程序,应使用Java等安全的语言编写程序,因为Java在对缓冲区进行操作时,有相应的边界检查,所以可以有效地防止缓冲区溢出漏洞的产生。但是,Java也并非绝对安全,Java的解释器是用C语言编写的,而C并不是一种安全的语言,所以Java解释器还是可能存在缓冲区溢出漏洞并受到攻击。

最后可以通过改进编译器,它的主要思想是在编译器中增加边界检查以及保护堆栈的功能,使得含有漏洞的程序和代码段无法通过编译。针对gcc编译器的很多补丁就提供了这些功能,比如说Stackguard等等。

5、总结

缓冲区溢出是一种系统攻击的手段,通过往程序的缓冲区写入超出其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈,使程序转而执行非预期指令,以达到攻击的目的。目前,在Internet上利用缓冲区溢出进行攻击的行为已经相当普遍。本文从缓冲区溢出的原理入手,指出缓冲溢出漏洞的产生原因及其原理,说明其危害性,并分析了现有的检测和防范缓冲区溢出的措施,提出了对防范缓冲区溢出的一些方法。

相关文档
最新文档