Тест переполнения буфера в 32-разрядной версии Fedora без изменения значения регистра $ eip

#c #gdb #fedora #cpu-registers #buffer-overflow

#c #gdb #fedora #cpu-регистры #переполнение буфера

Вопрос:

Я пытаюсь выполнить простое переполнение буфера на 32-разрядной Fedora, но значение регистра eip не меняется

Мой код на C выглядит следующим образом :

 #include <string.h>
int main(int argc, char ** argv){
    char buffer[8];
    strcpy(buffer, argv[1]);
}
  

Я попытался выполнить :

 echo 0 > /proc/sys/kernel/exec-shield
echo 0 > /proc/sys/kernel/randomize_va_space
  

чтобы отключить любую защиту.
А также я скомпилировал так:

 gcc -g -Wall -fno-stack-protector -z execstack -m32 boftest.c -o boftest
  

Когда я запускаю команду

 ./boftest AAAABBBBCCCCDDDD
  

А затем наблюдайте за значениями регистров с помощью gdb;
Я вижу, что:

 ebp contains  0x44444444, but 
eip contains 0x80483F4
  

это означает, что $ eip не был успешно изменен.

Я прочитал другие вопросы с той же проблемой, но ни одно из решений не сработало для меня. Есть ли у вас какие-либо идеи, как заставить это работать?

Комментарии:

1. Вы понимаете, что вы вызываете UB при прохождении AAAABBBBCCCCDDDD , верно?

2. Используйте strndup вместо этого. Я думаю, что вы пытаетесь передать AAAABBBBCCCCDDDD как адрес, поэтому вам нужно использовать функцию, аналогичную atoi .

3. Поведение переполнения массива не определено, чего именно вы ожидаете?

4. Вам следует попробовать использовать более длинный аргумент. Также покажите разборку main и точное место, на которое вы смотрите $EIP (лучше покажите весь сеанс GDB).

Ответ №1:

Хорошо, я думаю, что в конечном итоге я понял, что пошло не так. Я пробовал тест переполнения буфера на Fedore 9 Linux. Я перепробовал все модификации, но ничего не сработало.

Итак, я сменил ОС на Ubuntu 12.04, и тест сработал отлично. При выполнении ./boftest `perl -e 'print "A" x 200'` значение $eip регистра было перезаписано на 0x41414141 где 0x41 — шестнадцатеричное значение символа ‘A’, что означает, что тест переполнения буфера сработал.

Я думаю, что проблема была в ОС Fedora, возможно, она предлагала другие уровни защиты от переполнения буфера, о которых я не знал, в то время как версия ubuntu 12.04 этого не делала. Мне нужна была только команда echo 0 > /proc/sys/kernel/randomize_va_space для работы теста.

Ответ №2:

Одним из возможных результатов является то, что копия перезаписывает стек всего, что было в стеке до вызова main . Вы проверяете регистры. Вместо этого проверьте стек, на который указывает EPB.

EIP — это указатель инструкции, поэтому я не понимаю, почему вы думаете, что это каким-то интересным образом изменится. Обратите внимание, что машинные инструкции не находятся в стеке в x86. Также нет гарантии, что адрес возврата находится в стеке, поэтому вам не обязательно изменять его с помощью записи переполнения, если это то, что вы хотите.

Если вы хотите изменить EIP, вам нужно изменить указатель на какую-либо функцию или что-то в этом роде. Добавьте указатель на функцию по буферу, а затем вызовите его в конце main и посмотрите, изменили ли вы EIP путем переполнения записи поверх указателя функции.

Комментарии:

1. Спасибо за ваш ответ, но в конечном итоге моя проблема была связана с ОС Fedora, которая предлагала дополнительную защиту от переполнения буфера, о которой я не знал. Я попробовал тест на Ubuntu, и он сработал. На самом деле целью было изменить обратный адрес программы, который хранится в стеке. Поэтому, когда $ eip будет указывать на обратный адрес в конце, он будет указывать на перезаписанное значение, которое мы изменили.