Информационная безопасность



              

Неизвестная уязвимость функции printf - часть 2


Комизм ситуации заключается в том, что некоторые вещи настолько привычны, что перестают обращать на себя внимание, и мысль проверить их, просто не приходит в голову.

Один из недостатков языка Си заключается в отсутствии штатных механизмов подсчета количества аргументов, переданных функции. Поэтому функциям с переменным числом аргументов приходится самостоятельно определять сколько параметров находится в их распоряжении. Для решения этой задачи функция printf использует специальную управляющую строку, которая состоит из служебных комбинаций символов – спецификаторов. Спецификаторы описывают тип и количество аргументов. Каждому из спецификаторов должна соответствовать "своя" переменная, но что произойдет, если такое равновесие нарушится?.

Когда спецификаторов меньше, чем переменных, ничего скверного не происходит, поскольку в языке Си аргументы удаляются из стека не самой функцией, а вызывающим ее кодом (который уж наверняка знает, сколько аргументов было передано). Поэтому разбалансировки стека не происходит, и все работает нормально, за исключением того, что отображаются не все указанные переменные.

Но если спецификаторов окажется больше, чем переданных переменных, то при попытке извлечь из стека очередной аргумент произойдет обращение к "чужим" данным, находящимся в этой области стека!

Такую ситуацию позволяет продемонстрировать следующий пример: “main(){int a=0xa;int b=0xb;printf("%x %x\n",a);}”, в котором присутствует один "беспарный" спецификатор “%x”. Поскольку содержимое стека на момент вызова функции “printf” зависит от используемого компилятора, то поведение данного кода неопределенно. Например, результат работы программы, полученной с помощью Microsoft Visual C++ 6.0, выглядит так: “a b”

Функция вывела два числа, несмотря на то, что ей передавали всего одну переменную “a”. Каким же образом она сумела получить содержимое переменной “b”? Ответить на этот вопрос поможет дизассемблирование машинного кода программы, в результате которого удается установить содержимое стека на момент вызова функции printf (сам дизассемблерный листинг в журнальном варианте статьи опущен, полный текст содержится в книге "Техника сетевых атак", которую планируется выпустить в скором будущем):




Содержание  Назад  Вперед