缓冲区溢出攻击详细讲解

合集下载

缓冲区溢出攻击的基本原理

缓冲区溢出攻击的基本原理

缓冲区溢出攻击的基本原理
缓冲区溢出攻击(Buffer Overflow Attack)是一种常见的安全漏洞,指的是攻击者利用输入数据的长度或格式错误,超出程序设计者预留的存储空间范围,从而写入到相邻内存空间中,进而控制程序的执行或修改程序的行为。

缓冲区溢出攻击的基本原理如下:
1.内存分配:程序在运行时会根据变量类型和长度来分配内存空间。

2.缓冲区溢出:攻击者通过向程序输入异常数据,超出了程序预留的内存空
间。

3.覆盖关键数据:溢出的数据覆盖了原本存储的数据,可能是程序的返回地
址、函数指针等关键信息。

4.控制程序行为:攻击者利用溢出的数据修改程序的执行路径,跳转到自己
准备好的恶意代码。

5.执行恶意代码:程序执行了攻击者注入的恶意代码,可能导致系统崩溃、
拒绝服务或远程执行任意命令。

为了避免缓冲区溢出攻击,开发人员可以采取以下措施:
•使用安全的编程语言和工具,如内存安全的语言(如Rust)或经过良好测试的C/C++库。

•限制输入数据的长度,确保不会超过缓冲区可容纳的大小。

•进行输入验证和过滤,确保输入数据符合预期的格式和范围。

•定期更新软件和操作系统,及时修补已知的漏洞。

•实施数据执行保护(DEP)和地址空间布局随机化(ASLR)等安全机制。

综上所述,缓冲区溢出攻击是一种常见的安全漏洞,它利用错误处理输入数据的程序中的缺陷,从而控制程序行为。

开发人员和系统管理员应该密切关注安全问题,采取相应的防护措施,以保护系统和用户的信息安全。

第7章缓冲区溢出攻击及防御技术ppt课件

第7章缓冲区溢出攻击及防御技术ppt课件

2024/3/29
网络入侵与防范技术
7
篮球比赛是根据运动队在规定的比赛 时间里 得分多 少来决 定胜负 的,因 此,篮 球比赛 的计时 计分系 统是一 种得分 类型的 系统
7.1 缓冲区溢出概述
隐蔽性:
第三,由于漏洞存在于防火墙内部的主机上,攻击者可 以在防火墙内部堂而皇之地取得本来不被允许或没有权 限的控制权;
2024/3/29
网络入侵与防范技术
1
篮球比赛是根据运动队在规定的比赛 时间里 得分多 少来决 定胜负 的,因 此,篮 球比赛 的计时 计分系 统是一 种得分 类型的 系统
7.1 缓冲区溢出概述
什么是缓冲区?它是包含相同数据类型实例的一个 连续的计算机内存块。是程序运行期间在内存中分 配的一个连续的区域,用于保存包括字符数组在内 的各种数据类型。
Windows系统中缓冲区溢出的事例更是层出不穷。 2001年“红色代码”蠕虫利用微软IIS Web Server中
的缓冲区溢出漏洞使300 000多台计算机受到攻击; 2003年1月,Slammer蠕虫爆发,利用的是微软SQL
Server 2000中的缺陷; 2004年5月爆发的“振荡波”利用了Windows系统的活
产生碎片不同 对堆来说,频繁的new/delete或者malloc/free势必会造成 内存空间的不连续,造成大量的碎片,使程序效率降低。 对栈而言,则不存在碎片问题,因为栈是先进后出的队列, 永远不可能有一个内存块从栈中间弹出。
生长方向不同 堆是向着内存地址增加的方向增长的,从内存的低地址向高 地址方向增长。 栈的生长方向与之相反,是向着内存地址减小的方向增长, 由内存的高地址向低地址方向增长。
1999年w00w00安全小组的Matt Conover写了基于 堆缓冲区溢出专著,对堆溢出的机理进行了探索。

“溢出攻击”的讲解和防护

“溢出攻击”的讲解和防护

“溢出攻击”的讲解和防护随着网络普及,大量公开的Shellcode(“溢出”代码)与溢出攻击原理都能在各大安全网站中找到,也由此衍生了一系列安全隐患,很多稍微了解网络安全知识的人都可以利用现成的攻击软件轻易发动溢出攻击获得服务器权限。

