使用 fgets 导致缓冲区溢出

Causing a Buffer Overflow Using fgets

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

我已经尝试了数千种输入。 一般来说,我试过这些: 1)我已经尝试了显而易见的 - 给出一个很长的字符串作为输入。 2) 我试图给出一个很大的字符串,以至于 strlen() 实际上会 return 一个负值。 3)我试图将空字节和 EOF 作为输入,并附加字符串。它不会让我输入这些字符作为输入。 4)我试图覆盖 something,但没有任何东西被覆盖(如果我设法覆盖 something,这对我来说已经完成了 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] = '[=10=]';
    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] = '[=10=]';

    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 字节长的输入 EXACTLY - 我遇到段错误。 对于大于 56 的输入 - 我从程序中得到缓冲区溢出 "error"。 对于非常大的输入(超过 10^6 字节 [或多或少])——程序有点卡住了。

我希望能够覆盖任何东西,但我无法覆盖任何东西,也许直接跳到打印出代码的地址(在 0x804889d)

下面是汇编:

080485ab <get_input>:
 80485ab:       55                      push   %ebp
 80485ac:       89 e5                   mov    %esp,%ebp
 80485ae:       83 ec 18                sub    [=11=]x18,%esp
 80485b1:       c7 45 f0 00 00 00 00    movl   [=11=]x0,-0x10(%ebp)
 80485b8:       8b 45 0c                mov    0xc(%ebp),%eax
 80485bb:       83 c0 04                add    [=11=]x4,%eax
 80485be:       83 ec 0c                sub    [=11=]xc,%esp
 80485c1:       50                      push   %eax
 80485c2:       e8 99 fe ff ff          call   8048460 <malloc@plt>
 80485c7:       83 c4 10                add    [=11=]x10,%esp
 80485ca:       89 45 f4                mov    %eax,-0xc(%ebp)
 80485cd:       83 7d f4 00             cmpl   [=11=]x0,-0xc(%ebp)
 80485d1:       75 0a                   jne    80485dd <get_input+0x32>
 80485d3:       b8 fe ff ff ff          mov    [=11=]xfffffffe,%eax
 80485d8:       e9 ac 00 00 00          jmp    8048689 <get_input+0xde>
 80485dd:       83 ec 0c                sub    [=11=]xc,%esp
 80485e0:       68 60 89 04 08          push   [=11=]x8048960
 80485e5:       e8 26 fe ff ff          call   8048410 <printf@plt>
 80485ea:       83 c4 10                add    [=11=]x10,%esp
 80485ed:       a1 40 a0 04 08          mov    0x804a040,%eax
 80485f2:       8b 55 0c                mov    0xc(%ebp),%edx
 80485f5:       83 c2 04                add    [=11=]x4,%edx
 80485f8:       83 ec 04                sub    [=11=]x4,%esp
 80485fb:       50                      push   %eax
 80485fc:       52                      push   %edx
 80485fd:       ff 75 f4                pushl  -0xc(%ebp)
 8048600:       e8 2b fe ff ff          call   8048430 <fgets@plt>
 8048605:       83 c4 10                add    [=11=]x10,%esp
 8048608:       83 ec 0c                sub    [=11=]xc,%esp
 804860b:       ff 75 f4                pushl  -0xc(%ebp)
 804860e:       e8 6d fe ff ff          call   8048480 <strlen@plt>
 8048613:       83 c4 10                add    [=11=]x10,%esp
 8048616:       89 45 f0                mov    %eax,-0x10(%ebp)
 8048619:       8b 45 f0                mov    -0x10(%ebp),%eax
 804861c:       8d 50 ff                lea    -0x1(%eax),%edx
 804861f:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048622:       01 d0                   add    %edx,%eax
 8048624:       0f b6 00                movzbl (%eax),%eax
 8048627:       3c 0a                   cmp    [=11=]xa,%al
 8048629:       75 0e                   jne    8048639 <get_input+0x8e>
 804862b:       8b 45 f0                mov    -0x10(%ebp),%eax
 804862e:       8d 50 ff                lea    -0x1(%eax),%edx
 8048631:       8b 45 f4                mov    -0xc(%ebp),%eax
 8048634:       01 d0                   add    %edx,%eax
 8048636:       c6 00 00                movb   [=11=]x0,(%eax)
 8048639:       83 ec 0c                sub    [=11=]xc,%esp
 804863c:       ff 75 f4                pushl  -0xc(%ebp)
 804863f:       e8 3c fe ff ff          call   8048480 <strlen@plt>
 8048644:       83 c4 10                add    [=11=]x10,%esp
 8048647:       89 c2                   mov    %eax,%edx
 8048649:       8b 45 0c                mov    0xc(%ebp),%eax
 804864c:       39 c2                   cmp    %eax,%edx
 804864e:       76 15                   jbe    8048665 <get_input+0xba>
 8048650:       83 ec 0c                sub    [=11=]xc,%esp
 8048653:       ff 75 f4                pushl  -0xc(%ebp)
 8048656:       e8 c5 fd ff ff          call   8048420 <free@plt>
 804865b:       83 c4 10                add    [=11=]x10,%esp
 804865e:       b8 ff ff ff ff          mov    [=11=]xffffffff,%eax
 8048663:       eb 24                   jmp    8048689 <get_input+0xde>
 8048665:       83 ec 08                sub    [=11=]x8,%esp
 8048668:       ff 75 f4                pushl  -0xc(%ebp)
 804866b:       ff 75 08                pushl  0x8(%ebp)
 804866e:       e8 dd fd ff ff          call   8048450 <strcpy@plt>
 8048673:       83 c4 10                add    [=11=]x10,%esp
 8048676:       83 ec 0c                sub    [=11=]xc,%esp
 8048679:       ff 75 f4                pushl  -0xc(%ebp)
 804867c:       e8 9f fd ff ff          call   8048420 <free@plt>
 8048681:       83 c4 10                add    [=11=]x10,%esp
 8048684:       b8 01 00 00 00          mov    [=11=]x1,%eax
 8048689:       c9                      leave  
 804868a:       c3                      ret    

