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

合集下载

第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写了基于 堆缓冲区溢出专著,对堆溢出的机理进行了探索。

缓冲区溢出原因及解决

缓冲区溢出原因及解决

第三讲缓冲区溢出n1 缓冲区溢出问题简介n2 几种典型的缓冲区溢出n3 防范措施缓冲区溢出1 缓冲区溢出问题简介缓冲区溢出是一种常见的漏洞.据统计,通过缓冲区溢出进行的攻击占所有系统攻击总数的80%以上.这种错误的状态发生在写入内存的数据超过了分配给缓冲区的大小的时候,就像一个杯子只能盛一定量的水,如果放到杯子中的水太多,多余的水就会一出到别的地方。

由于缓冲区溢出,相邻的内存地址空间被覆盖,造成软件出错或崩溃。

如果没有采取限制措施,可以使用精心设计的输入数据使缓冲区溢出,从而导致安全问题。

缓冲区溢出缓冲区溢出问题的历史很长一段时间以来,缓冲区溢出都是一个众所周知的安全问题, C程序的缓冲区溢出问题早在70年代初就被认为是C语言数据完整性模型的一个可能的后果。

这是因为在初始化、拷贝或移动数据时,C语言并不自动地支持内在的数组边界检查。

虽然这提高了语言的执行效率,但其带来的影响及后果却是深远和严重的。

•1988年Robert T. Morris的finger蠕虫程序.这种缓冲区溢出的问题使得Internet几乎限于停滞,许多系统管理员都将他们的网络断开,来处理所遇到的问题. •1989年Spafford提交了一份关于运行在VAX机上的BSD版UNIX的fingerd的缓冲区溢出程序的技术细节的分析报告,引起了部分安全人士对这个研究领域的重视•1996年出现了真正有教育意义的第一篇文章, Aleph One在Underground发表的论文详细描述了Linux系统中栈的结构和如何利用基于栈的缓冲区溢出。

缓冲区溢出Aleph One的贡献还在于给出了如何写开一个shell的Exploit的方法,并给这段代码赋予shellcode的名称,而这个称呼沿用至今,我们现在对这样的方法耳熟能详--编译一段使用系统调用的简单的C程序,通过调试器抽取汇编代码,并根据需要修改这段汇编代码。

•1997年Smith综合以前的文章,提供了如何在各种Unix变种中写缓冲区溢出Exploit更详细的指导原则。

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

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

缓冲区溢出攻击原理与防范1.程序预留了一块内存区域作为缓冲区,用于执行其中一种特定的操作,如字符串拼接、输入输出处理等;2.当输入的数据长度超过了这个缓冲区的大小时,多余的数据会溢出到相邻的内存区域中;3.攻击者利用输入超出缓冲区的长度来对溢出的数据进行控制,修改程序的执行流程;4.修改后的程序执行流程可以导致程序崩溃、系统崩溃、拒绝服务等问题,也可以用于执行任意的恶意代码。

为了防范缓冲区溢出攻击,可以采取以下几种措施:1.对输入进行有效的长度检查:在程序中对输入数据进行有效的长度检查,确保不会超过预定的缓冲区大小。

这样就可以避免发生缓冲区溢出。

2. 使用安全编程语言和工具:选择使用安全编程语言,如Rust、Go 等,这些语言具有安全性的内存管理机制,能够自动检查和防范缓冲区溢出问题。

此外,使用安全编程工具如静态代码分析工具、Fuzzing工具等也可以帮助发现和修复潜在的缓冲区溢出漏洞。

3.使用内存安全检查工具:使用内存安全检查工具,如利用内存隔离技术的地址空间布局随机化(ASLR)、点火检查器、堆栈保护机制等。

这些工具可以帮助检测和防范缓冲区溢出攻击。

4.最小特权原则:在设计软件时,采用最小特权原则,即仅分配程序所需的最小权限。

这样做可以确保即使发生缓冲区溢出攻击,攻击者也只能访问到最小特权内的信息,减少损失。