1.什么是“溢出攻击”?“溢出攻击”就像是将很多沙子倒入装满水的容器时,水就会溢出来一样。

目前,大多溢出攻击都是针对缓冲区的溢出。

当缓冲区溢出时,过剩的信息对电脑内存中原有内容进行完全替换,如未进行备份,你的内容就永远丢失了。

现在网上公布的攻击程序不仅具有破坏文件的功能,一般还会得到系统权限的CMDSHELL(管理命令行),那它又是如何实现的呢?“溢出攻击”在对缓冲区中的文件进行替换的同时,还会执行一些非法程序,从而得到命令行下的管理员权限,之后攻击者再通过命令行建立管理员账号,对电脑进行控制。

2.“溢出攻击”的实现一般入侵者在网上了解或发现了可以进行溢出攻击的漏洞后,使用缺陷扫描器(如全面扫描的X-SCAN、针对单一漏洞扫描的IIS WEBDAV等工具)找到并确认存在远程溢出漏洞的电脑,接着便使用利用攻击代码编程成功的Exploit(攻击程序)发送Shellcode攻击,确认远程溢出成功后使用NC或TELNET等程序连接被溢出主机的端口从而得到CMDSHELL。

比如前段时间危害特别大的MS05039溢出漏洞,就是先利用MS05039Scan来扫描有漏洞的电脑(见图1),然后打开两个命令提示符窗口,一个用来得到CMDSHELL的NC(见图2),一个执行溢出攻击程序(见图3),当执行攻击程序后,就得到了系统权限的CMDSHELL(见图4)。

图1图2图3图43.如何对溢出攻击进行防护?说到防护,首先定时更新有效补丁,微软个官方补丁发布下载地址是/china/。

但如果攻击者用的是尚未发布补丁的攻击程序呢?所以打补丁是有效,但不是惟一的方法。

下面就来看看如何手动设置,对溢出攻击进行防御。

缓冲区溢出攻击的原理分析与防范

缓冲区溢出攻击的原理分析与防范

3、缓冲区溢出的防御方法
3.1、写正确的代码的方法 3.2、通过操作系统使得缓冲区不可执行,从而阻止攻击者植入攻击代码 3.3、利用编译器的数组边界检查来实现缓冲区的保护 3.4、在程序指针失效前进行完整性检查
4、总结与展望
4.1全文总结
4.2 展望
5、参考文献
本课题的研究意义
随着信息与网络技术的发展,以及这些技术在军事领域 的不断渗透,计算机网络已成为连接未来信息化战场的枢纽。 对计算机的攻击,能够获得大量宝贵的情报以及达到其它武 器系统所不能及的效果。因此对以计算机为基础的网络攻击 与防护就自然成为军事领域密切关注的问题。近年来,缓冲 区溢出漏洞的广泛性和破坏性受到国内外信息安全研究领域 的极切关注。从1988年CERT(计算机紧急响应小组)成立以来, 统计到的安全威胁事件每年以指数增长。缓冲区溢出攻击作 为网络攻击一种主要形式占所有系统攻击总数的80%以上[1]。 这种缓冲区溢出漏洞可以发生在不同的操作系统以及不同的 应用程序上。 缓冲区溢出攻击是黑客攻击的主要手段,给网络信息安全 带来了越来越大的危害。已有的防御手段研究相对滞后,目 前国内外的研究大多集中在某个具体漏洞的利用与防范上, 缺乏全面的研究。并且现有的缓冲区溢出防御手段也存在诸 多不足之处。论文主要是对缓冲区溢出攻击的原理分析与防 范进行深入研究。 论文首先介绍了缓冲区和堆栈的基本概念,研究并总结了 缓冲区溢出的原理和过程,并介绍了一些常用的攻击方法。 在此基础上,论文研究并总结了目前防御缓冲区溢出攻击的 一些常用方法,主要从主客观两方面来讨论。主观方面,主 要是要提高程序员编写代码的质量,形成良好的编程风格; 客观方面,主要是从系统和软件做一些相关的检查和优化。
缓冲区溢出影响及危害
• 在几乎所有计算机语言中,不管是新的语言还是旧的 语言,使缓冲区溢出的任何尝试通常都会被该语言本身自 动检测并阻止(比如通过引发一个异常或根据需要给缓冲 区添加更多空间),但是有两种语言不是这样:C和C++ 语言。C\C++语言由于其针灵活应用的特性,通常允许让 额外的数据乱写到其余内存的任何位置,而这种情况可能 被利用从而导致意想不到的结果。而且,用C\C++编写正 确的代码来始终如一地处理缓冲区溢出则更为困难;很容 易就会意外地导致缓冲区溢出。更重要的一点就是C\C++ 的应用非常广泛,例如,Red Hat Linux 7.1中86%的代码 行都是用C或C++编写的。因此,大量的代码对这个问题 都是脆弱的,出现缓冲区溢出也就是常见的事情。 缓冲区溢出漏洞很容易被蠕虫病毒利用造成了很大的 危害,如2001年7月19日,CodeRed蠕虫爆发,造成的损 失估计超过20亿美元[2],2001年9月18日,Nimda蠕虫被 发现,造成的损失更大,超过26亿美元,2002年Slapper 蠕虫出现,2003年1月25日Slammer蠕虫爆发,2004年5 月1日,“震荡波”被发现,这几个病毒对网络安全造成 的破坏之大是前所未有的。而以上病毒都利用了缓冲区溢 出漏洞。

