缓冲区溢出攻击_第1页
缓冲区溢出攻击_第2页
缓冲区溢出攻击_第3页
缓冲区溢出攻击_第4页
缓冲区溢出攻击_第5页
已阅读5页,还剩57页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、漏洞的公布与0day响应安全专家 发现漏洞 通知厂家的产品安全中心 厂家漏洞确定 补丁测试 正式发布漏洞公告和官方补丁。漏洞先被黑客发现 不通知厂家 写出利用漏洞做任何事情 这种未被公布、修复的漏洞称为0day。掌握0day是少数,但有时会曝光,全世界的黑客都利用它,在厂家官方补丁发布前INTERNET处于高危状态。1微软安全中心微软每月第二周的周二发布补丁(BLACK TUESDAY),许多黑客通宵达旦去研究这些补丁PATCK了哪些漏洞,并写出EXPLOIT,因为在补丁刚发布的一段时间内,并非所有用户能及时修复。公布漏洞的两个权威机构CEV 、CERT。2二进制文件PE(PORTABLE E

2、XECUTABLE)是WIN32平台下可执行文件(EXE、DLL)的数据格式。一个可执行文件除包含二进制的机器代码外,还带有字符串、菜单、图标、位图、字体等,PE文件格式规定了这些信息在可执行文件中如何组织,在程序被执行时,OS会按照PE文件格式的约定去相应的地方精确地定位各种资源,并分别装入内存的不同区域。3PE文件格式PE文件格式把可执行文件分成几个数据节(SECTION),不同的资源存放在不同的节中。TEXT由编译器产生,存放二进制的机器代码,是反汇编和调试的对象。DATA初始化的数据块,如宏定义、全局变量、静态变量等。IDATA可执行文件所使用的动态链接库等外来函数与文件的信息。RSR

3、C存放程序的资源,如图标、菜单等。4PE文件格式其他的节RELOCEDATATLSRDATA使用VISUAL C+中的编译指示符#PRAGMA DATA_SEG()可把代码中的任意部分编译到PE的任意节中,节名也可任意定义。如可执行文件经过了加壳处理, PE得节信息会变得古怪,在CRACK和反病毒分析中要经常处理这些古怪的PE文件5虚拟内存WINDOWS的内存分成两个层面:物理内存和虚拟内存。物理内存很复杂,需进入WINDOWS内核级别RING0才能看到。在用户模式,我们用调试器看到的内存地址都是虚拟内存。每个进程都相信自己拥有独立的4GB内存空间。6WINDOWS虚拟内存与物理内存进程1进程

4、1的虚拟内存(4GB)进程2进程3进程2的虚拟内存(4GB)进程3的虚拟内存(4GB)虚拟内存管理器真正的物理内存512M7PE文件与虚拟内存之间的映射在调试漏洞时,要做两件操作(1)用静态反汇编工具看到的PE文件中某条指令的位置是相对于磁盘文件而言的,即所谓的文件偏移,我们还需要知道这条指令在内存中的位置,即虚拟内存地址 (VA)。(2)在调试时看到的摩条指令的地址是虚拟内存地址 ,我们需要回到PE文件中找到这条指令对应的机器码。8PE文件地址与虚拟内存地址之间的映射关系文件偏移地址()数据在PE文件中的地址为文件偏移地址,这是文件在磁盘上存放时相对于文件开头的偏移。装载基址(IMAGE B

5、ASE): PE文件装入内存时的基地址。默认情况下,EXE文件在内存中的基址是0X00400000,DLL文件是0X10000000。这些位置可通过修改编译选相更改。9PE文件地址与虚拟内存地址之间的映射关系虚拟内存地址(VIRTUAL ADDRESS,VA) PE文件中的指令被装入内存后的地址。相对虚拟地址(RELATIVE VIRTUAL ADDRESS,RVA)相对虚拟地址是内存地址相对于映射基址的偏移量。他们间的关系:VA= IMAGE BASE+RVA10PE文件与虚拟内存的映射关系PE文件 内存其他DATA节RDATA节TEXT节文件头、节表等DATA节RDATA节TEXT节文件头

