Рис. 8.13. Дамп стека после вызова функции
bof(),но до выполнения функции
strcpy()
Рис. 8.14. Дамп стека функции bof() после обращения к функции strcpy(), но до инициализации переменной buffer
Теперь в дампе стека видны два параметра функции strcpy. Первый параметр указывает на область буфера, размещенного в стеке, а второй – на статический буфер, вмещающий 20 символов «А».
Рис. 8.15. Дамп стека функции
bof()после инициализации переменной
bufferфункцией
strcpy()(сравните с рис. 8.13)
Из дампа стека видно, что функция strcpy(), проинициализировав буфер, уничтожила ранее записанные в стеке данные. В эпилоге функции bof() программа, попытавшись восстановить из стека содержимое регистра EBP, загрузит в регистр значение 0x414141. После этого команда ret восстановит из стека содержимое регистра EIP и попытается передать управление по восстановленному адресу. В результате возникнет ошибка нарушения доступа при попытке выполнить неразрешенную операцию с памятью, поскольку команда ret загрузит в регистр EIP значение 0x41414141, указывающее на недействительную область памяти (см. рис. 8.16).
Рис. 8.16. Диагностика аварийного завершения программы из-за неверного содержимого регистров EIP и EBP
Пример программы, уязвимой к переполнению буфера
После изучения основ переполнения буфера пришло время рассмотреть пример программы, извлекающей из него пользу, – программы переполнения буфера. В интересах простоты изучения программа должна быть понятной, а каждый шаг ее работы подробно исследован. Программа написана для платформ Windows NT и Linux.
Программа, уязвимая к переполнению буфера
Главная цель – привести в этой секции пример программы, уязвимой к переполнению буфера. Рассмотренная в этой секции программа очень похожа на последний пример, но вместо постоянной строки входных данных она использует ввод данных пользователя. Это позволило загружать в регистр EIP нужные данные.
Исходный текст программы, уязвимой к переполнению буфера
На последующих рисунках, начиная с рис. 8.17, представлена программа, предназначенная для считывания входных данных из файла в локальную переменную, размещенную в области стека. В результате присваивания этой переменной входных данных происходит переполнение буфера. Управляя входными данными программы, появляется идеальная возможность изучить возможности использования переполнения буфера. В программе вызывается специально написанная для примера функция bof(), которая открывает файл «badfile», считывает из него входные данные программы размером 1024 байта, записывает их в восьмибайтовый буфер и закрывает файл. При записи данных в буфер происходят переполнение буфера и порча данных стека, а по завершении функции bof() в регистр EIP загружается значение из файла «bad-file». Исследуем работу этой программы в Linux и Windows, приводя для обеих платформ соответствующие примеры.
Рис. 8.17. Пример программы, уязвимой к переполнению буфера
Дизассемблерование
На рисунке 8.18 представлен дизассемблерный вид функции bof(). Дизассемблерный вид всей программы на рисунке не показан, поскольку она аналогична предыдущей программе и отличается от нее только функцией bof(). При большом размере файла «badfile» во время работы функции fread() произойдет переполнение буфера, а команда ret функции bof() загрузит в регистр EIP величину из входных данных.
Рис. 8.18. Дизассемблированный вид функции
bof()
Дамп стека после переполнения
Главное предназначение этой программы заключается в анализе уязвимостей переполнения буфера, поэтому на рис. 8.19 показан дамп стека после выполнения функции fread(). Для примера был создан файл «badfile» с двадцатью символами «Л». После выполнения функции fread() область стека изменена так же, как и в предыдущей программе, но дополнительно появилась возможность управлять записью данных в буфер с помощью файла «badfile». Запомним, что в функции определена дополнительная переменная стека – указатель дескриптора файла (дескриптор файла – уникальный идентификатор, присваиваемый системой Windows файлу в момент его открытия или создания и существующий до момента его закрытия), которая размещена в старших адресах памяти стека сразу за областью буфера.
Рис. 8.19. Дамп стека после выполнения функции fread()
Программа переполнения буфера
После ознакомления с примером программы, уязвимой к переполнению буфера при чтении файла «badfile», пришло время познакомиться с программой, извлекающей из этого пользу, – программой переполнения буфера. Программа переполнения буфера написана на ANSI C, поэтому она может быть откомпилирована любым компилятором ANSI C. Для приведенных в книге примеров использованы компиляторы Visual C++ for Windows NT и GCC for Linux.
Читать дальше
Конец ознакомительного отрывка
Купить книгу