#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 будет указывать на обратный адрес в конце, он будет указывать на перезаписанное значение, которое мы изменили.