zoukankan      html  css  js  c++  java
  • 栈溢出的初步利用

    栈溢出的初步利用

        我们接着上面的栈溢出原理来进行讲解栈溢出的利用,首先我们不会接着上一篇的文章的例子来进行讲解,我会再写一个C语言的例子来进行讲解。再进行讲一遍栈溢出的原理。更加熟悉栈溢出的原理能够让我们更好地利用栈溢出。

        下面的例子代码如下:(代码很简单我不做解释)

    #include <stdio.h>
    #include<string.h>
    #define PASSWORD "qqqqqqq"
    int verify_password(char *password)
    {
        int authenticated;
        char buffer[8];
        authenticated=strcmp(password,PASSWORD);
        strcpy(buffer,password); //构造栈溢出
        return authenticated;
    }
    
    int main()
    {
        int valid_flag=0;
        char password[1024];
        while(1)
        {
            printf("please input password:     ");
            scanf("%s",password);
            valid_flag=verify_password(password);
            if(valid_flag)
            {
                printf("incorrect password!
    
    ");
            }
            else
            {
                printf("Congratulation! you have passed the Verification !
    ");
                break;
            }
        }
        getchar();
        char i;
        scanf("%s",&i);
    }

         从上面的例子可以看出是密码有效性的验证的一个例子,是通过输入密码进行验证密码是否输入正确,首先我们现在运行下程序。

         通过输入正确密码和不正确密码的区别;

         输入7个'q'程序正常运行时的栈状态。

         如下图可以看到栈的内部情况:

         如果继续增加输入的字符,那么超出buffer[8]边界的字符将依次淹没authenticated、前栈帧EBP、返回地址。也就是说,控制好字符串的长度就可以让字符串中相应位置字符的ASCII码覆盖掉这些栈帧状态值。

     

         按照上面对栈帧的分析,可以得出以下的结论:

          (1)输入11个'q',第9-11个字符连同NULL结束符将authenticated冲刷为0x00717171。

          (2)输入15个'q',第9-12个字符将authenticated冲刷为0x71717171;第13-15个字符连同NULL结束符将前栈帧EBP冲刷为0x00717171。

          (3)输入19个'q',第9-12字符将authenticated冲刷为0x71717171;第13-16个字符连同NULL结束符将前栈帧EBP冲刷为0x71717171;第17-19个字符连同NULL结束符将返回地址冲刷为0x00717171。

         这里用19个字符作为输入,看看淹没返回地址会对程序产生什么影响。出于双字对齐的目的,我们输入的字符串按照"4321"为一个单元进行组织,最后输入的字符串为"4321432143214321432"(测试)。

    <OllyDbg加载程序,在字符串拷贝函数调用结束后观察栈状态。>

    下面来进行分析:

    当输入7个q时,观察程序返回时堆栈的里面的内容。

         下面执行这段代码:4321432143214321432

         实际的内存状况和我们分析的结论一致,此时的栈状态见。请见下表的内容:

         接下来我们用OD来调试下程序的运行过程:

        返回地址用于在当前函数返回时重定向程序的代码。在函数返回的"retn"指令执行时,栈顶元素恰好是这个返回地址。"retn"指令会把这个返回地址弹入EIP寄存器,之后跳转到这个地址去执行。

        在这个例子中,返回地址本来是0x040FACB,对应的是main函数代码区的指令,现在我们已经把这个地址用字符的ASCII码覆盖成了0x00323334。

    我们可以从调试器中的显示看出计算机中发生的事件。

    (1)函数返回时将返回地址装入EIP寄存器。

    (2)处理器按照EIP寄存器的地址0x00323334取指。

    (3)内存0x00323334处并没有合法的指令,处理器不知道该如何处理,故报错。

    由于0x00323334是一个无效的指令地址,所以处理器在取指的时候发生了错误使程序崩溃。但如果这里我们给出一个有效的指令地址,就可以让处理器跳转到任意指令区去执行(比如直接跳转到程序验证通过的部分),也就是说,我们可以通过淹没返回地址而控制程序的执行流程。

    这时候我们会想到这段代码是进行对密码的验证,如果对了就显示正确信息,如果不对弹出错误消息,这时候我们可以修改这个函数返回地址,直接执行正确信息这样就达到了我们的目的;接下来我们要对程序进行一定的改进。

    程序代码如下所示:

    #include <stdio.h>
    #define PASSWORD "1234567"
    int verify_password (char *password)
    {
        int authenticated;
        char buffer[8];
        authenticated=strcmp(password,PASSWORD);
        strcpy(buffer,password);//over flowed here!    
        return authenticated;
    }
    main()
    {
        int valid_flag=0;
        char password[1024];
        FILE * fp;
        if(!(fp=fopen("password.txt","rw+")))
        {
            exit(0);
        }
        fscanf(fp,"%s",password);
        valid_flag = verify_password(password);
        if(valid_flag)
        {
            printf("incorrect password!
    ");
        }
        else
        {
            printf("Congratulation! You have passed the verification!
    ");
        }
        fclose(fp);
    }

    这段代码主要改进部分是密码是从txt文件中读取出来的不是手动输入了,这样的好处就是能够用UE输入一些16进制来进行修改数据;首先我们将程序载入到OD中,看一下我们要跳转的地方地址在哪里,我们看下面这张图,我们可以清晰的看到我们要返回的地址应该是0x401122这个地址

         这时候我们在程序的同目录下面创建一个password.txt首先前面的东西可以随便输入,还是4321432143214321后面这个就要输入0x401122如下图所示:

         这时候可以看一下栈帧情况,栈帧的情况如下图所示:

        运行程序看一下结果

       

       OK我们就可以看到我们想要的效果,当然这样修改会有问题,因为没有通过一些手段进行处理,代码里面还存在一些非法的指令因为我们修改了程序的返回地址。由于栈内EBP等被覆盖为无效值,使得程序在退出时堆栈无法平衡,导致崩溃。虽然如此,我们已经成功地淹没了返回地址,并让处理器如我们设想的那样,在函数返回时直接跳转到了提示验证通过的分支。

     上一篇文章链接地址:(初步认识栈溢出漏洞)http://www.cnblogs.com/dwlsxj/p/StackOverflow.html

    如果有写错的地方希望各位前辈及时指正我并改正。

     

  • 相关阅读:
    冒泡排序
    【leetcode 简单】第二十二题 对称二叉树
    【leetcode 简单】第二十一题 相同的树
    【leetcode 简单】第二十七题 二叉树的最小深度
    【leetcode 简单】第二十三题 二叉树的最大深度
    python 版本zabbix_sender
    C语言二分查找
    【leetcode 简单】第二十题 合并两个有序数组
    【leetcode 简单】第十九题 删除排序链表中的重复元素
    【leetcode 简单】第十八题 爬楼梯
  • 原文地址:https://www.cnblogs.com/dwlsxj/p/StackOverflow_1.html
Copyright © 2011-2022 走看看