缓冲区溢出详解

缓冲区溢出详解

缓冲区溢出详解缓冲区溢出(Buffer Overflow)是计算机安全领域内既经典⽽⼜古⽼的话题。

随着计算机系统安全性的加强,传统的缓冲区溢出攻击⽅式可能变得不再奏效,相应的介绍缓冲区溢出原理的资料也变得“⼤众化”起来。

其中看雪的《0day安全:软件漏洞分析技术》⼀书将缓冲区溢出攻击的原理阐述得简洁明了。

本⽂参考该书对缓冲区溢出原理的讲解,并结合实际的代码实例进⾏验证。

不过即便如此,完成⼀个简单的溢出代码也需要解决很多书中⽆法涉及的问题,尤其是⾯对较新的具有安全特性的编译器——⽐如MS的Visual Studio2010。

接下来,我们结合具体代码,按照对缓冲区溢出原理的循序渐进地理解⽅式去挖掘缓冲区溢出背后的底层机制。

⼀、代码 <=> 数据顾名思义,缓冲区溢出的含义是为缓冲区提供了多于其存储容量的数据,就像往杯⼦⾥倒⼊了过量的⽔⼀样。

通常情况下,缓冲区溢出的数据只会破坏程序数据,造成意外终⽌。

但是如果有⼈精⼼构造溢出数据的内容,那么就有可能获得系统的控制权!如果说⽤户(也可能是⿊客)提供了⽔——缓冲区溢出攻击的数据,那么系统提供了溢出的容器——缓冲区。

缓冲区在系统中的表现形式是多样的,⾼级语⾔定义的变量、数组、结构体等在运⾏时可以说都是保存在缓冲区内的,因此所谓缓冲区可以更抽象地理解为⼀段可读写的内存区域,缓冲区攻击的最终⽬的就是希望系统能执⾏这块可读写内存中已经被蓄意设定好的恶意代码。

按照冯·诺依曼存储程序原理,程序代码是作为⼆进制数据存储在内存的,同样程序的数据也在内存中,因此直接从内存的⼆进制形式上是⽆法区分哪些是数据哪些是代码的,这也为缓冲区溢出攻击提供了可能。

图1 进程地址空间分布图1是进程地址空间分布的简单表⽰。

代码存储了⽤户程序的所有可执⾏代码,在程序正常执⾏的情况下,程序计数器(PC指针)只会在代码段和操作系统地址空间(内核态)内寻址。

数据段内存储了⽤户程序的全局变量,⽂字池等。

简述缓冲区溢出攻击的原理以及防范方法

简述缓冲区溢出攻击的原理以及防范方法

简述缓冲区溢出攻击的原理以及防范方法
一、缓冲区溢出攻击原理
缓冲区溢出攻击(Buffer Overflow Attack)是一种非法异常的程序运行行为,它发生的目的是让受害者的程序运行出现崩溃,从而获得机器控制权限,可以获取机器中存有的敏感资料,并进行恶意操作,如发送垃圾邮件,拒绝服务攻击(DoS attack),远程控制等行为破坏网络安全。

