您好,欢迎访问三七文档
第五章缓冲区溢出攻击5第五章缓冲区溢出攻击5.1缓冲区溢出程序的原理及要素5.2攻击UNIX5.3缓冲区溢出攻击概述55.4攻击Windows•缓冲区溢出是一种非常普遍、非常危险的漏洞,在各种操作系统、应用软件中广泛存在。利用缓冲区溢出攻击,可以导致程序运行失败、系统宕机、重新启动等后果。更为严重的是,可以利用它执行非授权指令,甚至可以取得系统特权,进而进行各种非法操作。5.1缓冲区溢出攻击概述•缓冲区溢出攻击有多种英文名称:bufferoverflow,bufferoverrun,smashthestack,trashthestack,scribblethestack,manglethestack,memoryleak,overrunscrew;它们指的都是同一种攻击手段。•第一个缓冲区溢出攻击—Morris蠕虫,发生在1988年,它曾造成了全世界6000多台网络服务器瘫痪。5.1缓冲区溢出攻击概述缓冲区溢出攻击概述•莫里斯蠕虫病毒–1988年,美国康奈尔大学的计算机科学系研究生、23岁的莫里斯利用Unixfingerd程序不限制输入长度的漏洞,输入512个字符后使缓冲器溢出,同时编写一段特别大的恶意程序能以root(管理员)身份执行,并感染到其他机器上。–它造成全世界6000多台网络服务器瘫痪。5.1–1996•AlephOne,SmashingtheStackforFunandProfit,Phrack49–1998•Dildog:提出利用栈指针的方法完成跳转•TheTaoofWindowsBufferOverflows–1999•DarkSpyrit:提出使用系统核心DLL中的JmpESP指令完成跳转,Phrack55•M.Conover:基于堆的缓冲区溢出教程5.1缓冲区溢出攻击概述–2001年始,微软的IIS5.0一系列的漏洞被发现,其中不少漏洞是由于Unicode的处理问题造成的,在攻击利用的时候与Windows所支持的语言字符集密切相关。(《Widechar的字符串缓冲区溢出攻击技术》)–2003年8月引起全球轰动的“冲击波”病毒及变种,也是利用WindowsRPC服务的缓冲区溢出漏洞来进行传播的。–2004年5月的“震荡波”病毒及变种也是利用了Windows系统的缓冲区漏洞。–目前5.1缓冲区溢出攻击概述缓冲区溢出攻击概述•定义–缓冲区溢出攻击是一种通过往程序的缓冲区写超出其长度的内容,造成缓冲区溢出,从而破坏程序的堆栈,使程序转而执行其他预设指令,以达到攻击目的的攻击方法。•分类–基于堆栈的缓冲区溢出(栈溢出)–基于Heap/BSS的缓冲区溢出5.1缓冲区溢出程序原理及要素•缓冲区溢出程序的原理–众所周知,C语言不进行数组的边界检查。–在许多C语言实现的应用程序中,都假定缓冲区的长度是足够的,即它的长度肯定大于要拷贝的字符串的长度。事实并非如此5.2缓冲区溢出程序原理及要素5.2例1:#includestdio.hvoidfunction(char*str){charbuffer[9];strcpy(buffer,str);}voidmain(){char*input=1234567890;function(input);}缓冲区溢出程序原理及要素5.2例2:#includestdio.hintmain(){charname[8];printf(pleasetypeyourname:);gets(name);printf(hello,%s!,name);return0;}•在C语言中,指针和数组越界不保护是Bufferoverflow的根源。•在C语言标准库中存在像strcpy,gets这样问题的标准函数还有strcat(),sprintf()和scanf()等。•要透彻地理解这种攻击方式,需要计算机体系架构方面的基础知识,理解CPU、寄存器、内存是怎样协同工作而让程序流畅执行的。5.2缓冲区溢出程序原理及要素缓冲区溢出程序原理及要素•缓冲区溢出攻击背景知识与技巧–进程内存空间结构–汇编语言基本知识–栈的基本结构–函数调用过程–编译器5.2进程内存空间结构•根据不同的操作系统,一个进程可能被分配到不同的内存区域去执行。但是不管什么样的操作系统、什么样的计算机架构,进程使用的内存都可以按照功能大致分成以下4个部分:–代码区:这个区域存储着被装入执行的二进制机器代码,处理器会到这个区域取指并执行。–数据区:用于存储全局变量等。进程内存空间结构•堆区:进程可以在堆区动态地请求一定大小的内存,并在用完之后归还给堆区。•栈区:用于动态地存储函数之间的调用关系,以保证被调用函数在返回时恢复到调用函数中继续执行。Linux进程内存空间结构17Linux进程内存空间•Highestzone(0xc0000000-3G)–进程环境参数:envstrings&pointers–进程参数:argvstrings&pointers,argc•栈–存储函数参数、本地参数和栈状态变量(返回地址,…)–LIFO,向低地址增长•堆–动态分配变量(malloc)–向高地址增长•.bss:uninitializeddata•.data:staticinitializeddata•.text(0x80000000):指令,只读数据Win32进程内存空间19Win32进程内存空间•系统核心内存区间–0xFFFFFFFF~0x80000000(4G~2G)–为Win32操作系统保留•用户内存区间–0x00000000~0x80000000(0G~2G)–堆:动态分配变量(malloc),向高地址增长–静态内存区间:全局变量、静态变量–代码区间:从0x00400000开始–栈:向低地址增长•单线程进程:(栈底地址:0x0012FFXXXX)–多线程进程拥有多个堆/栈汇编语言基础知识-寄存器汇编语言基础知识-汇编指令22栈的基本结构•栈-LIFO抽象数据结构–用于实现函数或过程调用•相关寄存器–BP(BasePointer)=FP(FramePointer):当前栈底指针–SP(StackPointer):当前栈顶指针•相关操作–PUSH:压栈–POP:弹栈23函数调用过程•函数调用过程的三个步骤–prologue:保存当前的栈基址(ebp).–call:调用参数和返回地址(eip)压栈,跳转到函数入口–return(orepilogue):恢复调用者原有栈函数调用示例intfunc_B(intarg_B1,intarg_B2){intvar_B1,var_B2;var_B1=arg_B1+arg_B2;var_B2=arg_B1-arg_B2;returnvar_B1*var_B2;}intfunc_A(intarg_A1,intarg_A2){intvar_A;var_A=func_B(arg_A1,arg_A2)+arg_A1;returnvar_A;}intmain(intargc,char**argv){intvar_main;var_main=func_A(4,3);returnvar_main}这段代码编译后,各个函数对应的机器指令在代码区中可能是这样分布的(我们可以简单地把它们在内存代码区中的分布位置理解成是散乱无关的)。缓冲区溢出程序原理及要素•第一种方法:–通过溢出改写邻接变量,导致程序流程发生改变。–这种漏洞利用方法对代码环境的要求相对比较苛刻。–例子:突破密码验证程序。#includestdio.h#definePASSWORD1234567intverify_password(char*password){intauthenticated;charbuffer[8];//addlocalbufftobeoverflowedauthenticated=strcmp(password,PASSWORD);strcpy(buffer,password);//overflowedhere!returnauthenticated;}voidmain(){intvalid_flag=0;charpassword[1024];while(1){printf(pleaseinputpassword:);scanf(%s,password);valid_flag=verify_password(password);if(valid_flag){printf(incorrectpassword!\n\n);}else{printf(Congratulation!Youhavepassedtheverification!\n);break;}}}这段代码执行到intverify_password(char*password)时的栈帧状态如下图所示。分析:在verify_password函数的栈帧中,局部变量authenticated恰好位于缓冲区buffer[8]的“下方”。authenticated为int类型,在内存中占4个字节。所以,如果能够让buffer数组越界,buffer[8]、buffer[9]、buffer[10]、buffer[11]将写入相邻的变量authenticated中。如果我们输入的密码超过了7个字符(注意:字符串截断符NULL将占用一个字节),则越界字符的ASCII码会修改掉authenticated的值。如果这段溢出数据恰好把authenticated改为0,则程序流程将被改变。缓冲区溢出程序原理及要素•第二种方法:–修改程序的返回地址,让它去执行一段精心准备的恶意代码。–具体包括:•得到‘有问题程序’返回点的精确位置。•编写一个恶意代码。•将返回点的地址覆盖成装载有恶意代码的地址。缓冲区溢出程序原理及要素缓冲区溢出程序原理及要素•上述攻击中的“恶意代码”被称为ShellCode或者Payload。•ShellCode的作用:获得操作系统的操作权。•ShellCode的形式charshellcode[]=\xeb\x18\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xec\xff\xff\xff/bin/sh;操作系统的Shell•操作系统中用户与操作系统的交互方式(通过命令行的方式)–Linux中叫做“Shell”,一般为“/bin/sh”–Windows中称作“命令提示符”,为“cmd.exe”•因此ShellCode一般在操作系统Shell中运行命令–如:文件操作、帐号操作等缓冲区溢出程序原理及要素•关键技术–在程序的地址空间安排适当的代码(ShellCode的编写)–将控制程序转移到攻击代码的方式•FunctionPointersOverwrite(覆盖函数指针)•ActivationRecords(覆盖函数调用的返回地址)•Longjmpbuffers(利用跳转指令)•植入码和流程控制(覆盖函数栈)–可执行的地址空间•代码段/数据段/堆栈段SHELLCODE的定位•在1999年之前,很多人提出了不少方法来定位ShellCode,但都不太精确。–例如,–NNNNNNSSSSSSSSSSSRRRRRRRR型。–适合于大缓冲区,“N”代表空指令,在实际运行中,程序将什么也不做,而是一直沿着这些NOPS运行下去,直到遇到不是NOPS的指令再执行之;“S”代表ShellCode;“R”代表覆盖的返回地址,思路是把返回地址R覆盖为NOPS的大概位置,这样就会跳到Nop中,然后继续执行,直到我们的ShellCode中。SHELLCODE的定位•RRRRRRNNNNNSSSSS型。思路是用大量的“R”填满整个缓冲区,然后大量的Nop,最后是ShellCode。这里,“R”往后跳到Nop中,再顺着往下执行就会到ShellCode中。但在Windows下,“R”中必定会含有0,这样,整个构造就会被截断,只能用于Unix中。SHELLCODE的定
本文标题:网络安全第六讲
链接地址:https://www.777doc.com/doc-1794656 .html