Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #58, СЕНТЯБРЬ 2005 г.

Защити свои приложения

Илья Рабинович

Спецвыпуск: Хакер, номер #058, стр. 058-034-3


И вроде бы все хорошо, все возможные пути проникновения в систему перекрыты. Так-то оно так, но не совсем. Исторически предтечи NX-бита появились на RISC-процессорах неIntell'овской архитектуры. Для них же впервые были созданы патчи на операционные системы, поддерживающие разграничение на исполнение кода внутри адресного пространства процесса. И именно для них появились первые "return-into-libc"-эксплойты за авторством Solar Desiner'а. Все гениальное просто. Если мы угадываем адрес системной функции, отвечающей за защиту страниц (оригинально исполняемые страницы модулей защищены от записи в них), и адрес функции копирования памяти из одного места в другое, мы можем скомпоновать данные при переполнении так, что при передаче управления первой его получит функция, отвечающая за защиту страниц с параметрами, которые позволят либо отключить защиту от записи в кодовую часть модулей, либо поставить атрибут "исполняемый" для какой-нибудь области памяти. После этого управление получает функция копирования с параметрами копирования нашего шелл-кода в уже подготовленную для исполнения область. Следующая часть Марлезонского балета: управление переходит на наш скопированный шелл-код в исполняемой области памяти. Как видишь, для реализации данного вида атаки необходимо: а) знать адреса функций; б) знать свой адрес; в) перехитрить проверки стека. И тут выясняется, что реализовать эти условия достаточно легко! Все необходимые функции для копирования памяти и управления параметрами защиты страницы реализованы в модуле kernel32.dll, база загрузки которого неизменна. Много угадывать не придется. Свой адрес мы можем также примерно знать, вбрасывая, например, большие порции данных 0x90 (команда nop) и шелл-кодом в конце. А перехитрить проверку целостности стека можно таким образом: мы переполняем буфер большим пакетом данных так, чтобы переписать ближайший адрес обработчика исключений SEH не просто, а чтобы он начал указывать внутрь какого-нибудь модуля на нужную нам последовательность опкодов. Например, add esp,XXX, ret. Теперь, при выходе их функции, буфер внутри которой мы переполнили, обычно сначала выполняется восстановление из стека сохраненных регистров, после чего идет проверка целостности стека. И тут выясняется, что было переполнение. SOS! Выбрасывается исключение, которое ловит – правильно! - уже наш обработчик SEH. Инструкция add esp,XXX очистит стек от тех данных, которые туда вбросила система при вызове обработчика в цепочке SEH, а инструкция ret передаст управление по нужному нам адресу, который мы уже заботливо положили в стеке. Цепочка "return-into-libc" успешно выполнена! Защита рухнула! Так что не бывает непробиваемых защит - бывают только плохо изученные. Нужно учиться, и тогда никакая защита не устоит перед тобой. Описанный пример лишь учебный, полет фантазии при проектировании шелл-кодов не ограничен ничем.

Назад на стр. 058-034-2  Содержание  Вперед на стр. 058-034-4