6、、节表等PE文件起始0字节0X200字节0X200字节0X200字节装载基址0X004000000X1000字节0X1000字节0X1000字节11PE文件与虚拟内存的映射关系在上图中,在默认情况下,一般PE文件的0字节将映射到虚拟内存的0X00400000位置,即为装载基址(IMAGE BASE)。文件偏移是相对于文件开始处0字节的偏移,RVA是相对于装载基址0X00400000处的偏移,OS在装载时基本上保持PE中的各种数据结构,所以文件偏移地址和RVA有很大的关系。12基本的理由PE文件中的数据按照磁盘数据标准存放,以0X200字节为基本单位进行组织。一个数据节(SECTION)不足0X

7、200字节时,以0X00填充,因此PE数据节的大小是0X200的整数倍。同理,当代码装入内存后,按照内存数据标准存放,以0X1000字节为基本单位进行组织,因此内存中的数据节的大小是0X1000的整数倍。13节偏移由于内存中数据节相对于装载基址的偏移量和文件中数据节的偏移量有上述差异,在进行文件偏移到虚拟内存地址之间的换算时要考虑到所转换的地址位于第几个节中。这种由存储单位差异引起的节基址差称为节偏差14转换关系文件偏移地址=虚拟内存地址(VA) -装载基址(IMAGE BASE)-节偏移=RVA-节偏移一些PE工具提供了这类地址转换,如LORD PE,他也可用来查看PE文件中的节信息。15系

8、统栈的工作原理内存的不同用途缓冲区溢出就是在大缓冲区中的数据向小缓冲区复制的过程中,由于没注意小缓冲区的边界,”撑破“了较小的缓冲区,从而覆盖了与小缓冲区相邻内存区域的其他数据而引起的内存问题。缓冲区溢出是攻击者入侵系统时所用到的最强大、最经典的一种漏洞利用方式。利用缓冲区溢出漏洞可以修改内存中变量的值,可以劫持进程,执行恶意代码,最终控制主机。16理解缓冲区溢出攻击的条件CPU、寄存器、内存的协同工作让程序流畅地执行。17内存的不同用途不同的OS,一个进程可被分配到不同的内存区域去执行,但进程使用的内存可按功能大致分成4个部分。代码区:存储被装入执行的二进制机器代码,处理器会到这个区域取指令

9、并执行。数据区:存储全局变量等。堆区:进程可在堆区动态请求一定大小的内存,并在用完后还给堆区,是动态分配和回收。18内存的不同用途栈区:用于动态地存储函数之间的调用关系,以保证被调用函数在返回时恢复到母函数中继续执行。深入理解程序的运行机制,请参阅深入理解计算机系统一书。在WINDOWS平台,高级语言写的程序经过编译连接后变成了PE文件。当PE文件被装载运行后,就成了所谓的进程。19程序运行的协作过程PE文件代码段中包含的二进制机器代码会被装入内存的代码区(TEXT),处理器会到内存的这个区域一条一条地取出指令和操作数,并送入算术逻辑单元进行运算。如代码请求开辟动态内存,则会在内存的堆区分配一

10、块大小合适的区域返回给代码区的代码使用。如函数调用发生时,函数的调用关系等信息会动态地保存在内存的栈区,以供处理器在执行完被调用函数的代码时,返回母函数。20协作过程PE文件装载运行-XOR EBX,EBXMOV BH,4SUB ESP,EBPMOV BX,3234PUSH EBXPUSH 723456PUSH ESPXOR EDX,EDX-进程的虚拟内存空间堆数据区(全局变量)当前函数的栈帧函数栈帧函数栈帧函数栈帧-函数栈帧ESPEBPEIP21缓冲区的分类进程中所用的缓冲区可以是堆区、栈区和存放静态变量的数据区。缓冲区溢出的利用方法和缓冲区到底属于上面哪个内存区域密不可分,我们主要针对系统

11、栈的情形。22栈与系统栈 栈是一种数据结构,是一种先进后出的数据表,他有两种常见操作:压栈(PUSH)、弹栈(POP),标示栈顶(TOP),栈低(BASE)。内存的栈区实际上指的就是系统栈 ,由系统自动维护,它用于实现高级语言中函数的调用,对类C的高级语言来说, PUSH和POP是透明的,在用汇编语言设计程序时,才需和它直接打交道。23函数调用时发生了什么先看一段代码:intfunc_B(int arg_B1, int arg_B2)int var_B1, var_B2;var_B1=arg_B1+arg_B2;var_B2=arg_B1-arg_B2;return var_B1*var_B2