0804868b <check_input>:
 804868b:       55                      push   %ebp
 804868c:       89 e5                   mov    %esp,%ebp
 804868e:       83 ec 08                sub    [=11=]x8,%esp
 8048691:       83 ec 0c                sub    [=11=]xc,%esp
 8048694:       68 73 89 04 08          push   [=11=]x8048973
 8048699:       e8 d2 fd ff ff          call   8048470 <puts@plt>
 804869e:       83 c4 10                add    [=11=]x10,%esp
 80486a1:       8b 45 08                mov    0x8(%ebp),%eax
 80486a4:       83 ec 0c                sub    [=11=]xc,%esp
 80486a7:       50                      push   %eax
 80486a8:       e8 d3 fd ff ff          call   8048480 <strlen@plt>
 80486ad:       83 c4 10                add    [=11=]x10,%esp
 80486b0:       89 c2                   mov    %eax,%edx
 80486b2:       8b 45 08                mov    0x8(%ebp),%eax
 80486b5:       89 90 80 00 00 00       mov    %edx,0x80(%eax)
 80486bb:       90                      nop
 80486bc:       c9                      leave  
 80486bd:       c3                      ret    

080486be <main>:
 80486be:       8d 4c 24 04             lea    0x4(%esp),%ecx
 80486c2:       83 e4 f0                and    [=11=]xfffffff0,%esp
 80486c5:       ff 71 fc                pushl  -0x4(%ecx)
 80486c8:       55                      push   %ebp
 80486c9:       89 e5                   mov    %esp,%ebp
 80486cb:       51                      push   %ecx
 80486cc:       81 ec b4 00 00 00       sub    [=11=]xb4,%esp
 80486d2:       89 c8                   mov    %ecx,%eax
 80486d4:       8b 40 04                mov    0x4(%eax),%eax
 80486d7:       89 85 54 ff ff ff       mov    %eax,-0xac(%ebp)
 80486dd:       65 a1 14 00 00 00       mov    %gs:0x14,%eax
 80486e3:       89 45 f4                mov    %eax,-0xc(%ebp)
 80486e6:       31 c0                   xor    %eax,%eax
 80486e8:       83 ec 0c                sub    [=11=]xc,%esp
 80486eb:       68 84 89 04 08          push   [=11=]x8048984
 80486f0:       e8 7b fd ff ff          call   8048470 <puts@plt>
 80486f5:       83 c4 10                add    [=11=]x10,%esp
 80486f8:       83 ec 0c                sub    [=11=]xc,%esp
 80486fb:       68 a8 89 04 08          push   [=11=]x80489a8
 8048700:       e8 6b fd ff ff          call   8048470 <puts@plt>
 8048705:       83 c4 10                add    [=11=]x10,%esp
 8048708:       83 ec 08                sub    [=11=]x8,%esp
 804870b:       6a 38                   push   [=11=]x38
 804870d:       8d 85 70 ff ff ff       lea    -0x90(%ebp),%eax
 8048713:       50                      push   %eax
 8048714:       e8 92 fe ff ff          call   80485ab <get_input>
 8048719:       83 c4 10                add    [=11=]x10,%esp
 804871c:       89 85 64 ff ff ff       mov    %eax,-0x9c(%ebp)
 8048722:       83 bd 64 ff ff ff ff    cmpl   [=11=]xffffffff,-0x9c(%ebp)
 8048729:       75 1a                   jne    8048745 <main+0x87>
 804872b:       83 ec 0c                sub    [=11=]xc,%esp
 804872e:       68 e8 89 04 08          push   [=11=]x80489e8
 8048733:       e8 38 fd ff ff          call   8048470 <puts@plt>
 8048738:       83 c4 10                add    [=11=]x10,%esp
 804873b:       b8 ff ff ff ff          mov    [=11=]xffffffff,%eax
 8048740:       e9 77 01 00 00          jmp    80488bc <main+0x1fe>
 8048745:       83 bd 64 ff ff ff fe    cmpl   [=11=]xfffffffe,-0x9c(%ebp)
 804874c:       75 1a                   jne    8048768 <main+0xaa>
 804874e:       83 ec 0c                sub    [=11=]xc,%esp
 8048751:       68 08 8a 04 08          push   [=11=]x8048a08
 8048756:       e8 15 fd ff ff          call   8048470 <puts@plt>
 804875b:       83 c4 10                add    [=11=]x10,%esp
 804875e:       b8 fe ff ff ff          mov    [=11=]xfffffffe,%eax
 8048763:       e9 54 01 00 00          jmp    80488bc <main+0x1fe>
 8048768:       83 ec 0c                sub    [=11=]xc,%esp
 804876b:       8d 85 70 ff ff ff       lea    -0x90(%ebp),%eax
 8048771:       50                      push   %eax
 8048772:       e8 14 ff ff ff          call   804868b <check_input>
 8048777:       83 c4 10                add    [=11=]x10,%esp
 804877a:       8b 45 f0                mov    -0x10(%ebp),%eax
 804877d:       3d 21 4e 49 57          cmp    [=11=]x57494e21,%eax
 8048782:       75 37                   jne    80487bb <main+0xfd>
 8048784:       8d 85 70 ff ff ff       lea    -0x90(%ebp),%eax
 804878a:       83 c0 38                add    [=11=]x38,%eax
 804878d:       c7 00 43 4f 52 52       movl   [=11=]x52524f43,(%eax)
 8048793:       c7 40 04 45 43 54 21    movl   [=11=]x21544345,0x4(%eax)
 804879a:       c7 40 08 20 59 4f 55    movl   [=11=]x554f5920,0x8(%eax)
 80487a1:       c7 40 0c 20 45 4e 54    movl   [=11=]x544e4520,0xc(%eax)
 80487a8:       c7 40 10 45 52 45 44    movl   [=11=]x44455245,0x10(%eax)
 80487af:       66 c7 40 14 3a 20       movw   [=11=]x203a,0x14(%eax)
 80487b5:       c6 40 16 00             movb   [=11=]x0,0x16(%eax)
 80487b9:       eb 2b                   jmp    80487e6 <main+0x128>
 80487bb:       8d 85 70 ff ff ff       lea    -0x90(%ebp),%eax
 80487c1:       83 c0 38                add    [=11=]x38,%eax
 80487c4:       c7 00 57 52 4f 4e       movl   [=11=]x4e4f5257,(%eax)
 80487ca:       c7 40 04 47 21 20 59    movl   [=11=]x59202147,0x4(%eax)
 80487d1:       c7 40 08 4f 55 52 20    movl   [=11=]x2052554f,0x8(%eax)
 80487d8:       c7 40 0c 57 4f 52 44    movl   [=11=]x44524f57,0xc(%eax)
 80487df:       c7 40 10 3a 20 20 00    movl   [=11=]x20203a,0x10(%eax)
 80487e6:       83 ec 0c                sub    [=11=]xc,%esp
 80487e9:       8d 85 70 ff ff ff       lea    -0x90(%ebp),%eax
 80487ef:       83 c0 38                add    [=11=]x38,%eax
 80487f2:       50                      push   %eax
 80487f3:       e8 88 fc ff ff          call   8048480 <strlen@plt>
 80487f8:       83 c4 10                add    [=11=]x10,%esp
 80487fb:       89 85 68 ff ff ff       mov    %eax,-0x98(%ebp)
 8048801:       83 ec 0c                sub    [=11=]xc,%esp
 8048804:       8d 85 70 ff ff ff       lea    -0x90(%ebp),%eax
 804880a:       50                      push   %eax
 804880b:       e8 70 fc ff ff          call   8048480 <strlen@plt>
 8048810:       83 c4 10                add    [=11=]x10,%esp
 8048813:       89 85 6c ff ff ff       mov    %eax,-0x94(%ebp)
 8048819:       c7 85 60 ff ff ff 00    movl   [=11=]x0,-0xa0(%ebp)
 8048820:       00 00 00 
 8048823:       eb 2a                   jmp    804884f <main+0x191>
 8048825:       8b 95 68 ff ff ff       mov    -0x98(%ebp),%edx
 804882b:       8b 85 60 ff ff ff       mov    -0xa0(%ebp),%eax
 8048831:       01 c2                   add    %eax,%edx
 8048833:       8d 8d 70 ff ff ff       lea    -0x90(%ebp),%ecx
 8048839:       8b 85 60 ff ff ff       mov    -0xa0(%ebp),%eax
 804883f:       01 c8                   add    %ecx,%eax
 8048841:       0f b6 00                movzbl (%eax),%eax
 8048844:       88 44 15 a8             mov    %al,-0x58(%ebp,%edx,1)
 8048848:       83 85 60 ff ff ff 01    addl   [=11=]x1,-0xa0(%ebp)
 804884f:       8b 85 60 ff ff ff       mov    -0xa0(%ebp),%eax
 8048855:       3b 85 6c ff ff ff       cmp    -0x94(%ebp),%eax
 804885b:       7c c8                   jl     8048825 <main+0x167>
 804885d:       8b 95 68 ff ff ff       mov    -0x98(%ebp),%edx
 8048863:       8b 85 60 ff ff ff       mov    -0xa0(%ebp),%eax
 8048869:       01 d0                   add    %edx,%eax
 804886b:       c6 44 05 a8 00          movb   [=11=]x0,-0x58(%ebp,%eax,1)
 8048870:       83 ec 0c                sub    [=11=]xc,%esp
 8048873:       8d 85 70 ff ff ff       lea    -0x90(%ebp),%eax
 8048879:       83 c0 38                add    [=11=]x38,%eax
 804887c:       50                      push   %eax
 804887d:       e8 ee fb ff ff          call   8048470 <puts@plt>
 8048882:       83 c4 10                add    [=11=]x10,%esp
 8048885:       8b 45 f0                mov    -0x10(%ebp),%eax
 8048888:       3d 21 4e 49 57          cmp    [=11=]x57494e21,%eax
 804888d:       75 18                   jne    80488a7 <main+0x1e9>
 804888f:       a1 38 a0 04 08          mov    0x804a038,%eax
 8048894:       83 ec 08                sub    [=11=]x8,%esp
 8048897:       50                      push   %eax
 8048898:       68 28 8a 04 08          push   [=11=]x8048a28
 804889d:       e8 6e fb ff ff          call   8048410 <printf@plt>
 80488a2:       83 c4 10                add    [=11=]x10,%esp
 80488a5:       eb 10                   jmp    80488b7 <main+0x1f9>
 80488a7:       83 ec 0c                sub    [=11=]xc,%esp
 80488aa:       68 68 8a 04 08          push   [=11=]x8048a68
 80488af:       e8 bc fb ff ff          call   8048470 <puts@plt>
 80488b4:       83 c4 10                add    [=11=]x10,%esp
 80488b7:       b8 00 00 00 00          mov    [=11=]x0,%eax
 80488bc:       8b 4d f4                mov    -0xc(%ebp),%ecx
 80488bf:       65 33 0d 14 00 00 00    xor    %gs:0x14,%ecx
 80488c6:       74 05                   je     80488cd <main+0x20f>
 80488c8:       e8 73 fb ff ff          call   8048440 <__stack_chk_fail@plt>
 80488cd:       8b 4d fc                mov    -0x4(%ebp),%ecx
 80488d0:       c9                      leave  
 80488d1:       8d 61 fc                lea    -0x4(%ecx),%esp
 80488d4:       c3                      ret    
 80488d5:       66 90                   xchg   %ax,%ax
 80488d7:       66 90                   xchg   %ax,%ax
 80488d9:       66 90                   xchg   %ax,%ax
 80488db:       66 90                   xchg   %ax,%ax
 80488dd:       66 90                   xchg   %ax,%ax
 80488df:       90                      nop