缓冲区溢出攻击的基本原理,就是恶意程序使用某种方法,将程序缓冲区中存放的数据或者信息溢出,超出缓冲区的容量,而这种溢出的数据又存放了受害者程序控制机器的恶意命令,从而给受害者程序植入恶意代码,使恶意程序获得了机器的控制权限,进而达到攻击系统的目的。

二、防范方法
1、使用受检程序,受检程序是一种编译技术,通过对程序源代码进行类型检查、安全检查等操作,来把漏洞修复好,从而起到防止缓冲区溢出攻击的作用。

2、使用数据流分析技术,它是一种动态分析技术,可以识别出恶意代码并阻止其危害,对程序运行的漏洞进行检查,从而防止攻击者利用缓冲区溢出攻击系统。

3、实行严格的安全审计制度,对程序源码、程序诊断、数据加密技术等进行严格的审计,确保程序运行的安全性,以及防止攻击者利用缓冲区溢出攻击系统。

4、采用虚拟化技术,虚拟化技术可以在不同的安全层次上对程序进行控制,对程序运行的过程进行审查,从而防止攻击者使用缓冲区溢出攻击系统。

5、对网络环境进行安全审计,包括电脑中存在的安全漏洞,系统的安全配置,网络设备的稳定性以及系统的社会工程学攻击等,从而确保网络环境能够不被缓冲区溢出攻击所侵袭。

安全测试中的缓冲区溢出漏洞检测

安全测试中的缓冲区溢出漏洞检测

安全测试中的缓冲区溢出漏洞检测在安全测试中,缓冲区溢出漏洞是一个重要的检测点。

本文将介绍什么是缓冲区溢出漏洞以及如何进行其检测。

一、什么是缓冲区溢出漏洞缓冲区溢出漏洞是指当程序在向一个缓冲区写入数据时,超过了该缓冲区的容量,导致数据溢出到相邻的内存区域。

攻击者可以通过利用这种溢出,覆盖控制数据、篡改程序逻辑,甚至执行恶意代码,从而导致系统崩溃、数据泄漏等严重后果。

二、缓冲区溢出漏洞检测方法1. 静态代码分析静态代码分析是一种通过分析源代码或可执行文件的方法,来查找可能存在的漏洞。

在缓冲区溢出漏洞检测中,静态代码分析可以通过识别潜在的缓冲区溢出点以及对应的输入来进行检测。

一些静态代码分析工具可以检测出一些明显的溢出漏洞,如strcpy、strcat等函数的使用。

但是,对于复杂的缓冲区溢出漏洞,静态代码分析往往无法完全覆盖,因此需要结合其他方法进行检测。

2. 动态测试动态测试是通过观察和控制程序的执行来检测漏洞。

在缓冲区溢出漏洞检测中,常用的动态测试方法是输入模糊测试(fuzzing)。

输入模糊测试通过构造各种异常输入来触发程序的潜在漏洞,其中就包括缓冲区溢出。

通过不断尝试大量的输入组合,可以增加发现溢出漏洞的概率。

3. 符号执行符号执行是一种通过符号代替具体输入值,对程序进行路径覆盖分析的方法。

在缓冲区溢出漏洞检测中,符号执行可以通过生成多个具有不同特征的符号输入,来探索程序可能存在的漏洞路径。

基于符号执行的漏洞检测工具如KLEE可以在一定程度上检测缓冲区溢出漏洞。

4. 模糊测试模糊测试是在动态测试中的一种常用方法。

通过模拟攻击者向程序输入异常数据,如大量随机字符、特殊字符等,来触发潜在的漏洞。

对于缓冲区溢出漏洞的检测,模糊测试可以通过构造各种边界情况的输入数据,来发现程序对于异常输入的处理是否存在问题。

三、缓冲区溢出漏洞检测的挑战缓冲区溢出漏洞检测面临一些挑战,包括以下几个方面:1. 多种编程语言和平台缓冲区溢出漏洞可能存在于多种编程语言和平台中,例如C、C++、Java等。

缓冲区溢出-原理和简单利用-概述说明以及解释

缓冲区溢出-原理和简单利用-概述说明以及解释

缓冲区溢出-原理和简单利用-概述说明以及解释1.引言概述部分是文章的开篇,旨在引入读者对于缓冲区溢出问题的背景和概念。

下面是概述部分的内容:1.1 概述在计算机科学和网络安全领域中,缓冲区溢出(Buffer Overflow)是一种常见的安全漏洞,它可能导致系统崩溃、数据泄露、远程命令执行等严重后果。

