zoukankan      html  css  js  c++  java
  • SEED实验——return-to-libc实验

    实验概述

    本实验的学习目标是让学生获得缓冲区溢出攻击的一种有趣变体——return-to-libc攻击实验的亲身体验。这种攻击可以绕过目前在主要linux操作系统中实现的现有保护方案。利用缓冲区溢出漏洞通常的方法是使缓冲区溢出,然后在溢出部分的返回地址指向一段恶意的shellcode,使程序跳转到存储在堆栈中的shellcode。为了防止这些类型的攻击,一些操作系统允许管理员关闭堆栈的可执行功能。因此跳转到shellcode将导致程序失败。不幸的是,上述保护机制不是足够安全的。存在一种成为return-to-libc攻击的缓冲区溢出攻击的变体,其不需要可执行堆栈,甚至不需要shellcode。相反,它会导致受到攻击的程序跳转到一些现有的代码。例如已经加载到内存中的libc库中的system()函数。在这个实验中,学生被给予一个包含缓冲区溢出漏洞的程序,他们的任务是利用该漏洞,开发一个返回到libc库函数的攻击,最终获得root权限。除了这些攻击之外,学生们还将参与学习在ubuntu中实施的防止缓冲区溢出攻击的几项保护措施。学生需要评估方案是否有效,并解释评估过程。


    第二部分:实验任务

    该实验共有三个任务:

    • 漏洞利用
    • 地址随机化
    • StackGuard保护机制

    任务一:漏洞利用

    1.编译代码是关闭地址随机化机制和非执行栈机制

    sudo sysctl -w kernel.randomize_va_space=0         //注意:这里等号和0之间不能有空格

       在进行代码编译时,加上-fno-stack-protector,即可关闭ubuntu上StackGuard保护机制,加上-z -execstack/noexecstack即可打开或关闭可执行栈的机制。

      在本实验中,我们按照如下命令编译含有缓冲区溢出漏洞的代码段:

       su root

       gcc -fno-stack-protector -z noexecstack -o retlib retlib.c

       chmod 4755 retlib  /  chmod u+s retlib

       exit

      

    2.获取/bin/sh地址

      为了获取/bin/sh的内存地址,需要编写一个程序。

    //getenvaddr.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    int main(int argc,char const *argv[])
    {
        char *ptr;
        if(argc<3)
        {
            printf("Usage: %s <environment var> <target program name>
    ", argv[10]);
            exit(0);
         }
        ptr = getenv(argv[1]);
        ptr += (strlen(argv[0]) - strlen(argv[2])) * 2 ;
        printf("%s will be at %p 
    ", argv[1], ptr ) ;
        return 0;
    }

      其中,getenv的参数为一个环境变量,因此我们需要创建一个环境变量来记录路径export BIN_SH="/bin/sh"。调用程序./getenvaddr BIN_SH ./retlib得到/bin/sh的地址。

    如上面截图所示,/bin/sh的地址为:0xbffffe39。

    3. 获取system()和exit()地址

      这两个程序是驻留在内核态的,所有程序共享内核态的函数,因此我们可以用gdb来获取这两个程序的地址。

    如上图所示,在main函数设置断点,然后运行,运用gdb调试命令,我们可以得到system()函数的地址是0xb7e5f430,exit()函数的地址是0xb7e52fb0。

    将上述获得的三个地址写到代码中,


    第三部分:

    实验指导:了解函数调用机制

    3.1 获取libc库函数的地址

    用gdb命令进行获取。

    3.2 将shell字符串放在内存中

    本实验的一个挑战是将字符串“/bin/sh”放入内存中,并获取其地址。这可以使用环境变量来实现。执行C程序时,它会继承执行它的shell的所有环境变量。环境变量SHELL直接指向/bin/bash并且环境变量同时也被其他程序需要。所以我们引入一个新的shell变量MYSHELL,并指向zsh。

    $ export MYSHELL = /bin/sh

    我们将使用该变量的地址作为system()函数调用的参数。这个变量的位置在内存中使用以下代码就可以发现:

    void main()
    {
        char 8shell = getenv("MYSHELL");
        if(shell)
        prinf("%x
    ",(unsigned int)shell);
    }

    如果地址随机化被关闭,将会发现打印出的地址是相同的。然而,当您运行漏洞程序retlib时,环境变量的地址可能与通过运行上述程序获得的地址完全相同。当您更改程序名称时,这样的地址甚至会更改(文件名中的字符数不一样)。好消息是,shell的地址将与上述程序打印出来的地址相当接近。因此,您可能哟啊尝试几次才能成功。

    3.3 理解栈

    要知道如何进行return-to-libc攻击,必须了解堆栈的工作原理。我们使用一个小程序来了解函数调用对堆栈的影响。

    /* foobar.c */
    #include <stdio.h>
    void foo(int x)
    {
      printf("Hello world: %d ", x);
    }
    int main()
    {
      foo(1);
      return(0);
    }

    我们可以用“gcc -S foobar.c”来将程序编译成汇编代码。

  • 相关阅读:
    Step by step Dynamics CRM 2013安装
    SQL Server 2012 Managed Service Account
    Step by step SQL Server 2012的安装
    Step by step 活动目录中添加一个子域
    Step by step 如何创建一个新森林
    向活动目录中添加一个子域
    活动目录的信任关系
    RAID 概述
    DNS 正向查找与反向查找
    Microsoft Dynamics CRM 2013 and 2011 Update Rollups and Service Packs
  • 原文地址:https://www.cnblogs.com/xlwang1995/p/7153878.html
Copyright © 2011-2022 走看看