我在c9环境下工作。

另外,我读过这个主题:Causing a buffer Overflow with fgets 没有帮助。

当您输入恰好 len 个字符时会发生缓冲区溢出,这些字符将被复制到 guess.word 并且 nul 终止符溢出到末尾。

那个 strcpy(guess.result,"thing" 然后覆盖 nul 然后 for 循环循环直到它用完内存并出现段错误。

一个成功的漏洞将写入一个值到 ioffset 这样 a:循环终止而没有遇到错误的内存地址 b: status 中的值匹配 STATUS_WINNER

为此,必须使用小于 70 的值破坏 LEN

感谢大家的帮助,你们都给了我很好的想法,这是我的解决方案:

在main函数中,有这样一个for循环:

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

offset 等于字符串的长度 "WRONG! YOUR WORD: " 即 19。 因此,如果用户输入一个 56 字节长的字符串(这是 guess.word 的最大长度),"len" 将是 75(输入的 56 + 19),而 "offset+i" 将是在 19 和 74 之间(实际上是 75,但循环将退出)。因此,当 "offset+i" 为 72 时,guess.result 将开始覆盖 guess.status(guess.result 为 72 字节长,guess.status 紧随其后),并且在"offset+i"=75 - 当 i=56 时发生,guess.word[56] 将是 guess.result[0],即 "W"(属于 "WRONG! YOUR...")。 从那里开始很容易。