转 浅谈缓冲区溢出之栈溢出

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               


浅谈缓冲区溢出之栈溢出




 发表于 2012-12-02

有段时间没有用windows了,刚一开机又是系统补丁更新。匆匆瞥了一眼看到了“内核缓冲区溢出漏洞补丁”几个字眼。靠,又是内核补丁。打完这个补丁后MD的内核符号文件又得更新了。于是抱怨了几句,一旁的兄弟问什么是缓冲区溢出。这个…三两句话还真说不清楚。解释这个问题用C语言比较方便,但是单从C代码是看不出来什么的,具体原理要分析机器级代码才能说清楚。既然是浅谈原理,那就从最基本的开始吧。

本文的定位是对此方面一无所知的读者,所以大牛们可以直接飘过…

缓冲区溢出这个名词想必大家并不陌生吧,在微软的系统漏洞补丁里经常可以看到这个词(微软这算是普及计算机知识么? – -)。从C语言来分析的话,最简单的一种溢出就是向数组中写入数据时超出了预定义的大小,比如定义了长度为10的数组,偏偏写入了10+个数据。C标准告诉我们这种做会产生不可预料的结果,而在信息安全领域看来,缓冲区溢出的艺术就是要让这种“不可预料的结果”变成攻击者想达成的结果。比如远程攻击服务器上的程序,使其返回一个具有管理员权限的shell什么的。千万别觉得这是天方夜谭,印象中微软历史上爆出过不少这样的漏洞,前段时间不就有覆盖微软全版本的MS12-020么(新的也有,但是我没关注 – -)。虽然网上广为流传的只是一个远程让服务器死机的shellcode,但是让远程服务器执行任意代码理论上是可行的。关于漏洞利用这块的东西我不怎么擅长,所以就不敢再多说了。

一般来说关于缓冲区溢出漏洞,官方的描述都是诸如“攻击者通过提交一个精心构造的字符串使得缓冲区溢出从而执行任意代码”之类的。这里的重点词是两个,“精心构造”和“字符串”。精心构造可以理解,那“字符串”呢?我们都知道,一段二进制代码是什么东西取决于机器对其的解释,如果把这段代码当作变量,当作整型是一个值,当作浮点型又是一个值,如果把它当成可执行代码的话,又会是另外一种解释。所以这里的字符串实际上就是一段可执行代码的字符串表现形式。接下来我们的重点就是如何“精心构造”这个“字符串”和如何让机器把我们构造的字符串(也就是数据)当作可执行代码来执行。

必须说明的是,真正意义上的shellcode要解决诸如函数地址重定位,汇编级系统调用,以及应对编译器抵抗此类缓冲区溢出攻击的“栈随机化”等技术,这些东西对于我们这篇“科普性质”的文章来说显然过于艰深,加之作者本人也是一个水货,故不会提及。我们只研究最浅显的原理。

我们先来看一段代码:

编译运行后我们看到了什么?

why_it_run函数居然被执行了。可是,我们并没有对该函数进行任何的显式调用啊。代码本身很简单,唯一值得怀疑的地方就在于we_call函数中buff[3] = (int)why_it_run;这一行了。我们定义了一个长度为2的数组,正常的访问范围是应该是buff[0]和buff[1]。但我们却访问了buff[3]这个超出了数组末端4个字节之后的地址,在这里写入了一个函数的地址。(为了便于之后解释变量地址的关系,我们在源代码中加入两句对buf[0]和buf[1]的赋值操作,即buf[0] = 0;与buf[1] = 1;)

为什么这样就能“诱使”系统执行了why_it_run函数呢?这里储存的到底是什么值呢?看来我们的问题越来越多了。一开始我们就说过,单从C代码是看不出任何东西的,所以我们需要研究机器代码的相关实现。那么我们需要基础的汇编指令知识,尤其是关于栈和C语言函数调用时call/ret相关的概念。如果之前没有基础,那么最好先补充一点相关的原理再继续吧,虽然这只是一篇基础文章,会尽量解释一切出现的术语和指令集。但是如果我们再解释这些基本概念的话,就过于偏离主线了。

这里是传送门:百度百科关于堆栈的解释 http://baike.baidu.com/view/93201.htm。

我们可以用gcc输出这段代码的汇编形式,命令是gcc -S overflow.c -o overflow.asm(vc的话可以用cl /Fa overflow.c命令),gcc默认输出的是AT&T风格的汇编代码,如果更习惯Intel格式的汇编的话,可以在命令行加上 -masm=intel参数,这样gcc就会输出Intel风格的汇编了。不过今天我们采用另外一种方法查看生成的机器指令,即使用objdump命令对最终形成的可执行文件进行反汇编来查看其机器代码。操作指令是objdump -d overflow -M intel,这样我们便得到了why_it_run、we_call以及main函数的执行代码,-M intel的意思是让objdump生成intel风格的汇编,objdump默认是AT&T风格的。我们可以看到输出的结果中有很多我们没定义的函数,它们来自C运行时库,它们才是这个可执行文件真正意义上的入口函数和结束函数。

下面是我们定义的三个函数反汇编的截图:

在这里我们需要关心的是main函数和we_call函数的实现,我们先给出程序运行到这里的时候栈的分布情况:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值