Causing a Buffer Overflow Using fgets

0

I'm trying to make a buffer overflow on a c program, but I can't manage to find the vulnerability and exploit the code.

I've tried thousands of inputs. Generally I've tried these: 1) I've tried the obvious - giving a very long string as an input. 2) I've tried to give a string so big that strlen() will acually return a negative value. 3)I've tried to give null bytes and EOF as an input, and append string. it wont let me enter those chars as input. 4)I've tried to override something, but nothing gets overridden (if i managed to override something, it's 70% of the way for me)

all of these I've tried with 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; 
}

for input 56 bytes long EXACTLY - I get segfault. for inputs larger than 56 - I get the buffer overflow "error" from the program. for very large inputs (over 10^6 bytes [long more or less]) - the program just sort of stuck.

I expect to manage to override anything, but I can't manage to override anything, maybe jump straight into the address that prints out the code(at 0x804889d)

below is assembly:

080485ab <get_input>:
 80485ab:       55                      push   %ebp
 80485ac:       89 e5                   mov    %esp,%ebp
 80485ae:       83 ec 18                sub    $0x18,%esp
 80485b1:       c7 45 f0 00 00 00 00    movl   $0x0,-0x10(%ebp)
 80485b8:       8b 45 0c                mov    0xc(%ebp),%eax
 80485bb:       83 c0 04                add    $0x4,%eax
 80485be:       83 ec 0c                sub    $0xc,%esp
 80485c1:       50                      push   %eax
 80485c2:       e8 99 fe ff ff          call   8048460 <malloc@plt>
 80485c7:       83 c4 10                add    $0x10,%esp
 80485ca:       89 45 f4                mov    %eax,-0xc(%ebp)
 80485cd:       83 7d f4 00             cmpl   $0x0,-0xc(%ebp)
 80485d1:       75 0a                   jne    80485dd <get_input+0x32>
 80485d3:       b8 fe ff ff ff          mov    $0xfffffffe,%eax
 80485d8:       e9 ac 00 00 00          jmp    8048689 <get_input+0xde>
 80485dd:       83 ec 0c                sub    $0xc,%esp
 80485e0:       68 60 89 04 08          push   $0x8048960
 80485e5:       e8 26 fe ff ff          call   8048410 <printf@plt>
 80485ea:       83 c4 10                add    $0x10,%esp
 80485ed:       a1 40 a0 04 08          mov    0x804a040,%eax
 80485f2:       8b 55 0c                mov    0xc(%ebp),%edx
 80485f5:       83 c2 04                add    $0x4,%edx
 80485f8:       83 ec 04                sub    $0x4,%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    $0x10,%esp
 8048608:       83 ec 0c                sub    $0xc,%esp
 804860b:       ff 75 f4                pushl  -0xc(%ebp)
 804860e:       e8 6d fe ff ff          call   8048480 <strlen@plt>
 8048613:       83 c4 10                add    $0x10,%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    $0xa,%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   $0x0,(%eax)
 8048639:       83 ec 0c                sub    $0xc,%esp
 804863c:       ff 75 f4                pushl  -0xc(%ebp)
 804863f:       e8 3c fe ff ff          call   8048480 <strlen@plt>
 8048644:       83 c4 10                add    $0x10,%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    $0xc,%esp
 8048653:       ff 75 f4                pushl  -0xc(%ebp)
 8048656:       e8 c5 fd ff ff          call   8048420 <free@plt>
 804865b:       83 c4 10                add    $0x10,%esp
 804865e:       b8 ff ff ff ff          mov    $0xffffffff,%eax
 8048663:       eb 24                   jmp    8048689 <get_input+0xde>
 8048665:       83 ec 08                sub    $0x8,%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    $0x10,%esp
 8048676:       83 ec 0c                sub    $0xc,%esp
 8048679:       ff 75 f4                pushl  -0xc(%ebp)
 804867c:       e8 9f fd ff ff          call   8048420 <free@plt>
 8048681:       83 c4 10                add    $0x10,%esp
 8048684:       b8 01 00 00 00          mov    $0x1,%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    $0x8,%esp
 8048691:       83 ec 0c                sub    $0xc,%esp
 8048694:       68 73 89 04 08          push   $0x8048973
 8048699:       e8 d2 fd ff ff          call   8048470 <puts@plt>
 804869e:       83 c4 10                add    $0x10,%esp
 80486a1:       8b 45 08                mov    0x8(%ebp),%eax
 80486a4:       83 ec 0c                sub    $0xc,%esp
 80486a7:       50                      push   %eax
 80486a8:       e8 d3 fd ff ff          call   8048480 <strlen@plt>
 80486ad:       83 c4 10                add    $0x10,%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    $0xfffffff0,%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    $0xb4,%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    $0xc,%esp
 80486eb:       68 84 89 04 08          push   $0x8048984
 80486f0:       e8 7b fd ff ff          call   8048470 <puts@plt>
 80486f5:       83 c4 10                add    $0x10,%esp
 80486f8:       83 ec 0c                sub    $0xc,%esp
 80486fb:       68 a8 89 04 08          push   $0x80489a8
 8048700:       e8 6b fd ff ff          call   8048470 <puts@plt>
 8048705:       83 c4 10                add    $0x10,%esp
 8048708:       83 ec 08                sub    $0x8,%esp
 804870b:       6a 38                   push   $0x38
 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    $0x10,%esp
 804871c:       89 85 64 ff ff ff       mov    %eax,-0x9c(%ebp)
 8048722:       83 bd 64 ff ff ff ff    cmpl   $0xffffffff,-0x9c(%ebp)
 8048729:       75 1a                   jne    8048745 <main+0x87>
 804872b:       83 ec 0c                sub    $0xc,%esp
 804872e:       68 e8 89 04 08          push   $0x80489e8
 8048733:       e8 38 fd ff ff          call   8048470 <puts@plt>
 8048738:       83 c4 10                add    $0x10,%esp
 804873b:       b8 ff ff ff ff          mov    $0xffffffff,%eax
 8048740:       e9 77 01 00 00          jmp    80488bc <main+0x1fe>
 8048745:       83 bd 64 ff ff ff fe    cmpl   $0xfffffffe,-0x9c(%ebp)
 804874c:       75 1a                   jne    8048768 <main+0xaa>
 804874e:       83 ec 0c                sub    $0xc,%esp
 8048751:       68 08 8a 04 08          push   $0x8048a08
 8048756:       e8 15 fd ff ff          call   8048470 <puts@plt>
 804875b:       83 c4 10                add    $0x10,%esp
 804875e:       b8 fe ff ff ff          mov    $0xfffffffe,%eax
 8048763:       e9 54 01 00 00          jmp    80488bc <main+0x1fe>
 8048768:       83 ec 0c                sub    $0xc,%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    $0x10,%esp
 804877a:       8b 45 f0                mov    -0x10(%ebp),%eax
 804877d:       3d 21 4e 49 57          cmp    $0x57494e21,%eax
 8048782:       75 37                   jne    80487bb <main+0xfd>
 8048784:       8d 85 70 ff ff ff       lea    -0x90(%ebp),%eax
 804878a:       83 c0 38                add    $0x38,%eax
 804878d:       c7 00 43 4f 52 52       movl   $0x52524f43,(%eax)
 8048793:       c7 40 04 45 43 54 21    movl   $0x21544345,0x4(%eax)
 804879a:       c7 40 08 20 59 4f 55    movl   $0x554f5920,0x8(%eax)
 80487a1:       c7 40 0c 20 45 4e 54    movl   $0x544e4520,0xc(%eax)
 80487a8:       c7 40 10 45 52 45 44    movl   $0x44455245,0x10(%eax)
 80487af:       66 c7 40 14 3a 20       movw   $0x203a,0x14(%eax)
 80487b5:       c6 40 16 00             movb   $0x0,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    $0x38,%eax
 80487c4:       c7 00 57 52 4f 4e       movl   $0x4e4f5257,(%eax)
 80487ca:       c7 40 04 47 21 20 59    movl   $0x59202147,0x4(%eax)
 80487d1:       c7 40 08 4f 55 52 20    movl   $0x2052554f,0x8(%eax)
 80487d8:       c7 40 0c 57 4f 52 44    movl   $0x44524f57,0xc(%eax)
 80487df:       c7 40 10 3a 20 20 00    movl   $0x20203a,0x10(%eax)
 80487e6:       83 ec 0c                sub    $0xc,%esp
 80487e9:       8d 85 70 ff ff ff       lea    -0x90(%ebp),%eax
 80487ef:       83 c0 38                add    $0x38,%eax
 80487f2:       50                      push   %eax
 80487f3:       e8 88 fc ff ff          call   8048480 <strlen@plt>
 80487f8:       83 c4 10                add    $0x10,%esp
 80487fb:       89 85 68 ff ff ff       mov    %eax,-0x98(%ebp)
 8048801:       83 ec 0c                sub    $0xc,%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    $0x10,%esp
 8048813:       89 85 6c ff ff ff       mov    %eax,-0x94(%ebp)
 8048819:       c7 85 60 ff ff ff 00    movl   $0x0,-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   $0x1,-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   $0x0,-0x58(%ebp,%eax,1)
 8048870:       83 ec 0c                sub    $0xc,%esp
 8048873:       8d 85 70 ff ff ff       lea    -0x90(%ebp),%eax
 8048879:       83 c0 38                add    $0x38,%eax
 804887c:       50                      push   %eax
 804887d:       e8 ee fb ff ff          call   8048470 <puts@plt>
 8048882:       83 c4 10                add    $0x10,%esp
 8048885:       8b 45 f0                mov    -0x10(%ebp),%eax
 8048888:       3d 21 4e 49 57          cmp    $0x57494e21,%eax
 804888d:       75 18                   jne    80488a7 <main+0x1e9>
 804888f:       a1 38 a0 04 08          mov    0x804a038,%eax
 8048894:       83 ec 08                sub    $0x8,%esp
 8048897:       50                      push   %eax
 8048898:       68 28 8a 04 08          push   $0x8048a28
 804889d:       e8 6e fb ff ff          call   8048410 <printf@plt>
 80488a2:       83 c4 10                add    $0x10,%esp
 80488a5:       eb 10                   jmp    80488b7 <main+0x1f9>
 80488a7:       83 ec 0c                sub    $0xc,%esp
 80488aa:       68 68 8a 04 08          push   $0x8048a68
 80488af:       e8 bc fb ff ff          call   8048470 <puts@plt>
 80488b4:       83 c4 10                add    $0x10,%esp
 80488b7:       b8 00 00 00 00          mov    $0x0,%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

