版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第9章
缓存区溢出攻防9内容安排缓冲区溢出概述缓冲区溢出原理缓冲区溢出攻击的方式缓冲区溢出攻击演练缓冲区溢出攻击的防范9.1缓冲区溢出概述缓冲区(buffer)缓冲区溢出(bufferoverflow)在内存中预留的指定大小的存储空间,用来缓冲输入或输出的数据(即临时存储)。由于程序设计的缺陷,向缓冲区中写入的数据超过缓冲区所能容纳的最大容量,使得写入的数据超过了定义的内存边界,从而将数据写进其他区域。对于缓冲区溢出,一般可以分为4种类型,即栈溢出、堆溢出、BSS溢出与格式化字符串溢出。9.1缓冲区溢出概述缓冲区溢出攻击缓冲区溢出危害攻击者故意将大于缓冲区定义长度的数据写入到缓冲区,覆盖其他区域的数据,以达到攻击目的的操作。缓冲区溢出已经成为一种十分普遍和危险的安全漏洞,存在于各种操作系统和应用软件中。攻击者可以通过缓冲区溢出攻击更改缓冲区的数据、注入恶意代码、改变程序的控制权、使未授权的用户获得管理员权限,以致可以非法执行任意代码。9.1缓冲区溢出概述
程序在内存中的存放形式5程序运行时,程序是分别加载到内存中几个内存分区的,包括代码段、数据段、BSS段(BlockStartedbySymbol)、堆(Heap)和栈(Stack)。操作系统内核空间用户进程不能对该区域读写高地址
栈
堆
BSS段数据段代码段低地址代码段又叫文本段,主要存放可执行代码,可读不可写。数据段存放已初始化的变量,包括已经初始化的静态变量、全局变量以及常量。BSS段存放没有初始化的全局变量和静态变量。堆用来存放在程序中动态申请的内存区域,由程序员分配(malloc)和释放(free)。栈存放函数的局部变量、函数参数、返回数据和返回地址等,由编译器分配释放。9.1缓冲区溢出概述
程序在内存中的存放形式9.1缓冲区溢出概述
程序在内存中的存放形式9.1缓冲区溢出概述
堆和栈的区别栈堆分配方式不同有静态分配和动态分配,静态分配由编译器完成,如局部变量分配;动态分配由malloc函数分配由程序员动态分配,没有静态分配。管理方式不同由编译器自动申请和释放由程序员手动申请和释放产生碎片不同不存在碎片问题频繁执行malloc()或free()会造成内存空间的不连续,形成大量的碎片内存地址增长的方向不同栈是向着内存地址减小的方向增长,由内存的高地址向低地址方向增长堆是向着内存地址增加的方向增长的,即从内存的低地址向高地址方向增长分配效率不同由机器系统提供的数据结构,计算机在底层提供对栈的支持,分配专门的寄存器和指令,速度快。由库函数提供,按一定算法搜索内存,速度慢。空间大小不同空间有限,32位平台下,VC6默认为1M最大可支持4G9.1缓冲区溢出概述
堆和栈的区别需要注意进程的栈由多个栈帧构成,其中每个栈帧都对应一个函数调用。当函数调用发生时,新的栈帧被压入栈;当函数返回时,相应的栈帧从栈中弹出。尽管栈帧结构的引入为在高级语言中实现函数或过程这样的概念提供了直接的硬件支持,但是由于需要将函数返回地址等重要数据保存在程序员可见的堆栈中,因此也给系统安全带来了极大的隐患。当程序写入超过缓冲区的边界时,就会产生所谓的“缓冲区溢出”。发生缓冲区溢出时,就会覆盖下一个相邻的内存块,导致程序发生一些不可预料的结果:也许程序可以继续,也许程序的执行出现奇怪现象,也许程序完全失败或者崩溃等。9.2缓冲区溢出原理栈溢出栈溢出是缓冲区溢出的一种。函数的局部变量等通常保存在栈上,如果这些缓冲区发生溢出,就是栈溢出。如果攻击者能任意覆盖栈上的数据,就意味着他能修改程序的执行流程,从而可造成更大的破坏,这就是栈溢出攻击。栈是从高地址到低地址增长的,而程序中缺少错误检测另外对缓冲区的潜在操作(比如字符串的复制)都是从内存低地址到高地址,而函数调用的返回地址往往就在缓冲区的上方(当前栈底),这为覆盖返回地址提供了条件。9.2缓冲区溢出原理分析:有什么问题?栈溢出voidfun(unsignedchar*data){ unsignedcharbuffer[BUF_LEN];
strcpy((char*)buffer,(char*)data);//溢出点}一个简单的例子strcpy():实现字符串复制会将data的全部数据拷贝到buffer指向的内存区域。buffer的长度是有限的,一旦data的数据长度超过BUF_LEN,便会产生缓冲区溢出。9.2缓冲区溢出原理由于栈向低地址方向增长,局部数据buffer的指针在缓冲区的下方。当把data的数据复制到buffer时,超过缓冲区的高地址部分数据会覆盖原本的栈数据,产生栈溢出。9.2缓冲区溢出原理①覆盖了其他的局部变量。如果被覆盖的局部变量是条件变量,那么可能会改变函数原本的执行流程。这种方式可以用于破解简单的软件验证。根据覆盖数据的内容不同,可能会产生以下情况:②覆盖了基址寄存器ebp的值。修改了函数执行结束后要恢复的栈指针,将会导致栈帧失去平衡。③覆盖了返回地址。这是栈溢出原理的核心所在,通过覆盖修改函数的返回地址,使程序代码执行“意外”的流程。④覆盖参数变量。修改函数的参数变量也可能改变当前函数的执行结果和流程。⑤覆盖上级函数的栈值,情况与第4点类似,只不过影响的是上级函数的执行。9.2缓冲区溢出原理通过计算返回地址内存区域相对于buffer的偏移,并在被覆盖返回地址处构造新的返回地址指向buffer内部二进制代码的实际位置,便能执行用户的自定义代码。这段既是代码又是数据的二进制数据被称为shellcode。因为攻击者希望通过这段代码打开系统的shell,以执行任意的操作系统命令——比如下载病毒、安装木马、开放端口、格式化磁盘等恶意操作。9.2缓冲区溢出原理①
编译器方面,采用Canary机制防护栈溢出攻击,即在栈上放置一个标志Canary,然后在函数结束时,判断该标志是否改变,如果改变,则表示有攻击行为发生。②操作系统方面,
Windows系列操作系统中增加了SEHOP(结构化异常处理覆盖保护),增强系统安全性。Canary的意思是金丝雀,来源于英国矿井工人用来探查井下气体是否有毒的金丝雀笼子。工人们每次下井都会带上一只金丝雀。如果井下的气体有毒,金丝雀由于对毒性敏感就会停止鸣叫甚至死亡,从而使工人们得到预警。栈溢出的检查与防范③
硬件方面,64位CPU中引入了NX(No-eXecute)硬件机制,在内存中区分数据区与代码区,当攻击使CPU跳转到数据区去执行时,就会异常终止。9.2缓冲区溢出原理堆溢出不同于栈,堆是程序运行时动态分配的内存,用户通过malloc、new等函数申请内存,通过返回的起始地址指针对分配的内存进行操作,使用完后要通过free、delete等函数释放这部分内存,否则会造成内存泄露。堆的操作分为分配、释放、合并三种。因为堆在内存中位置不固定,大小比较自由,多次申请、释放后可能会更加凌乱,系统从性能、空间利用率还有安全角度出发,来管理堆,具体实现比较复杂。9.2缓冲区溢出原理堆溢出系统根据大小不同维护一系列的堆块,如下图所示。堆块分为块首和数据区,其中空闲堆块数据区的前两个双字(DWORD)分别是双向链表的两个指针。通常同样大小的空闲堆块通过双向链表连接在一起,分配与释放堆,分别对应插入与删除双向链表节点的操作,而合并则会同时进行着两种操作。空闲堆块中两个指针“Previousblock”和“Nextblock”,分别指向双向链表中此堆块的前后两个堆块的数据部分。分配一个堆块时,将分配堆块从空闲堆块双链表中删除,会有如下所示的操作:voidDeleteBlock(DListBlock*p){p->next->previous=p->previous;p->previous->next=p->next;}9.2缓冲区溢出原理堆溢出同一个堆中的堆块在内存中通常是连续的,由此可能发生这样的情况:在向一个已分配堆块中写入数据时,由于数据长度超出了该堆块的大小,导致数据溢出覆盖堆块后方(高地址处)的相邻空闲堆块,而包含的两个堆块指针(即Previousblock和Nextblock)会被覆盖。9.2缓冲区溢出原理堆溢出假设有空闲堆块*p,则p->previous是指向双向链表中的p的前一堆块的前向指针,p->next是后向指针。若p的两个堆块指针被覆盖,即p->previous=X,p->next=Y。如果这个空闲堆块被分配出去,需要将这个节点从空闲堆块链表中删除,那么分配过程中的DeleteBlock函数就会将p下一个空闲的前向指针(p->next->previous)指向p之前的空闲块前向指针(p->previous)。需要注意的是:每个堆块指针指向的就是堆块的Previousblock。所以p->next->previous相当于对Y进行解引用,即*Y,因此执行的效果就是*Y=X。从而可以利用超长数据覆盖空闲堆块的这两个指针,达到向Y指向的任意地址处写入X包含的任意内容的目的。9.2缓冲区溢出原理堆溢出涉及内存链表操作的堆内存分配、释放、合并操作都可能实现这一效果,即向攻击者任意指定地址写入4字节的任意内容,称之为“arbitraryDWORDreset”或者“DWORDShoot”攻击。在得到一个将指定内存地址改写为任意值的机会后,攻击者可以写出利用的程序,用于覆盖内存堆中的一些函数指针地址、C++类对象虚函数表、GOT全局偏移表入口地址或者DTORS地址等,而改写的值就是指向内存中的Shellcode的地址。此外,还可以通过HeapSpray攻击实现堆溢出攻击。9.2缓冲区溢出原理堆溢出HeapSprayHeapSpray是在shellcode的前面加上大量的slidecode(滑板指令),组成一个注入代码段。然后向系统申请大量内存,并且反复用注入代码段来填充。这样就使得进程的地址空间被大量的注入代码所占据。然后结合其他的漏洞攻击技术控制程序流,使得程序执行到堆上,最终将导致shellcode的执行。slidecode传统slidecode(滑板指令)一般是NOP指令,但是一些攻击技术逐渐使用更多的类NOP指令,譬如0x0C(0x0C0C代表的x86指令是ORAL0x0C),0x0D等等,不管是NOP还是0C,他们的共同特点就是不会影响shellcode的执行。值得注意的是,HeapSpray只是一种辅助技术,需要结合其他的栈溢出或堆溢出等溢出技术才能发挥作用。9.2缓冲区溢出原理BSS溢出BSS段存放全局和静态的未初始化变量,其分配比较简单,变量与变量之间是连续存放的,没有间隔空间。#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<string.h>#include<errno.h>#defineERROR-1#defineBUFSIZE169.2缓冲区溢出原理intmain(intargc,char**argv){ u_longdiff; intoversize; staticcharbuf1[BUFSIZE],buf2[BUFSIZE]; if(argc<=1) {
fprintf(stderr,"Usage:%s<numbytes>\n",argv[0]);
fprintf(stderr,"[Willoverflowstaticbufferby<numbytes>]\n");
exit(ERROR); } BSS溢出9.2缓冲区溢出原理
diff=(u_long)buf2-(u_long)buf1;
printf("buf1=%p,buf2=%p,diff=0x%x(%d)bytes\n\n",
buf1,buf2,
diff,diff);
memset(buf2,'A',BUFSIZE-1),memset(buf1,'B',BUFSIZE-1);buf1[BUFSIZE-1]='\0',buf2[BUFSIZE-1]='\0';
printf("beforeoverflow:buf1=%s,buf2=%s\n",buf1,buf2);
oversize=diff+atoi(argv[1]);
memset(buf1,'B',oversize);
buf1[BUFSIZE-1]='\0',buf2[BUFSIZE-1]='\0';
printf("afteroverflow:buf1=%s,buf2=%s\n\n",buf1,buf2);
return0;}[warning3@testserverbasic]$./heap28buf1=0x8049874,buf2=0x8049884,diff=0x10(16)bytesbeforeoverflow:buf1=BBBBBBBBBBBBBBB,buf2=AAAAAAAAAAAAAAAafteroverflow:buf1=BBBBBBBBBBBBBBB,buf2=BBBBBBBBAAAAAAA说明buf1和buf2是紧挨着的,不用猜测buf1和buf2间的间距。在程序的地址空间里安排适当的代码;通过适当的初始化寄存器和存储器,让程序跳转到安排好的地址空间执行。9.3缓冲区溢出攻击的方式缓冲区溢出漏洞可以使任何一个有黑客技术的人取得机器的控制权甚至是最高权限。黑客要达到目的通常要完成两个任务:9.3缓冲区溢出攻击的方式当向要攻击的程序里输入一个字符串时,程序就会把这个字符串放到缓冲区里,这个字符串包含的数据是可以在这个攻击目标的硬件平台上运行的指令序列。①在程序的地址空间里安排适当的代码如果要攻击的代码在所攻击程序中已经存在,那就对代码传递一些参数,使程序跳转到目标去执行就可以完成。很多时候攻击的代码不能从被攻击程序中找到,这就得用“植入法”的方式来完成。缓冲区可以设在堆栈、堆和静态数据区等的任何地方;也可以不必溢出任何缓冲区,只要找到足够的空间来放置这些攻击代码,然后再寻找适当的机会使程序跳转到其所安排的这个地址空间。9.3缓冲区溢出攻击的方式②
控制程序转移到攻击代码缓冲区溢出漏洞攻击都是在寻求改变程序的执行流程,使它跳转到攻击代码,基本思路就是溢出一个没有检查或者有其他漏洞的缓冲区,扰乱程序的正常执行次序。原则上来讲攻击时所针对的缓冲区溢出的程序空间可为任意空间。但因不同位置程序空间的突破和内存空间的定位差异,产生了多种转移方式。函数指针激活记录长跳转缓冲区植入综合代码和流程控制9.4缓冲区溢出攻击演练基本概念栈是一种基本的数据结构,具有后入先出(LastInFirstOut,LIFO)的特性。调用函数时实际参数、返回地址与局部变量都位于栈上,栈是自高向低增长(先入栈的地址较高),栈指针寄存器ESP始终指向栈顶元素。当程序中发生函数调用时,计算机操作如下:把指令寄存器EIP(它指向当前CPU将要运行的下一条指令的地址)中的内容压入栈,作为程序的返回地址(下文中用RET表示);放入栈的是基址寄存器EBP,它指向当前函数栈帧的底部;然后把当前的栈指针ESP复制到EBP,作为新的基地址;为本地变量的动态存储分配留出一定空间,并把ESP减去适当的数值。9.4缓冲区溢出攻击演练charc[]="AAAAAAAAAAAAAAAA";intmain(void){chararr[8];/*执行复制,如果c长度超过8,则出现缓冲区溢出*/strcpy(arr,c);for(inti=0;i<8&&arr[i];i++){
printf("\\0x%x",arr[i]);}printf("\n");return0;}定义了一个8字节的缓冲区arr[8],然后使用函数strcpy来将数组c的内容复制到该缓冲区中。例如下面一段代码演示了程序在执行过程中对栈的操作和溢出的产生过程。9.4缓冲区溢出攻击演练由于数组c中的数据长度超过了8字节,数组arr容纳不下,只好向栈的底部方向继续写入“A”。因此,数组c中的数据依次覆盖了EBP和返回地址RET(两个都是32位的,占用4字节),使得strcpy函数返回后的EIP指向0x41414141(0x41414141也就是“AAAA”的ASCII码)。很显然,地址0x41414141是非法的,CPU会试图执行0x41414141处的指令,结果出现难以预料的后果,所以程序会出现异常而退出,如下图所示。9.4缓冲区溢出攻击演练在上面的示例代码中,程序把函数返回后的EIP修改成0x41414141,这是因为数组c中的数据“AAAA”将返回地址覆盖了的结果。其中,“A”对应的ASCII码的十六进制表示是41,因此,“AAAA”就是0x41414141。为了验证这个事实,现在继续将数组c中的最后4个元素(覆盖返回地址的部分)改成“ABCD”,示例代码如下所示:charc[]="AAAAAAAAAAAAABCD"9.4缓冲区溢出攻击演练现在再次运行上面的示例代码,其运行结果如下图所示。这时EIP被修改成0x44434241,对应的是“DCBA”,与覆盖的数据是相反的。这是因为在Windows32系统中由低位向高位存储一个4字节的双字(DWORD),但作为数值表示的时候,却是按照高位字节向低位字节进行解释的,所以,内存地址与逻辑上使用的“数值数据”的顺序相反。如果这时候能够把EIP修改指向特定代码,就可以接管程序的控制权,从而做任何事情。9.4缓冲区溢出攻击演练charshellcode[]="\x41\x41\x41\x41""\x41\x41\x41\x41"/*覆盖ebp*/"\x41\x41\x41\x41"/*覆盖eip,jmpesp地址7ffa4512*/"\x12\x45\xfa\x7f""\x55\x8b\xec\x33\xc0\x50\x50\x50\xc6\x45\xf4\x6d""\xc6\x45\xf5\x73\xc6\x45\xf6\x76\xc6\x45\xf7\x63""\xc6\x45\xf8\x72\xc6\x45\xf9\x74\xc6\x45\xfa\x2e""\xc6\x45\xfb\x64\xc6\x45\xfc\x6c\xc6\x45\xfd\x6c""\x8d\x45\xf4\x50\xb8"/*LoadLibrary的地址*/"\x77\x1d\x80\x7c""\xff\xd0""\x55\x8b\xec\x33\xff\x57\x57\x57\xc6\x45\xf4\x73“"\xc6\x45\xf5\x74\xc6\x45\xf6\x61\xc6\x45\xf7\x72"9.4缓冲区溢出攻击演练"\xc6\x45\xf8\x74\xc6\x45\xf9\x20\xc6\x45\xfa\x63“"\xc6\x45\xfb\x6d\xc6\x45\xfc\x64\x8d\x7d\xf4\x57""\xba“/*System的地址*/"\xc7\x93\xbf\x77""\xff\xd2";intmain(){chararr[8];strcpy(arr,shellcode);for(inti=0;i<8&&arr[i];i++){printf(
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年6年级上中学考试卷子及答案
- 2026年18法考配套测试题及答案
- 2026年18高考语文试题及答案
- 2026年17旅游概论试题及答案
- 2026年6岁小孩智商测试题及答案
- 2026年9套三基试卷及答案
- 2026年2岁认知测试题及答案
- 2026年16年入党培训测试题及答案
- (正式版)DB43∕T 1588.31-2019 《小吃湘菜 第31部分:古丈蒿草粑》
- 办公耗材采购与使用管理指南
- GB/T 42609-2023煤粉给料三通换向阀
- 成人机械通气患者俯卧位护理-中华护理学会团体标准
- 年产30万吨合成氨脱碳工段工艺设计
- 优选文档压裂压力诊断PPT
- FZ/T 52010-2014再生涤纶短纤维
- 电力系统简介课件
- 电力公司新竹区营业处课件
- 建筑废土处置方案
- 医院内部控制手册
- 香蕉组培快繁生产过程
- 新沪教牛津版七年级下册英语Unit 1 More practice-Cultural corner课件
评论
0/150
提交评论