zoukankan      html  css  js  c++  java
  • CSAPP lab3 bufbomb-缓冲区溢出攻击实验(上)smoke fizz

    前言

    完成这个实验大概花费一天半的时间,看了很多大佬的博客,也踩了很多的坑,于是打算写一篇博客重新梳理一下思路和过程,大概会有两篇博客吧。

    CSAPP lab3 bufbomb-缓冲区溢出攻击实验(上)smoke fizz

    CSAPP lab3 bufbomb-缓冲区溢出攻击实验(下)bang boom kaboom

    lab3要我们做这样一件事情,修改一个正在运行程序的stack以达到预期的目的。具体的修改方式是这样的:程序定义了一个局部C风格字符串变量,注意局部变量是放在stack上面的,所以当初始化这个字符串为用户输入,而又没有边界检查的话,就会缓冲区溢出,那么就会破坏这个函数栈。

    就像下面这个函数会破坏自己的函数栈:

    #define NORMAL_BUFF_SIZE 32
    int getbuf()
    {
        char buf[NORMAL_BUFF_SIZE];
        Gets(buf);
        return 1;
    }

    会破坏到什么程度呢?如果用户输入太大,那么就把saved ebp给覆盖掉了;再大一点,就把return address覆盖掉了…没错,这个lab的精髓就是要让我们的输入来覆盖return address达到return到代码的其它地方执行!!!

    ESP(Extended Stack Pointer)为扩展栈指针寄存器,是指针寄存器的一种,用于存放函数栈顶指针。与之对应的是EBP(Extended Base Pointer),扩展基址指针寄存器,也被称为帧指针寄存器,用于存放函数栈底指针。

    ESP为栈指针,用于指向栈的栈顶(下一个压入栈的活动记录的顶部),而EBP为帧指针,指向当前活动记录的底部

     

    实验目的:

    通过缓冲区溢出攻击,使学生进一步理解IA-32函数调用规则和栈帧结构。

    实验技能:

    需要使用objdump来反汇编目标程序,使用gdb单步跟踪调试机器代码,查看相关内存及寄存器内容,也需要学生掌握简单的IA32汇编程序编写方法。

    实验要求:

    5个难度等级(0-4逐级递增)

    级别0、Smoke(candle):构造攻击字符串作为目标程序输入,造成缓冲区溢出,使目标程序能够执行smoke函数。


    级别1、Fizz(sparkler):构造攻击字符串作为目标程序输入,造成缓冲区溢出,使目标程序能够执行fizz函数;fizz函数含有一个参数(cookie值),构造的攻击字符串应能给定fizz函数正确的参数,使其判断成功。


    级别2、Bang(firecracker):构造攻击字符串作为目标程序输入,造成缓冲区溢出,使目标程序能够执行bang函数;并且要篡改全局变量global_value为cookie值,使其判断成功。因此,需要在缓冲区中注入恶意代码篡改全局变量。


    级别3、Boom(dynamite):前面的攻击都是使目标程序跳转到特定函数,进而利用exit函数结束目标程序运行。Boom要求攻击程序能够返回到原调用函数test继续执行,即要求攻击之后,还原对栈帧结构的破坏。


    级别4、kaboom(Nitro):本攻击需要对目标程序连续攻击n=5次,但每次攻击,被攻击函数的栈帧内存地址都不同,也就是函数的栈帧位置每次运行时都不一样。因此,要想办法保证每次都能够正确复原原栈帧被破坏的状态,使程序每次都能够正确返回。

    从这个等级的命名我们也能窥探到一些端倪,candle 蜡烛,sparkler 烟火,firecracker 爆竹,dynamite 火药,Nitro 硝化甘油这一套命名规则显然让我们想起来lab2的拆弹实验,可见级别越高威力必然也就越大。而另外一套命名规则显然是从效果来看的,Smoke 冒烟,Fizz 劈啪作响,Bang 怦然巨响,Boom 隆隆作响,kaboom 大炸裂,果然有点意思。

    文件夹内容

    本实验的数据包含于一个文件夹buflab-handout.tar中。下载该文件到本地目录中,然后利用“tar –xvf buflab-handout.tar”命令将其解压。

    bufbomb:实验需要攻击的目标程序bufbomb。
    bufbomb.c:目标程序bufbomb的主源程序。本校的实验中没有给出,但老师给的ppt上有。
    makecookie:该程序基于你的学号产生一个唯一的由8个16进制数字组成的4字节序列(例如0x5f405c9a),称为“cookie”。
    hex2raw:构建的攻击字符串中可能包含不可打印字符,很难通过键盘输入,提交结果时,一般将结果放置在一个答案txt文件中(攻击字符串以可显示的16进制形式存储),在输入给bufbomb之前,需要使用hex2raw将其转换成原始的(raw)数据。


    其中结果提交和验证时,均需要使用到bufbomb,其使用方法(-h查看帮助):

    h:查看帮助;
    u:学生标识;-u要求我们输入一个唯一的userid,根据不同的userid生成不同的cookie值,这里我使用的userid是stu
    n:对于级别4(nitro/kaboom),需要加此参数,被坑了很久,一定要加上此参数!!
    s:验证正确性的同时,将结果提交到服务器(如果验证正确);

    实验步骤及操作说明

    准备工作

    使用objdump -d命令将其反汇编到bufbomb.asm。

     objdump -d bufbomb > bufbomb.asm

    使用makecookie,生成用户的Cookie,后面解题都要用到这个Cookie:

    0~3关:

    攻击test()下getbuf()

    第4关(Nitro/kaboom):

    循环调用5次,
    攻击testn() 下getbufn()

    第0关:smoke

    构造攻击字符串作为目标程序输入,造成缓冲区溢出,使目标程序能够执行smoke函数。

    源码:

    #define NORMAL_BUFFER_SIZE 32
    void test()
    {
        int val;
        /* Put canary on stack to detect possiblecorruption */
        volatile int local = uniqueval();
        val = getbuf();
        /* Check for corruption stack */
        if (local != uniqueval())
        {
            printf("Sabotaged!: the stack has beencorrupted
    ");
        }
        else if (val == cookie)
        {
            printf("Boom!: getbuf returned0x%x
    ", val);
            validate(3);
        }
        else
        {
            printf("Dud: getbuf returned0x%x
    ", val);
        }
    }
    int getbuf()
    {
        char buf[NORMAL_BUFFER_SIZE];
        Gets(buf);
        return 1;
    }
    //Smoke源码:
    void smoke()
    {
        puts("Smoke!: You calledsmoke()");
        validate(0);
        exit(0);
    }

    我们的目标是调用上面的getbuf()以后,不正常返回,而是跳掉smoke这个函数的地方执行。

    先看一下smoke的反汇编代码:

    smoke函数的地址:0x8048c28

    getbuf函数对应的栈还是上面那个栈的图:

    buf只有0x28字节长度。

    接下来,只要构造0x28(buf)+4(ebp)+4(return address)=48字节长度的字节码就可以将返回地址覆盖,最后四个字节的内容放smoke函数的地址保证返回地址是被smoke函数的地址覆盖,因为是小端存储(是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中),也就是:28 8c 04 08,前面44个字节任意这里我放一些00

     也就是:

    00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00
    00 00 00 00
    28 8c 04 08

    将其保存到一个txt文件中,用管道输入,通过hex2raw之后输入bufbomb程序。

    完成!

    第1关:fizz

    构造攻击字符串作为目标程序输入,造成缓冲区溢出,使目标程序能够执行fizz函数;fizz函数含有一个参数(cookie值),构造的攻击字符串应能给定fizz函数正确的参数,使其判断成功。

    还是上面的test函数和getbuf函数,这里就给出fizz源码:

    void fizz(int val)
    {
        if (val == cookie)
        {
            printf("Fizz!: You called fizz(0x%x)
    ", val);
            validate(1);
        }
        else
            printf("Misfire: You called fizz(0x%x)
    ", val);
        exit(0);
    }

    这一关和第0关类似,最大的区别是这次要跳到fizz这个函数有个参数,我们在输入里需要伪造出函数的参数。

    先看一下fizz的反汇编代码:

    fizz函数的地址:0x08048c52 即( 52 8c 04 08)

    在fizz函数代码里有这样两句:

     mov    0x8(%ebp),%eax
     cmp    0x804d108,%eax

    其中0x8(%ebp)就是函数的第一个参数,而0x804d108这个内存地址保存着cookie的值,然后这两个值期望是一样的,这个位置就是我们要放cookie的位置。也就是说参数是放到了返回地址的上面,并且和返回地址相邻。同第0关一样,先用fizz函数地址覆盖掉getbuf返回地址,可以执行fizz函数,并且要将fizz函数的返回地址覆盖掉,并用cookie覆盖掉上面的参数。这样就可以跳转到fizz函数,并且在跳转后自己取到cookie作为参数,fizz函数的返回地址可以用任意四个字节的数覆盖,这里00 00 00 00覆盖掉,其作用只是用来占位。

    也就是:

    00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00
    00 00 00 00
    52 8c 04 08 /*fizz 函数地址*/
    00 00 00 00/*fizz return address */
    94 25 80 4f /*Cookie: 0x4f802594*/

    将其保存到一个txt文件中,用管道输入,通过hex2raw之后输入bufbomb程序。

    完成!

    CSAPP lab3 bufbomb-缓冲区溢出攻击实验(下)bang boom kaboom

  • 相关阅读:
    Windows Server 2008关闭internet explorer增强的安全配置
    【转载并整理】mysql分页方法
    Mysql:MyIsam和InnoDB的区别
    【转载】web网站css,js更新后客户浏览器缓存问题,需要刷新才能正常展示的解决办法
    【转载】java前后端 动静分离,JavaWeb项目为什么我们要放弃jsp?
    Redis命令汇总
    Redis介绍及安装
    【转载】Spring Cache介绍
    简单示例:Spring4 整合 单个Redis服务
    【转载整理】Hibernater的锁机制
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/10808730.html
Copyright © 2011-2022 走看看