12、;intfunc_A(int arg_A1, int arg_A2)int var_A;var_A = func_B(arg_A1,arg_A2) + arg_A1 ;return var_A;int main(int argc, char *argv, char *envp)int var_main;var_main=func_A(4,3);return var_main;24机器指令在代码区中的分布上段代码经过编译器编译后,各个对应的机器指令在代码区中可能是这样分布的-(其他指令)-(FUNC_A的指令)-(MAIN函数指令)-(其他指令)-FUNC_B的指令-25机器指令在代码区中的分布

13、依据OS的不同,编译器和编译选项的不同,同一文件不同函数的代码在内存代码区中的分布可能相邻,也可能相离甚远,可能先后有序,也可能无序,但他们都在同一个PE文件的代码所影射的一个节里。当CPU在执行调用FUNC_A函数时,会从代码区中MAIN函数对应的机器指令的区域跳转到FUNC_A函数对应的机器指令区域,在那里取指并执行;当FUNC_A函数执行完毕,需返回时,又会跳回到MAIN函数对应的机器指令区域,紧接着调用FUNC_A函数后面的指令继续执行MAIN函数的代码。26CPU在代码区中的取指轨迹MAIN函数入口-CALL FUNC_A后继的指令-返回指令FUNC_B函数入口-返回指令FUNC_A

14、函数入口-CALL FUNC_B后继的指令-返回指令返回到上层函数的代码空间,紧接着执行函数调用的后继指令处理器跳转去FUNC_A的代码空间去继续执行跳转去FUNC_B的代码空间取指执行27系统栈的作用CPU是如何知道要去FUNC_A的代码区取指,在执行完FUNC_A后又是如何知道跳回到MAIN函数(而不是FUNC_B的代码区)? CPU从何得知这些函数的调用及返回信息?在代码区中精确的跳转都是借助系统栈的配合。当函数被调用时,系统栈会为这个函数开辟一个新的栈帧,并把它压入栈中,这个栈帧中的内存空间被它所属的函数独占,是不会和别的函数共享的。当函数返回时,系统栈会弹出该函数所对应的栈帧。28系

15、统栈在函数调用时的变化栈顶方向TOP栈底方向BASEMAIN函数栈帧其他函数栈帧-FUNC_A栈帧局部变量返回地址MAIN函数栈帧其他函数栈帧FUNC_B栈帧局部变量返回地址FUNC_A栈帧局部变量返回地址MAIN函数栈帧其他函数栈帧FUNC_A栈帧局部变量返回地址MAIN函数栈帧其他函数栈帧MAIN函数栈帧其他函数栈帧用弹出的返回地址回溯出上一个函数的代码空间用弹出的返回地址回溯出上一个函数的代码空间29在函数调用过程中系统栈中的操作MAIN函数调用FUNC_A时,首先在自己的栈帧中压入函数返回地址,然后为FUNC_A创建新栈帧并压入系统栈。在FUNC_A调用FUNC_B时,首先在自己的栈帧

16、中压入函数返回地址,然后为FUNC_B创建新栈帧并压入系统栈。在FUNC_B返回时, FUNC_B的栈帧被弹出系统栈, FUNC_A栈帧中的返回地址被露在栈顶,此时处理器按照这个返回地址重新调到FUNC_A代码区中执行。在FUNC_A返回时, FUNC_A的栈帧被弹出系统栈, MAIN函数栈帧中的返回地址被露在栈顶,此时处理器按照这个返回地址跳到MAIN函数代码区中执行。30寄存器与函数栈帧每一个函数独占自己的栈帧空间,当前正在运行的函数的栈帧总是在栈顶。WIN32系统用两个特殊的寄存器来标识位于栈顶的栈帧。ESP:栈指针寄存器(EXTENDED STACK POINTER),其内存放着一个指

