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




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


Такая путаница объясняется тем, что термин "машинное слово" в одних случаях равен разрядности процессора, а в других приравнивается к двум байтам. Поэтому использование nargs порождает совершенно непереносимый код, работоспособность которого может быть нарушена даже изменением некоторых опций компилятора!

Некоторые разработчики предлагают собственный вариант реализации nargs, который сводится к следующему алгоритму: из стека извлекается адрес возврата из функции и, исходя из предположения, что он указывает на команду наподобие ADD SP, xx, производится попытка определить значение ‘xx’, равное количеству байт, помещенных в стек перед вызовом функции. Недостатки такого приема следующие: он не переносим на отличные от Intel 80x86 платформы; современные компиляторы ведут себя не так, как пять-десять лет назад, и генерируют чрезвычайно запутанный код, допускающий дисбаланс стека на некотором промежутке, отчего процедура анализа количества переданных функции аргументов по сложности приближается к самому компилятору.

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

Существует и другой вариант – вручную подсчитывать число аргументов и через специальный параметр передавать их функции. Но это слишком утомительно да и ненадежно.

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

1 Здесь и далее первый аргумент функции printf называется "строкой спецификаторов", а все последующие "переменными"   

2 Ну чем не трюк для соревнований в "магическом программировании"?   

3 Базовый адрес загрузки большинства приложений равен 0x400000   

4 Спецификатор "%f" "съедает" восемь байт, но сам занимает два байта, таким образом, в ста байтах вводимой строки можно расположить не более пятидесяти спецификаторов "%f", которые выведут четыреста байт.   

5 Тем самым он откроет доступ к коду и данным 32-разрядных приложений, исполняющихся под управлением операционной системы Windows NT, поскольку большинство из них расположено в памяти по адресу выше 0x00401000   




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