本文将介绍缓冲区溢出的原理和简单利用方法。

缓冲区溢出指的是当向一个缓冲区写入数据时,超出了该缓冲区所能容纳的大小,导致溢出的数据覆盖到相邻的内存区域。

这种溢出可能会覆盖控制流程信息,改变程序执行路径,从而使攻击者能够执行恶意代码。

缓冲区溢出是一种经典的安全漏洞,其发现最早可以追溯到20世纪70年代。

尽管多年来在软件和系统的开发过程中进行了一系列的改进和加固,但仍然存在很多软件和系统容易受到缓冲区溢出攻击的漏洞存在。

正因如此,了解缓冲区溢出的原理和简单利用方法对于计算机科学和网络安全从业人员来说是至关重要的。

本文的主要目的是帮助读者理解缓冲区溢出的原理,并介绍常见的利用方法。

在深入研究和了解缓冲区溢出的背景之后,读者将能够更好地理解和应对这种常见的安全威胁。

接下来的章节将分别介绍缓冲区溢出的原理,并提供一些简单的利用方法作为案例。

最后,我们将总结本文的内容,并进一步讨论缓冲区溢出的意义和应对措施。

通过阅读本文,我们希望读者能够加深对于缓冲区溢出问题的理解,提高对于软件和系统安全的意识,并能够采取相应的措施来预防和应对这种安全漏洞。

让我们一起深入探索缓冲区溢出的原理和简单利用方法吧!文章结构是指文章整体组织的安排和框架。

一个良好的文章结构可以帮助读者更好地理解和吸收文章内容。

本文主要讨论缓冲区溢出的原理和简单利用方法,因此文章结构如下:1. 引言1.1 概述引入缓冲区溢出的基本概念和定义,解释缓冲区溢出在计算机领域的重要性和普遍存在的问题。

1.2 文章结构介绍本文的文章结构以及各个部分的内容安排,方便读者了解整个文章的组织。

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

缓冲区溢出攻击详细讲解缓冲区溢出(Buffer Overflow)是计算机安全领域既经典而又古老的话题。

随着计算机系统安全性的加强,传统的缓冲区溢出攻击方式可能变得不再奏效,相应的介绍缓冲区溢出原理的资料也变得“大众化”起来。

其中看雪的《0day安全:软件漏洞分析技术》一书将缓冲区溢出攻击的原理阐述得简洁明了。

本文参考该书对缓冲区溢出原理的讲解,并结合实际的代码实例进行验证。

不过即便如此,完成一个简单的溢出代码也需要解决很多书中无法涉及的问题,尤其是面对较新的具有安全特性的编译器——比如MS的Visual Studio2010。

接下来,我们结合具体代码,按照对缓冲区溢出原理的循序渐进地理解方式去挖掘缓冲区溢出背后的底层机制。

一、代码 <=> 数据顾名思义,缓冲区溢出的含义是为缓冲区提供了多于其存储容量的数据,就像往杯子里倒入了过量的水一样。

通常情况下,缓冲区溢出的数据只会破坏程序数据,造成意外终止。

但是如果有人精心构造溢出数据的容,那么就有可能获得系统的控制权!如果说用户(也可能是黑客)提供了水——缓冲区溢出攻击的数据,那么系统提供了溢出的容器——缓冲区。

缓冲区在系统中的表现形式是多样的,高级语言定义的变量、数组、结构体等在运行时可以说都是保存在缓冲区的,因此所谓缓冲区可以更抽象地理解为一段可读写的存区域,缓冲区攻击的最终目的就是希望系统能执行这块可读写存中已经被蓄意设定好的恶意代码。

按照冯·诺依曼存储程序原理,程序代码是作为二进制数据存储在存的,同样程序的数据也在存中,因此直接从存的二进制形式上是无法区分哪些是数据哪些是代码的,这也为缓冲区溢出攻击提供了可能。

图1 进程地址空间分布图1是进程地址空间分布的简单表示。

代码存储了用户程序的所有可执行代码,在程序正常执行的情况下,程序计数器(PC指针)只会在代码段和操作系统地址空间(核态)寻址。

数据段存储了用户程序的全局变量,文字池等。

栈空间存储了用户程序的函数栈帧(包括参数、局部数据等),实现函数调用机制,它的数据增长方向是低地址方向。