17、针,该指针永远指向系统栈最上面一个栈帧的栈顶。EBP:基址指针寄存器(EXTENDED BASE POINTER),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。31寄存器对栈帧的标识作用栈帧1栈帧2栈帧3栈帧-EBPESP栈顶以上的未使用的内存空间栈帧2栈帧3栈帧-EBPESP栈帧1被释放栈顶以上的未使用的内存空间-32函数栈帧ESP和EBP之间的内存空间为当前栈帧, ESP标识了当前栈帧的顶部, EBP标识了当前栈帧的底部。在函数栈帧中,一般包含以下几类重要信息:局部变量:为函数局部变量开辟的内存空间。栈帧状态值:保存前栈帧的顶部和底部(实际上只保存前栈帧的底部),用于在本

18、栈帧被弹出后恢复出上一个栈帧。函数返回地址:33EIP指令寄存器(EXTENDED INSTRUCTION POINTER)其内存放着一个指针,该指针永远指向下一条等待执行的指令地址。如控制了EIP指令寄存器的内容,就控制了进程我们让EIP指向哪里, CPU就会去执行那里的指令。34EIP指令寄存器的作用-XOR EBX,EBXMOV BH,4SUB ESP,EBPMOV BX,3234PUSH EBXPUSH 723456PUSH ESPXOR EDX,EDX-EIPEIP为指令寄存器,永远指向下一条等待执行的指令。 CPU按照EIP寄存器的所指位置取出指令和操作数后,送入算术逻辑单元运算处

19、理。35函数调用约定与相关指令函数调用约定描述了函数传递参数方式和栈协同工作的细节。约定:传递参数方式,参数入栈次序,函数返回时恢复堆栈平衡的操作在母还是子函数中进行等。36函数调用约定对于VISUAL C+来说,可支持3种函数调用约定。VC在默认情况下使用_STDCALL调用方式。同段代码不同的编译选项、不同的编译器编译链接后,得到的可执行文件有很多不同。调用约定的声明参数入栈次序恢复堆栈平衡的操作_CDECL右左母函数_FASTCALL右左子函数_STDCALL右左子函数37函数调用大致包括的几个步骤参数入栈:将参数从右向左依次压入系统栈中。返回地址入栈:将当前代码区调用指令的下一条指令地

20、址压入栈中,供函数返回时继续执行。代码区跳转:处理器从当前代码区跳转到被调用函数的入口处。38函数调用大致包括的几个步骤栈帧调整:具体包括保存当前栈帧状态值,以备后面恢复本栈时使用( EBP入栈)。将当前栈帧切换到新栈帧(将ESP值装入EBP,更新新栈帧底部)。给新栈帧分配空间(把ESP减去所需空间的大小,抬高栈顶)。39_STDCALL调用约定时函数调用用到的指令序列;调用前PUSH参数3(设有三个参数)PUSH参数2PUSH参数1CALL函数地址; CALL指令向栈中压入当前指令在内存中的位置,即保存返回地址。然后跳转到被调用函数的入口处。PUSH EBP;保存旧栈帧的底部MOV EBP,

21、ESP;设置新栈帧的底部(栈帧切换)SUB ESP,XXX;设置新栈帧的顶部(抬高栈顶,为新栈帧开辟空间)40上段用于函数调用的指令在栈中引起的变化ESPEBP函数调用前当前函数栈帧ARG1ARG2ARG3ESPEBP当前函数栈帧PUSHARG_X函数参数从右到左入栈返回地址ARG1ARG2ARG3ESPEBP当前函数栈帧CALL指令引起的压栈操作。紧接CALL后面那条指令的内存地址被压入栈中,即返回地址EBP返回地址ARG1ARG2ARG3前栈帧EBPESPEBP当前函数栈帧PUSH EBP保存当前栈帧的底部位置,备栈帧恢复时使用前栈帧EBP返回地址ARG1ARG2ARG3前栈帧EBPESP

22、EBP当前函数栈帧MOV EBP,ESP设置新栈帧的底部开始栈帧切换前栈帧EBP返回地址ARG1ARG2ARG3前栈帧EBPEBPESP旧函数栈帧新函数栈帧SUB ESP,XXX设置新栈帧的顶部,新栈帧切换完毕41说明前栈帧EBP值既属于上一个栈帧,也属于下一个栈帧,返回地址成为栈帧顶部的数据42函数返回时步骤保存返回值:通常将函数返回值保存在EAX寄存器中。弹出当前栈帧,恢复上一个栈帧。具体包括在堆栈平衡的基础上,给ESP加上栈帧的大小,降低栈顶,回收当前栈帧的空间。将当前栈帧底部保存的前栈帧EBP值弹入EBP寄存器,恢复上一个栈帧。将函数返回地址弹给EIP寄存器。跳转:按照函数返回地址跳回

