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