堆空间存储了程序运行时动态申请的存数据等,数据增长方向是高地址方向。

除了代码段和受操作系统保护的数据区域,其他的存区域都可能作为缓冲区,因此缓冲区溢出的位置可能在数据段,也可能在堆、栈段。

如果程序的代码有软件漏洞,恶意程序会“教唆”程序计数器从上述缓冲区取指,执行恶意程序提供的数据代码!本文分析并实现栈溢出攻击方式。

二、函数栈帧栈的主要功能是实现函数的调用。

因此在介绍栈溢出原理之前,需要弄清函数调用时栈空间发生了怎样的变化。

每次函数调用时,系统会把函数的返回地址(函数调用指令后紧跟指令的地址),一些关键的寄存器值保存在栈,函数的实际参数和局部变量(包括数据、结构体、对象等)也会保存在栈。

这些数据统称为函数调用的栈帧,而且是每次函数调用都会有个独立的栈帧,这也为递归函数的实现提供了可能。

图2 函数栈帧如图所示,我们定义了一个简单的函数function,它接受一个整形参数,做一次乘法操作并返回。

当调用function(0)时,arg参数记录了值0入栈,并将call function指令下一条指令的地址0x00bd16f0保存到栈,然后跳转到function函数部执行。

每个函数定义都会有函数头和函数尾代码,如图绿框表示。

因为函数需要用ebp 保存函数栈帧基址,因此先保存ebp原来的值到栈,然后将栈指针esp容保存到ebp。

函数返回前需要做相反的操作——将esp指针恢复,并弹出ebp。

这样,函数正常情况下无论怎样使用栈,都不会使栈失去平衡。

sub esp,44h指令为局部变量开辟了栈空间,比如ret变量的位置。

理论上,function只需要再开辟4字节空间保存ret即可,但是编译器开辟了更多的空间(这个问题很诡异,你觉得呢?)。

函数调用结束返回后,函数栈帧恢复到保存参数0时的状态,为了保持栈帧平衡,需要恢复esp的容,使用add esp,4将压入的参数弹出。

之所以会有缓冲区溢出的可能,主要是因为栈空间保存了函数的返回地址。

该地址保存了函数调用结束后后续执行的指令的位置,对于计算机安全来说,该信息是很敏感的。

如果有人恶意修改了这个返回地址,并使该返回地址指向了一个新的代码位置,程序便能从其它位置继续执行。

三、栈溢出基本原理上边给出的代码是无法进行溢出操作的,因为用户没有“插足”的机会。

但是实际上很多程序都会接受用户的外界输入,尤其是当函数的一个数组缓冲区接受用户输入的时候,一旦程序代码未对输入的长度进行合法性检查的话,缓冲区溢出便有可能触发!比如下边的一个简单的函数。

