“缓冲区溢出攻击”原理分析及实例演示

一.原理分析

缓冲区溢出是一种非常普遍、非常危险的漏洞,在各种操作系统、应用软件中广泛存在。利用缓冲区溢出攻击,可以导致程序运行失败、系统宕机、重新启动等后果。更为严重的是,可以利用它执行非授权指令,甚至可以取得系统特权,进而进行各种非法操作。

要了解缓冲区溢出攻击,就得先了解程序函数调用的栈内存分布:

如上图所示:堆栈帧的顶部为函数的实参,下面是函数的返回地址以及前一个堆栈帧的指针,最下面是分配给函数的局部变量使用的空间。一个堆栈帧通常都有两个指针,其中一个称为堆栈帧指针,另一个称为栈顶指针。前者所指向的位置是固定的,而后者所指向的位置在函数的运行过程中可变。因此,在函数中访问实参和局部变量时都是以堆栈帧指针为基址,再加上一个偏移。对照图可知,实参的偏移为正,局部变量的偏移为负。

那么当函数的局部变量有一个为字符串时,函数调用的栈会怎么分布呢?

如上代码所示的函数调用栈为:

如图所示,操作系统在给buf分配栈空间时,看到buf的长度为8,即申请8个字节长的地址空间,然后按照倒序将buf的内容填充入栈地址中。而缓冲区溢出攻击正是利用这一机制,如果将长度大于8的一个字符串赋值给buf,那么操作系统就会倒序一直填充栈地址,导致覆盖掉了”previous frame pointer”和”return adress”,而攻击者如果让覆盖”return adress”的内容为一个有意义的地址,即攻击者想要让操作系统执行的攻击代码,那么当函数返回时就会去执行攻击代码达到了攻击者的目的。

图中灰色的区域会根据不同的机器硬件,不同的操作系统而有长度的变化。

二.实例演示

以下面代码为例:

如上,当代码第18行的fun()函数调用结束后,应该换回19行的return 0;执行,但如果我们传入fun()的ss参数在给buf赋值时,ss的长度大于buf的长度,覆盖了栈中buf上面return adress区域,而此区域正好是fun的返回地址,如果我们知道函数haha()的入口地址,那么可以把此入口地址填入return adress处,这样当fun执行完后,就会“很神奇”的去执行haha()函数,如果haha()函数是一段恶意代码,那么就实现了所谓的缓冲区溢出攻击。

我们在windows下用codeblocks演示整个实验的过程:

1.得到haha()函数的地址,通过第16行打印我们可以得到,如下图所示,haha的地址以16进制的形式显示为00401358。

2.我们得获得fun函数执行完成后的返回地址,也就是return 0;语句的地址。进入调试模式,通过查看编译后的汇编语言,可以看到ret语句(最后一行)的返回地址为004013C7。

3.查看fun()函数buf存放地址与其返回地址之间的距离,由图中有深蓝背景的区域我们可以看到为fun的返回地址。这个地址与buf的开始地址即下图所示地址的开始(由其中内容可看到为我们赋值的“41 42 43..”,即AB…)距离为20,所以我们只需要将buf变成长度为25,从21-24字节为haha的地址即可。

4.又由于操作系统在分配内存是用了大端对齐的方式,所以每个字节应该倒叙填入即为“58 13 40 00”,程序19行可见。我们用已经写好的溢出字符串调试程序,可见如下图,返回地址已经变成了haha()的地址。

5.然后运行程序可以看到如下结果,执行了haha()中的代码输出了“OK!Success”。实验成功

二.如何防止此类攻击

C语言编译器充分信任编程人员,认为在进行strcpy()这些字符串操作时,参数长度的检查应该由编程人员完成。而如果编程人员忽略了这一点,程序就有了漏洞,攻击者就有机可趁,所以写C语言时一定要注意了。


  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值