5.及时修复漏洞和更新软件:及时修复已知的缓冲区溢出漏洞,更新软件以获取最新的安全补丁是非常重要的。

由于缓冲区溢出攻击是一种常见的攻击方式,软件开发商通常会不断更新修复这方面的漏洞。

综上所述,缓冲区溢出攻击是一种常见的安全漏洞利用技术,可以对各种软件和操作系统进行攻击。

为了防范这种攻击,需要采取有效的措施,如对输入进行有效的长度检查、使用安全编程语言和工具、使用内存安全检查工具、采用最小特权原则以及及时修复漏洞和更新软件等。

这样可以有效地减少缓冲区溢出攻击带来的风险。

缓冲区溢出攻击与防范实验报告

缓冲区溢出攻击与防范实验报告

缓冲区溢出攻击与防范实验报告——计算机网络(2)班——V200748045黄香娥1·缓冲区溢出的概念:缓冲区溢出是指当计算机向缓冲区内填充数据位数时超过了缓冲区本身的容量溢出的数据覆盖在合法数据上,理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符,但是绝大多数程序都会假设数据长度总是与所分配的储存空间想匹配,这就为缓冲区溢出埋下隐患.操作系统所使用的缓冲区又被称为"堆栈". 在各个操作进程之间,指令会被临时储存在"堆栈"当中,"堆栈"也会出现缓冲区溢出。

2·缓冲区溢出的危害:在当前网络与分布式系统安全中,被广泛利用的50%以上都是缓冲区溢出,其中最著名的例子是1988年利用fingerd漏洞的蠕虫。

而缓冲区溢出中,最为危险的是堆栈溢出,因为入侵者可以利用堆栈溢出,在函数返回时改变返回程序的地址,让其跳转到任意地址,带来的危害一种是程序崩溃导致拒绝服务,另外一种就是跳转并且执行一段恶意代码,比如得到shell,然后为所欲为。

3·缓冲区溢出原理:由一个小程序来看://test.c#include "stdio.h"#include "stdlib.h"#include "string.h"void overflow(void){char buf[10];strcpy(buf,"0123456789123456789");}//end overflowint main(void){overflow();return 0;}//end main按F11进入"Step into"调试模式,如下:按F11跟踪进入overflow,让程序停在6,现在再看一下几个主要参数:esp=0x0012ff30,eip发生了变化,其它未变。

c语言缓冲区溢出原理

c语言缓冲区溢出原理

c语言缓冲区溢出原理摘要:1.缓冲区溢出概念2.C语言中可能导致缓冲区溢出的原因3.缓冲区溢出的防范方法4.总结正文:正文:缓冲区溢出是计算机科学中的一种常见错误,它在编程中可能导致严重的安全问题。

本文将解释缓冲区溢出的概念,探讨其原因、危害以及如何预防。

一、什么是缓冲区溢出缓冲区溢出是指程序中的缓冲区无法容纳输入的数据,从而覆盖了其他内存区域。

这种情况通常发生在程序没有正确处理输入数据长度的情况下,导致数据超过了缓冲区的容量。

二、缓冲区溢出的原因1.字符串操作函数:在C语言中,一些字符串操作函数(如gets、strcpy 等)没有对输入数据长度进行限制,可能导致缓冲区溢出。

2.动态内存分配:在使用动态内存分配函数(如malloc)分配内存时,如果未正确初始化或超量分配,可能导致缓冲区溢出。

3.函数调用:在调用函数时,如果传入的参数长度超过预期,可能导致缓冲区溢出。

三、缓冲区溢出的危害1.程序崩溃:缓冲区溢出可能导致程序崩溃,因为覆盖的内存区域可能包含程序的重要数据或代码。

2.数据损坏:缓冲区溢出可能导致数据损坏,因为覆盖的内存区域可能包含程序处理数据的正确结果。

3.安全漏洞:缓冲区溢出可能被恶意利用,攻击者可以通过注入恶意数据来覆盖内存中的安全关键数据,如密码、加密密钥等。