I work in c9 environment.

also, I've read this topic: Causing a buffer Overflow with fgets not helping.

python
c
buffer-overflow
asked on Stack Overflow May 3, 2019 by Elyasaf755 • edited May 3, 2019 by Elyasaf755

2 Answers

1

the buffer overflow happens when you inpout exactly len characters the characters are copied into guess.word and the nul terminator overflows past the end.

the strcpy(guess.result,"thing" then ovewrites the nul then the for loop loops until it runs out of memory and you get a segfault.

a successful exploit will write a values to i and offset such that a: the loop terminates without hitting a bad memory address b: the value in status matches STATUS_WINNER

To do that LEN must be clobbered with a values less than 70

answered on Stack Overflow May 3, 2019 by Jasen
0

Thanks everyone for trying to help, all of you gave me great ideas, here is my solution:

In main function, there is this for-loop:

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

offset equals to the length of the string "WRONG! YOUR WORD: " which is 19. therefore, if the user enters a 56 bytes long of string (which is the max length of guess.word), "len" would be 75 (56 of input + 19), and "offset+i" would be between 19 and 74 (actually 75, but the loop will exit). therefore, when "offset+i" would be 72, guess.result would start override guess.status (guess.result is 72 bytes long, and guess.status is right after it), and at "offset+i"=75 - which happens when i=56, guess.word[56] would be guess.result[0], which is "W" (of "WRONG! YOUR..."). from there it's easy.

answered on Stack Overflow May 4, 2019 by Elyasaf755

User contributions licensed under CC BY-SA 3.0