《网络攻防实验课程缓冲区溢出》由会员分享,可在线阅读,更多相关《网络攻防实验课程缓冲区溢出(89页珍藏版)》请在金锄头文库上搜索。
1、网络攻防实战技术之缓冲区溢出篇内容摘要l 缓冲区溢出相关概念l 缓冲区溢出原理l 溢出保护技术l 安全编程技术学习要求l了解缓冲区溢出的相关概念l明确缓冲区溢出的危害l理解栈溢出、堆溢出、整型溢出、格式化 字符串溢出及文件流溢出的原因l掌握安全编程技术引言-缓冲区溢出的历史l1988年的Morris蠕虫病毒,感染了6000多台机 器:利用UNIX服务finger中的缓冲区溢出漏洞 来获得访问权限,得到一个shelll1996年前后,开始出现大量的缓冲区溢出攻击 ,因此引起人们的广泛关注l源码开放的操作系统首当其冲 l随后,Windows系统下的缓冲区溢出也相继被 发掘出来l已经有一些非常经典细
2、致的文章来介绍与缓冲 区溢出有关的技术 l这两年广泛流行的一些Internet worms利用了 一些缓冲区溢出漏洞缓冲区溢出相关概念l缓冲区l从程序的角度,缓冲区就是应用程序用来保 存用户输入数据、程序临时数据的内存空间l缓冲区的本质l数组 l存储位置lStacklHeapl数据段缓冲区溢出相关概念l缓冲区溢出l如果用户输入的数据长度超出了程序为其分 配的内存空间,这些数据就会覆盖程序为其 它数据分配的内存空间,形成所谓的缓冲区 溢出为什么会缓冲区溢出?l在C语言中,指针和数组越界不保护是Buffer overflow的根源,而且,在C语言标准库中就有 许多能提供溢出的函数,如strcat(
3、), strcpy(), sprintf(), vsprintf(), bcopy(), gets()和scanf()l通过指针填充数据l不好的编程习惯l溢出类型l栈溢出l堆溢出利用缓冲区溢出进行的攻击l基本的思想l通过修改某些内存区域,把一段恶意代码存储到一个buffer中, 并且使这个buffer被溢出,以便当前进程被非法利用(执行这段恶 意的代码)l危害性l在UNIX平台上,通过发掘Buffer Overflow, 可以获得一个交互式 的shelll在Windows平台上,可以上载并执行任何的代码l溢出漏洞发掘起来需要较高的技巧和知识背景,但是,一旦有人 编写出溢出代码,则用起来非常简单
4、l与其他的攻击类型相比,缓冲区溢出攻击l不需要太多的先决条件l杀伤力很强l技术性强l在Buffer Overflows攻击面前,防火墙往往显得很无奈利用缓冲区溢出的攻击l随便往缓冲区中填东西造成它溢出一般只会出现“ 分段错误”(Segmentation fault),而不能达到 攻击的目的。l如果覆盖缓冲区的是一段精心设计的机器指令序 列,它可能通过溢出,改变返回地址,将其指向 自己的指令序列,从而改变该程序的正常流程。程序指令流被改变后l溢出之后,让程序执行我们指定的代码l我们自己提供的一段代码l系统现有的调用l由于这段代码往往不能太长,所以需要精心设计,并且充 分利用系统中现有的函数和指令
5、l对于不同的操作系统lLinux/Unix,尽可能地得到一个shell(最好是root shell)lWindows,一个可以远程建立连接的telnet会话l通用的模式l找到具有漏洞的程序(vulnerable program )l编写出shellcode,l然后编写把shellcode送到漏洞程序的程序(称为exploit)Windows平台下缓冲区溢出l过程l发现目标l找到有漏洞的程序,如果在 输入非正常字符串的时候, 出现右图的情形l或者从程序中找漏洞,用好 的反汇编工具,加上耐心l以一个特定的字符串作为线 索,跟踪到strcpy这样的函 数,看是否有边界检查l编写shellcodel编
6、写exploit程序,并试验 ,直到成功简单溢出实例#include int main() char name8 = 0;printf(“Your name:”);gets(name);printf(“Hello,%s!”,name);return 0; 缓冲区溢出的危害l应用程序异常l系统不稳定甚至崩溃l程序跳转到恶意代码,控制权被窃缓冲区溢出原理l预备知识l理解程序内存空间l理解堆栈l理解函数调用过程l理解缓冲区溢出的原理Windows环境下的堆栈l程序空间由何构成?l堆栈是什么?l堆栈里面放的都是什么信息?l程序使用超过了堆栈默认的大小怎么办?l在一次函数调用中,堆栈是如何工作的?程序在
7、内存中的映像文本(代码)段数据段堆栈段内存低地址内存高地址内存递增方向初始化数据段非初始化数据段(BSS)堆(Heap)栈(stack)堆的增长方向栈的增长方向内核数据代码0x800000000x7FFFFFFFPEBstrcpy(stack,input); void bar()printf(“nAh,Ive been hacked!n“); void main(int argc,char *argv)foo(argv1); main:pushl %ebpmovl %esp,%ebpsubl $8,%espaddl $-12,%espmovl 12(%ebp),%eaxaddl $4,%eax
8、movl (%eax),%eushl %edxcall fooaddl $16,%esp .L4:leaveretfoo:pushl %ebpmovl %esp,%ebpsubl $24,%espaddl $-8,%espmovl 8(%ebp),%eaxpushl %eaxleal -12(%ebp),%eaxpushl %eaxcall strcpyaddl $16,%esp .L2:leaveret例子2int AFunc(int i,int j) int m = 3; int n = 4;m = i; n = j;BFunc(m,n);return 8; int BFunc(int i
9、,int j) int m = 1;int n = 2;m = i;n = j;return m; int main() AFunc(5,6); return 0;6当前EBP当前ESPAFunc(5,6); push 6 push 5 call _AFunc add esp+8语句执行前的EBP语句执行前的ESP函数调用中栈的工作过程5EIP_AFunc push ebp mov ebp,esp sub esp,48h /压入环境变量 /为局部变量分配空间EBP48hEDI ESI EBX3(m=3)4(n=4)6当前EBP当前ESPAFunc(5,6); call _AFunc add e
10、sp+8语句执行前的EBP语句执行前的ESP函数调用中栈的工作过程5EIP_AFunc return 0; pop edi pop esi pop ebx add esp,48h /栈校验 pop ebp retEBP48hEDI ESI EBX3(m=3)4(n=4)当缓冲区溢出发生时int AFunc(int i,int j) int m = 3; int n = 4;char szBuf8 = 0; strcpy(szBuf, “This is a overflow buffer!”);m = i;n = j;BFunc(m,n);return 8; 6szBuf5EIPEBPEDI E
11、SI EBX3(m=3)4(n=4)缓冲区溢出原理及其利用l缓冲区溢出种类l栈溢出l堆溢出l整型溢出l格式化字符串溢出l其他溢出栈溢出l特点l缓冲区在栈中分配l拷贝的数据过长l覆盖了函数的返回地址或其它一些重要数据 结构、函数指针栈溢出实例int AFunc(int i,int j) int m = 3; int n = 4;char szBuf8 = 0; *(int *)(int)szBuf+20) = BFunc;m = i;n = j;BFunc(m,n);return 8; 用BFunc的地址替换正常 的AFunc返回地址,使程 序运行至BFunc堆溢出l堆和栈有何区别l内存的动态分
12、配与 静态分配l数据增长方向l堆溢出特点l缓冲区在堆中分配l拷贝的数据过长l覆盖了堆管理结构#define BUFLEN 32 int main(int argc, char* argv ) char *buf1; buf1 = (char*)malloc(BUFLEN); strcpy(buf1,argv1); printf(“%sn“,buf1);free(buf1); return 0; 关于堆溢出l比较少引起人们的关注,原因在于l比栈溢出难度更大l需要结合其他的技术,比如l函数指针改写lVtable改写lMalloc库本身的漏洞l对于内存中变量的组织方式有一定的要求整型溢出l宽度溢出(
13、Widthness Overflow)l尝试存储一个超过变量表示范围的大数到变量中l运算溢出(Arithmetic Overflow)l如果存储值是一个运算操作,稍后使用这个结果的 程序的任何一部分都将错误的运行,因为这个计算 结果是不正确的。l符号溢出(Signedness Bug) l一个无符号的变量被看作有符号,或者一个有符号 的变量被看作无符号宽度溢出示例void main(int argc,char* argv) unsigned short s; int i; char buf80; i = atoi(argv1);/将字符串转换为整型数据 s = i; if(s = 80) re
14、turn; memcpy(buf,argv2,i); 运算溢出示例void CopyIntArray(int *array,int len) int* myarray,i; myarray = malloc(len*sizeof(int); if(myarray = NULL) return; for(i=0;i size) return; memcpy(kbuf,buf,len); 格式化字符串溢出l关键字l“%n”l产生原因lprintf()是不定参数输入lprintf()不会检查输入参数的个数其他溢出类型l.data section溢出lPEB/TEB溢出l文件流溢出归纳l溢出的共性l大
15、object向小object复制数据(字符串或整型) ,容纳不下造成溢出l溢出会覆盖一些关键性数据(返回地址、管 理数据、异常处理或文件指针等)l利用程序的后续流程,得到程序的控制权缓冲区溢出的利用char szBuf8 = 0; strcpy(szBuf,argv2);largv2的内容:l对EIP的填充lShellcode6szBuf5EIPEBPEDI ESI EBX3(m=3)4(n=4)ShellcodeShellcodelShellcode其实就是一段可以完成某种特定 功能的二进制代码lShellcode的功能l基本功能l添加administrator or root组用户l远程可
16、用shelll下载程序(Trojan or Rootkit)执行l高级功能l抗NIDS检测l穿透防火墙Shellcode不通用lShellcode为什么不通用l不同硬件平台lIBM PC、Alpha,PowerPCl不同系统平台lUnix、Windowsl不同内核与补丁版本l不同漏洞对字符串限制不同利用缓冲区溢出的攻击实例llogin: zch lPassword: lLast login: Fri Jan 12 15:21:34 from 210.34.6.82 lSun Microsystems Inc. SunOS 5.6 Generic August 1997 lYou have mail. l$ who lzch pts/1 Jan 12 15:22 () l$ lpset