使用fgets导致缓冲区溢出

2024-05-19 15:40:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在一个c程序上造成缓冲区溢出,但我无法找到漏洞并利用代码进行攻击。在

我试过上千个输入。 一般来说,我试过这些: 1) 我尝试了一个很明显的方法-给一个很长的字符串作为输入。 2) 我试图返回一个很大的字符串。 3) 我尝试将空字节和EOF作为输入,并附加字符串。它不允许我输入这些字符作为输入。 4) 我尝试过重写某个的东西,但是没有什么东西被覆盖(如果我成功地覆盖了某些东西,那么对我来说这是70%的方法)

所有这些我都尝试过Python。在

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int secretCode = 123;

#define STATUS_WINNER 'WIN!'

typedef struct _word_struct
{
    char word[32 + 24];
    char result[48 + 24];
    int status;
} word_struct, *word_data;

int get_input(char *word, int len)
{
    int wordSize = 0;
    char *locWord = malloc(len+4);
    if(!locWord)
        return -2;
    printf("Enter your guess: ");
    fgets(locWord,len+4,stdin);
    wordSize = strlen(locWord);
    // strip newline character
    if(locWord[wordSize-1] == '\n')
        locWord[wordSize-1] = '\0';
    if(strlen(locWord) > len)
    {
    free(locWord);
    return -1;
    }
    strcpy(word,locWord);
    free(locWord);
    return 1;
}

void check_input(word_data w)
{
    //todo: implement this
    printf("Incorrect word!\n");
    w->status = strlen(w->word);
}

int main(int argc, char* argv[])
{
    //check with sizeof - off by one + strcpy (overwrite the next with 0)
    //strcpy that will copy that additional symbol
    //strncat that will start later because there is a 0 later
    word_struct guess;
    int i,offset,len,ret;
    printf("Welcome to Alladin's magic cave!\n");
    printf("Enter the secret word and get the treasure cave entrance code!\n");
    ret = get_input(guess.word, sizeof(guess.word));
    if(ret == -1)
    {
        printf("Exiting due to buffer overflow!\n");
        return -1;
    }
    else if(ret == -2)
    {
        printf("Out of resources! Exiting...\n");
        return -2;
    }

    check_input(&guess);
    printf("STATUS: %d\n", guess.status);
    printf("REAL:%d\n", STATUS_WINNER);
    if(guess.status == STATUS_WINNER)
        strcpy(guess.result,"CORRECT! YOU ENTERED: ");
    else
        strcpy(guess.result,"WRONG! YOUR WORD:  ");

    //we don't use unsafe str functions, we copy strings carefully one-by-one!
    offset = strlen(guess.result);
    len = strlen(guess.word);    
    for(i = 0; i < len; ++i)
        guess.result[offset+i] = guess.word[i];
    guess.result[offset+i] = '\0';

    printf("%s\n",guess.result);

    // give them the flag?
    if(guess.status == STATUS_WINNER)
        printf("It was cool, wasn't it ?! Go get your treasure, the code is %d\n", secretCode);
    else
        printf("Better luck next time!\n");

    return 0; 
}

对于输入56字节长的正好,我得到segfault。 对于大于56的输入,我从程序中得到缓冲区溢出“错误”。 对于非常大的输入(超过10^6字节[长得多或少])—程序有点卡住了。在

我希望能够覆盖任何内容,但我无法覆盖任何内容,可能直接跳转到打印代码的地址(0x804889d)

装配图如下:

^{pr2}$

我在c9环境工作。在

{我也读过这个 帮不上忙。在


Tags: thelenreturnifstatusresultwordint
2条回答

当您精确地输入复制到的len个字符时,就会发生缓冲区溢出猜猜看并且nul结束符溢出超过结尾。在

strcpy(guess.result,“thing”然后重写nul,然后for循环循环,直到内存耗尽,得到一个segfault。在

成功利用漏洞将向ioffset写入一个值,这样 a: 循环在没有命中错误内存地址的情况下终止 b: status中的值与STATUS_WINNER匹配

要做到这一点,LEN必须被一个小于70的值痛击

感谢大家的帮助,你们给了我很好的主意,下面是我的解决方案:

此函数在循环中有:

for(i = 0; i < len; ++i)
    guess.result[offset+i] = guess.word[i];

偏移量等于字符串“错误!你的话:“就是19。 因此,如果用户输入56字节长的字符串(这是猜猜看),“len”将是75(输入+19的56),“offset+i”将在19和74之间(实际上是75,但循环将退出)。因此,当“偏移量+i”为72时,猜测。结果会启动超驰控制猜测状态(猜测。结果是72字节长,并且猜测状态在“偏移量+i”=75时,当i=56时,猜猜看[56]是的猜测。结果[0],即“W”(错误!你的…)。 从那里很容易。在

相关问题 更多 >