四、如何预防缓冲区溢出1.检查输入数据长度:在对输入数据进行处理之前,应检查数据长度,确保不会超过缓冲区容量。

2.使用安全的字符串操作函数:尽量使用带有长度限制的字符串处理函数,如strncpy、strncat等。

3.初始化缓冲区:在使用动态内存分配时,应初始化缓冲区,并确保分配的内存空间足够大。

4.使用边界检查:在编写程序时,对输入数据进行边界检查,确保数据长度符合预期。

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

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

“溢出攻击”的讲解和防护随着网络普及,大量公开的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日,“震荡波”被发现,这几个病毒对网络安全造成 的破坏之大是前所未有的。而以上病毒都利用了缓冲区溢 出漏洞。

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

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

缓冲区溢出攻击的原理分析与防范原理分析:1.缓冲区的分配:当程序运行时,会为其分配一定大小的缓冲区(数组)来存储数据。

攻击者通过输入超过缓冲区大小的数据,覆盖相邻的内存区域。

2. 缓冲区溢出:攻击者构造特定的输入,超过缓冲区的边界,将溢出的数据覆盖到程序的其他内存空间,包括调用栈(stack)等。

3.返回地址覆盖:返回地址是指程序执行的下一条指令的地址,攻击者通过溢出缓冲区,将恶意代码的地址覆盖到返回地址上,使程序执行恶意代码。

4.执行恶意代码:当程序执行到返回地址时,由于返回地址被替换为恶意代码的地址,程序控制权转移到了恶意代码上,攻击者可以控制程序执行一系列恶意操作。

防范措施:1. 输入验证:在程序中对用户输入进行验证和过滤,确保输入的大小不会超出缓冲区的边界。