23、母函数中继续执行。43WIN32平台函数返回时相关指令序列ADD ESP,XXX;降低栈顶,回收当前栈帧POP EBP;将上一个栈帧底部位置恢复到EBPRETN;弹出当前栈顶元素,即弹出返回地址,栈帧恢复完成。让处理器跳转到弹出的返回地址,恢复调用前的代码区。44最终按函数调用约定组织起来的系统栈结构图局部变量VAR_B2局部变量VAR_B1前栈帧EBP返回地址FUNC_B第一个参数ARG_B1FUNC_B第二个参数ARG_B2局部变量VRA_A前栈帧EBP返回地址FUNC_A第一个参数ARG_A1FUNC_A第二个参数ARG_A2局部变量VRA_MAIN前栈帧EBP返回地址MAIN第一个参数

24、INT ARGCMAIN第二个参数CHAR*ARGVMAIN第三个参数CHAR*ENVP其他数据-MAIN栈帧FUNC_A栈帧FUNC_B栈帧ESPEBPFUNC_A代码区-CALL FUNC_BMOV VAR-A,EAX- MAIN代码区-CALL FUNC_AMOV VAR-MAIN,EAX-45代码植入原理如果在BUFFER中包含我们自己想要执行的代码,然后通过返回地址让程序跳转到系统栈里执行。在实验中,我们向PASSWORD.TXT文件里植入二进制的机器码,并用这段机器码来调用WINDOWS的一个API函数 MESSAGEBOXA,最终在桌面弹出一个消息框并显示“MAOTEACH” 。

25、46示例代码#include #include #define PASSWORD 1234567int verify_password (char *password)int authenticated;char buffer44;authenticated=strcmp(password,PASSWORD);strcpy(buffer,password);/over flowed here!return authenticated;main()int valid_flag=0;char password1024;FILE * fp;LoadLibrary(user32.dll);/prepa

26、re for messageboxif(!(fp=fopen(password.txt,rw+)exit(0);fscanf(fp,%s,password);valid_flag = verify_password(password);if(valid_flag)printf(incorrect password!n);elseprintf(Congratulation! You have passed the verification!n);fclose(fp);47利用栈溢出植入可执行代码-BUFFER(可执行机器码)- (可执行机器码)- (可执行机器码)Authenticated(覆盖

27、)前栈帧EBP (覆盖)返回地址(覆盖)-溢出后被改写的新返回地址-用包含可正确执行的机器码填充缓冲区,并将返回地址覆盖成BUFFER的起址,成功后可让程序跳转到栈区执行我们输入的代码-CALL verify_passwordADD ESP,4MOV DWORD PTR SS:EBP-4,EAXMOV DWORD PTR SS:EBP-4,0-正常情况下的返回地址48要做的几项工作分析并调试漏洞程序,获得淹没返回地址的偏移。获得BUFFER的起始地址,并将其写入PASSWORD.TXT的相应偏移处,用来覆盖返回地址。向PASSWORD.TXT中写入可执行的机器代码,用来调用API弹出一个消息框

28、。49示例代码的说明verify_password函数的局部变量buffer为44个字节, buffer的大小依赖于我们要植入代码的大小。Main函数中使用LoadLibrary(“user32.dll”);用于初始化装载USER32.DLL,以便在植入代码中调用MESSAGEBOX函数。50代码植入的事先分析verify_password函数的局部变量buffer为44个字节,当MAIN函数调用它时,栈的结构为右图。-BUFFER0-3机器码- (可执行机器码)BUFFER40-43机器码Authenticated(覆盖)前栈帧EBP (覆盖)返回地址(覆盖)-44个字节-51代码植入的事先分析如在PASSWORD.TXT中恰好写入44个字符,那么第45个隐藏的截断符NULL将覆盖Authenticated底字节中的1。用11组“4321”输入单元来填充buffer。则第12个输入单元将覆盖Authenticated;第13个输入单元将覆

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论