软件安全实验:栈溢出漏洞二

实验目的:

在掌握栈帧结构的基础上,学习栈溢出漏洞的基本原理。

完成功能:

在函数的栈帧中,局部变量是顺序排列的,栈帧中还保存前栈帧EBP及返回地址RET等信息。构造password.txt。
使得str在读取该文件后恰能够覆盖fun函数的返回地址,从而运行attack函数。

实验代码:

#include 
void attack(){
    printf("Attacked!\n");
    exit(0);
}

void fun(){
    char password[6]="ABCDE";
    char str[6];
    FILE *fp;
    if(!(fp=fopen("password.txt","r"))){
        exit(0);
    }
    fscanf(fp,"%s",str);

    str[5]='\0';
    if(strcmp(str,password)==0)
        printf("OK!\n");
    else
        printf("NO!\n");
}

int main()
{
    fun();
    return 0;
}

实验结果和分析:

  1. 设置程序断点
    软件安全实验:栈溢出漏洞二_第1张图片
  2. 让程序运行到断点处停止,这时候查看main()函数栈的ebp指针的值
    软件安全实验:栈溢出漏洞二_第2张图片
    可以看到ebp指针的值是0x6dff08
  3. 这时候让我们跳进fun()函数中去,同时查看fun()函数栈中ebp指针的值
    软件安全实验:栈溢出漏洞二_第3张图片
  4. 这时候打开内存,查看fun()的ebp指针指向的值
    软件安全实验:栈溢出漏洞二_第4张图片
    可以看到fun()函数栈中ebp指针指向的值是main()函数栈中ebp指针的值,由于栈的增长方向是从高地址向低地址增长的,ebp指针紧挨着的高地址位置是函数栈的返回地址。我们就可以知道fun()函数的返回地址是0x401410, 要使得fun()函数返回时成功地跳到attack()函数处去,就得把fun()函数的返回地址覆盖为attack()的函数地址,这样才能实现跳转。
  5. 让我们查看下attack()的函数地址
    软件安全实验:栈溢出漏洞二_第5张图片
    可以看到attack()函数的地址是0x401350
  6. 接着让我们查看下str数组的地址
    软件安全实验:栈溢出漏洞二_第6张图片
    从fun()函数的ebp地址到str数组地址中间相差了0x6dfef8 - 0x6dfee0共24个字节,存储返回值的地址到ebp地址中间又相差了4个字节。返回地址的长度是4个字节,所以从str数组开始到完全覆盖返回地址需要输入32个字节的数据。
    软件安全实验:栈溢出漏洞二_第7张图片
    前28个字节随便输入,后4个字节为attack的地址。
  7. 完成输入后,我们一直点击next line让程序往下执行
    软件安全实验:栈溢出漏洞二_第8张图片
    可以看到成功地从fun()返回后跳到了attack()函数处,继续执行程序。
    软件安全实验:栈溢出漏洞二_第9张图片
    成功了!

你可能感兴趣的:(安全)