可以使用编程语言中的字符串处理函数,如strncpy(、snprintf(等,确保只将有效数据拷贝到缓冲区。

2. 使用编程语言和框架提供的安全API:使用编程语言提供的安全API,如Java中的StringBuilder类,C#中的StringBuilder类等,这些API在处理字符串时会进行边界检查,避免缓冲区溢出。

3. 栈保护技术:栈保护技术包括Stack Smashing Protector (SSP)和Control Flow Integrity (CFI)等。

SSP通过在栈上插入一个特殊的栈保护变量,监控缓冲区的溢出情况。

CFI通过在程序中插入额外的代码和元数据,来防止控制流的恶意改变。

4. 内存随机化:通过内存随机化技术,如ASLR(Address Space Layout Randomization),将程序的内存布局随机化,使攻击者难以预测恶意代码的位置。

5.使用静态和动态代码分析工具:使用静态和动态代码分析工具来检测和修复程序中的缓冲区溢出漏洞。

静态代码分析工具可以在编译时检测潜在的缓冲区溢出漏洞,而动态代码分析工具可以模拟攻击,并检测运行时的缓冲区溢出情况。

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

缓冲区溢出攻击的原理与防范陈硕2004-7-12读者基础:熟悉C语言及其内存模型,了解x86汇编语言。

缓冲区溢出(buffer overflow)是安全的头号公敌,据报道,有50%以上的安全漏洞和缓冲区溢出有关。

C/C++语言对数组下标访问越界不做检查,是引起缓冲区溢出问题的根本原因。

本文以Linux on IA32(32-bit Intel Architecture,即常说的x86)为平台,介绍缓冲区溢出的原理与防范措施。

按照被攻击的缓冲区所处的位置,缓冲区溢出(buffer overflow)大致可分为两类:堆溢出1(heap overflow)和栈溢出2(stack overflow)。

栈溢出较为简单,我先以一些实例介绍栈溢出,然后谈一谈堆溢出的一般原理。

栈溢出原理我们知道,栈(stack)是一种基本的数据结构,具有后入先出(LIFO, Last-In-First-Out)的性质。

在x86平台上,调用函数时实际参数(arguments)、返回地址(return address)、局部变量(local variables)都位于栈上,栈是自高向低增长(先入栈的地址较高),栈指针(stack pointer)寄存器ESP始终指向栈顶元素。

以图表1中的简单程序为例,我们先将它编译为可执行文件,然后在gdb中反汇编并跟踪其运行:$ gcc stack.c –o stack -ggdb -mperferred-stack-boundary=2在IA32上,gcc默认按8个字节对齐,为了突出主题,我们令它按4字节对齐,最末一个参数的用处在此。

图表1在每条语句之后列出对应的汇编指令,注意这是AT&T格式汇编,mov %esp, %ebp 是将寄存器ESP的值赋给寄存器EBP(这与常用的Intel汇编格式正好相反)。

// stack.c#01 int add(int a, int b)#02 {// push %ebp// mov %esp,%ebp#03 int sum;// sub $0x4,%esp#04 sum = a + b;// mov 0xc(%ebp),%eax// add 0x8(%ebp),%eax// mov %eax,0xfffffffc(%ebp)#05 return sum;// mov 0xfffffffc(%ebp),%eax1本文把静态存储区溢出也算作一种堆溢出。

2 Stack 通常翻译为“堆栈”,为避免与文中出现的“堆/heap”混淆,这里简称为“栈”。

// leave// ret#06 }#07#08 int main()#09 {// push %ebp// mov %esp,%ebp#10 int ret = 0xDEEDBEEF;// sub $0x4,%esp// movl $0xdeedbeef,0xfffffffc(%ebp)#11 ret = add(0x19, 0x82);// push $0x82// push $0x19// call 80482f4 <add>// add $0x8,%esp// mov %eax,0xfffffffc(%ebp)#12 return ret;// mov 0xfffffffc(%ebp),%eax// leave// ret#13 }图表 1 典型的函数调用当程序执行完第10行时,堆栈如图表2所示。

图中每格表示一个double word(4字节)。

图表 2 堆栈状况1EBP是栈帧指针(frame pointer),在整个函数的运行过程中,它始终指向间于返回地址和局部变量之间的一个double word,此处保存着调用端函数(caller)的EBP值(第9行对应的两条指令正是起这个作用)。

EBP所指的位置之下是局部变量,例如EBP-4是变量ret 的地址,-4的补码表示正好是0xFFFFFFFC,第11行上方的movl指令将0xDEEDBEEF 存入变量ret。

当函数返回时,须将EBP恢复原值。

leave指令相当于:mov %ebp, %esp // 先令esp指向saved ebppop %ebp // 弹出栈顶内容至ebp,此时esp正好指向返回地址,ebp也恢复原值ret指令的作用是将栈顶元素(ESP所指之处)弹出至指令指针EIP,完成函数返回动作。

执行第11条语句时,先将add()的两个参数按从右到左的顺序压入堆栈,call指令会先把返回地址(也就是call指令的下一条指令的地址,此处为一条add指令3)压入堆栈,3C语言为了实现变长参数调用(就像printf()),通常规定由调用端负责清理堆栈,这条add指令正是起平衡堆栈的作用。

然后修改指令指针EIP,使程序流程(flow)到达被调用函数处(第2行)。

当程序运行到第4行时,堆栈的情况如图表3所示。

图表 3 堆栈情况2图中灰色部分是main()的栈帧(stack frame,又称活动记录:activation record),其下是add()的栈帧,从中可以看出,保存函数返回地址(return addr)的位置比第一个局部变量高8字节。

由此我们想到,函数可以修改自己的返回地址。

下面我们做一个试验。

// retaddr.c#01 #include <stdio.h>#02#03 void malice()#04 {#05 printf("Hey, you've been attacked.\n");#06 }#07#08 void foo()#09 {#10 int* ret;#11 ret = (int*)&ret + 2; // get the addr of return addr#12 (*ret) = (int)malice; // set my return addr to malice()#13 }#14#15 int main()#16 {#17 foo();#18 return 0;#19 }图表 4 改变函数返回地址图表4列出了一个函数改变自己返回地址的程序,foo()函数将自己的返回地址改为malice()函数。

编译运行这个程序,结果如下:$ gcc retaddr.c -o retaddr -ggdb -mpreferred-stack-boundary=2$ ./retaddrHey, you've been attacked.Segmentation fault (core dumped)core dump 4发生在malice()返回时,我们来分析一下究竟发生了什么。

首先,在进入main()函数后,在执行第17行之前,堆栈情况如图表5-(a)所示,这是main()的栈帧;随后,进入函数foo(),在执行第11行之前,堆栈布局如图表5-(b)所示,灰色部分是调用端main()的栈帧;执行第11行之后,ret 指向函数的返回地址(图表5-(c));第12行修改*ret ,将返回地址设为malice()的入口。

foo()函数结束后,本应返回到main(),执行第18行的语句return 0;然而由于返回地址被修改,foo()函数返回后进入函数malice(),在执行第5行之前,堆栈的情况如图表5-(d)。

这时堆栈已被破坏,malice()函数的返回地址处存放的是main()函数保存的EBP 值(图中的 saved EBP* ),malice()函数返回后,会跳转到 saved EBP* 所指的地址,oops!接下来发生的事情想必大家都知道了☺(a) (b)(c) (d)图表 5 堆栈情况3继续我们的试验:如何让这个程序正常退出?我想到的办法是,利用main()函数的局部变量伪造一个貌似合法的堆栈,让malice()返回后,程序得以安全退出。

办法很简单,在malice()的返回地址处放上exit()的入口地址☺,当然,我们还要顺便伪造传给exit()的参数。

改进后的main()见图表 6。

4如果没有出现core dumped 字样,请先执行 ulimit –c unlimited 。

#02 #include <stdlib.h>#15 int main() #16 {#17 volatile int exit_val = 100; #18 volatile int dumy = 0;#19 volatile void* ret_addr = &exit; #20 foo(); #21 }图表 6 改进后的“修改函数返回地址”示例使用volatile 关键字是为了防止编辑器将这些看似没用的局部变量优化掉。

进入函数malice()后,堆栈情况如图表 7-(a)所示。

与图表 5-(d)比较可知,malice()会把ret_addr作为自己的返回地址,我们已在此处填上了exit()的入口地址。

当malice()返回后,程序进入exit()函数,这时堆栈如图表 7-(b)所示(注意,exit()没有保存ESP )。

exit()函数会把100认为是传递给自己的参数,还会认为返回地址是0,但是exit()永不返回,所以不会造成core dump ,程序正常结束,返回给操作系统的代码是100。

(a) (b)图表 7 堆栈情况4有了以上对函数调用栈的了解,接下来,我们可以谈谈栈上的缓冲区溢出了。

利用缓冲区溢出,我们能 1) 自由修改EIP ,控制程序流程;2) 植入shellcode ,获得root shell 。

所谓shellcode ,是指能调出shell 的程序,功能如同shellcode1.c (图表 8)。

#01 #include <unistd.h>#02#03 int main() #04 {#05 char* name[2]; #06#07 setuid(0); // required if bash is used #08 name[0] = "/bin/sh"; #09 name[1] = NULL;#10 execve(name[0], name, NULL); #11 return 0; #12 }图表 8 shellcode1.c如果以root权限执行这段程序,我们就能获得一个root shell,Wow! 先试一把:$ gcc -o shellcode1 shellcode1.c$ whoamischen$ ./shellcode1sh-2.05b$ whoamischen咦?怎么没有变身root?噢,忘了将shellcode1的owner设为root,还要设置suid位:$ sudo chown root shellcode1$ sudo chmod +s shellcode1$ whoamischen$ ./shellcode1sh-2.05b# whoamirootsh-2.05b# id// 不放心,再确认一下☺uid=0(root) gid=500(schen) groups=500(schen)当然,我们不能直接使用图表8中的程序,需要把它转换为机器码,再注入缓冲区。

相关文档
最新文档