Обязательным условием понимания приведенных в главе способов переполнения буфера является знание принципов работы стека. Стек используется почти каждой функцией для передачи входных и выходных параметров. Регистр ESP указывает на вершину локального стека, а регистр EBP – на базовый регистр стека. При вызове функции содержимое регистров EIP и EBP сохраняется в стеке для того, чтобы в конце работы функции обеспечить дальнейшую работу программы.
Атаки переполнения буфера обыгрывают идею подмены сохраненного в стеке содержимого регистра EIP и передачи управления на нужный программный код. Успешная реализация идеи позволит выполнить на машине любую программу. Для успешного использования уязвимости необходимо иметь загрузчик, точку перехода, программный код полезной нагрузки и программу переполнения буфера. Загрузчик размещает в нужное место программный код полезной нагрузки, точка перехода позволяет передать управления на нужную программу – программный код полезной нагрузки, а программа переполнения буфера управляет их работой.
Известны многочисленные способы улучшения программы переполнения буфера. В главе рассмотрены способы фильтрации входных данных и вопросы частичного переполнения буфера. Показаны способы переполнения динамически распределяемой памяти («кучи») и варианты использования ее уязвимостей. Наконец, было исследовано несколько способов улучшения управляющего кода: использование уже существующего программного кода и загрузка кода, недоступного во время выполнения программы переполнения буфера.
Стек
· Область стека предназначена для хранения локальных переменных функции. Обычно она настраивается для работы в прологе функции – части программного кода, расположенного в начале функции, и очищается в эпилоге – части программного кода, расположенного в ее конце.
· Нередко отдельные части области стека используются как буферы данных функции. Из-за особенностей принципов работы стека размер буфера данных не изменяется на протяжении всей жизни функции.
· Некоторые компиляторы при генерации выполнимого кода могут использовать ряд хитроумных способов работы со стеком для оптимизации размера функции и времени ее выполнения. Имеются также разнообразные способы вызова функции и передачи ей параметров, которые влияют на использование стека в пределах функции.
Стековый фрейм функции
· Стековый фрейм функции – область памяти, выделяемая всякий раз, когда вызывается функция. Она предназначается для временного хранения параметров, локальных переменных функции, оставшегося от предыдущего вызова функции содержимого регистра EBP и содержимого регистра EIP, указывающего на точку возврата.
· Содержимое регистра ESP указывает на вершину стека, содержимое регистра EBP – на дно. Значение регистра ESP меняется по мере выталкивания и проталкивания данных в стек. Регистр EBP обычно является базовым регистром для ссылки на локальные стековые переменные.
· Команды процессора Intel call и ret позволяют вызывать и завершать функцию. По команде call в стеке сохраняется содержимое регистра EIP, которое указывает на точку возврата. По команде ret из стека восстанавливается значение регистра EIP и управление передается в точку возврата из функции.
Основы переполнения буфера
· Копирование чрезмерно большого количества данных в буфер ведет к повреждению части стека.
· Поскольку по команде ret в регистр EIP будут загружены данные из стека, то при перезаписи области хранения в стеке содержимого регистра EIP данными пользователя команда ret загрузит в регистр адрес перехода, указанный пользователем.
Пример программы, уязвимой к переполнению буфера
· В программу переполнения буфера входят загрузчик, адрес перехода и программный код полезной нагрузки.
· Загрузчик записывает программный код полезной нагрузки в указанный буфер. В зависимости от ситуации загрузка может осуществляться сетевыми средствами, с помощью формы ввода или чтения из файла.
· Адрес перехода – адрес, который подменяет сохраненное в стеке содержимое регистра EIP. Имеется много возможностей для подмены содержимого регистра EIP с целью непосредственной или косвенной передачи управления нужной программе. Ряд способов позволяет повысить надежность передачи управления, например к ним относятся способ последовательности операций NOP (NOP sleds) или способ распыления динамически распределяемой памяти (heap spray).
Читать дальше
Конец ознакомительного отрывка
Купить книгу