1.void fun(unsigned char*data)2.{3.unsigned char buffer[BUF_LEN];4.strcpy((char*)buffer,(char*)data);//溢出点5.}这个函数没有做什么有“意义”的事情(这里主要是为了简化问题),但是它是一个典型的栈溢出代码。

在使用不安全的strcpy库函数时,系统会盲目地将data的全部数据拷贝到buffer指向的存区域。

buffer的长度是有限的,一旦data的数据长度超过BUF_LEN,便会产生缓冲区溢出。

图3 缓冲区溢出由于栈是低地址方向增长的,因此局部数组buffer的指针在缓冲区的下方。

当把data的数据拷贝到buffer 时,超过缓冲区区域的高地址部分数据会“淹没”原本的其他栈帧数据,根据淹没数据的容不同,可能会有产生以下情况:1、淹没了其他的局部变量。

如果被淹没的局部变量是条件变量,那么可能会改变函数原本的执行流程。

这种方式可以用于破解简单的软件验证。

2、淹没了ebp的值。

修改了函数执行结束后要恢复的栈指针,将会导致栈帧失去平衡。

3、淹没了返回地址。

这是栈溢出原理的核心所在,通过淹没的方式修改函数的返回地址,使程序代码执行“意外”的流程!4、淹没参数变量。

修改函数的参数变量也可能改变当前函数的执行结果和流程。

5、淹没上级函数的栈帧,情况与上述4点类似,只不过影响的是上级函数的执行。

当然这里的前提是保证函数能正常返回,即函数地址不能被随意修改(这可能很麻烦!)。

如果在data本身的数据就保存了一系列的指令的二进制代码,一旦栈溢出修改了函数的返回地址,并将该地址指向这段二进制代码的其实位置,那么就完成了基本的溢出攻击行为。

图4 基本栈溢出攻击通过计算返回地址存区域相对于buffer的偏移,并在对应位置构造新的地址指向buffer部二进制代码的其实位置,便能执行用户的自定义代码!这段既是代码又是数据的二进制数据被称为shellcode,因为攻击者希望通过这段代码打开系统的shell,以执行任意的操作系统命令——比如下载病毒,安装木马,开放端口,格式化磁盘等恶意操作。

四、栈溢出攻击上述过程虽然理论上能完成栈溢出攻击行为,但是实际上很难实现。

操作系统每次加载可执行文件到进程空间的位置都是无法预测的,因此栈的位置实际是不固定的,通过硬编码覆盖新返回地址的方式并不可靠。

为了能准确定位shellcode的地址,需要借助一些额外的操作,其中最经典的是借助跳板的栈溢出方式。

根据前边所述,函数执行后,栈指针esp会恢复到压入参数时的状态,在图4中即data参数的地址。

如果我们在函数的返回地址填入一个地址,该地址指向的存保存了一条特殊的指令jmp esp——跳板。

那么函数返回后,会执行该指令并跳转到esp所在的位置——即data的位置。

我们可以将缓冲区再多溢出一部分,淹没data这样的函数参数,并在这里放上我们想要执行的代码!这样,不管程序被加载到哪个位置,最终都会回来执行栈的代码。

图5 借助跳板的栈溢出攻击借助于跳板的确可以很好的解决栈帧移位(栈加载地址不固定)的问题,但是跳板指令从哪找呢?“幸运”的是,在Windows操作系统加载的大量dll中,包含了许多这样的指令,比如kernel32.dll,ntdll.dll,这两个动态库是Windows程序默认加载的。

如果是图形化界面的Windows程序还会加载user32.dll,它也包含了大量的跳板指令!而且更“神奇”的是Windows操作系统加载dll时候一般都是固定地址,因此这些dll的跳板指令的地址一般都是固定的。

我们可以离线搜索出跳板执行在dll的偏移,并加上dll的加载地址,便得到一个适用的跳板指令地址!//查询dll第一个jmp esp指令的位置int findJmp(char*dll_name){char* handle=(char*)LoadLibraryA(dll_name);//获取dll加载地址for(int pos=0;;pos++)//遍历dll代码空间{if(handle[pos]==(char)0xff&&handle[pos+1]==(char)0xe4)//寻找0xffe4 = jmp esp{return (int)(handle+pos);}}}这里简化了搜索算法,输出第一个跳板指令的地址,读者可以选取其他更合适位置。

LoadLibraryA库函数返回值就是dll的加载地址,然后加上搜索到的跳板指令偏移pos便是最终地址。

jmp esp指令的二进制表示为0xffe4,因此搜索算法就是搜索dll这样的字节数据即可。

虽然如此,上述的攻击方式还不够好。

因为在esp后继续追加shellcode代码会将上级函数的栈帧淹没,这样做并没有什么好处,甚至可能会带来运行时问题。

既然被溢出的函数栈帧提供了缓冲区,我们还是把核心的shellcode放在缓冲区,而在esp之后放上跳转指令转移到原本的缓冲区位置。

由于这样做使代码的位置在esp 指针之前,如果shellcode中使用了push指令便会让esp指令与shellcode代码越来越近,甚至淹没自身的代码。

这显然不是我们想要的结果,因此我们可以强制抬高esp指针,使它在shellcode之前(低地址位置),这样就能在shellcode正常使用push指令了。

图6 调整shellcode与栈指针调整代码的容很简单:add esp,-Xjmp esp第一条指令抬高了栈指针到shellcode之前。

X代表shellcode起始地址与esp的偏移。

如果shellcode从缓冲区起始位置开始,那么就是buffer的地址偏移。

这里不使用sub esp,X指令主要是避免X的高位字节为0的问题,很多情况下缓冲区溢出是针对字符串缓冲区的,如果出现字节0会导致缓冲区截断,从而导致溢出失败。

第二条指令就是跳转到shellcode的起始位置继续执行。

(又是jmp esp!)通过上述方式便能获得一个较为稳定的栈溢出攻击。

相关文档
最新文档