...
Примечание
В этой главе термин «ниже» («под») применяется к данным, которые были помещены в стек раньше каких-то других. Для описания данных, помещенных позже, применяется термин «выше» («над»). В архитектуре Intel стек растет вниз. В архитектурах с растущим вниз стеком адрес вершины уменьшается по мере роста стека, поэтому данные, расположенные «ниже», хранятся в областях памяти с большими адресами, чем данные, расположенные «выше».
Тот факт, что область памяти с большим адресом логически располагается в стеке ниже, может вызвать путаницу. Когда про область стека говорят, что она выше другой, это означает, что эта область находится ближе к вершине стека, чем другая.
В примере второй аргумент функции printf() – целое число, которое включается в формируемую строку в соответствии со спецификацией вывода целого числа со знаком %i. В результате в формируемой строке на месте спецификации формата будет помещено значение переменной integer в формате целого десятичного числа, которое равно 10.
В соответствии со спецификацией вывода целого числа со знаком функция printf() для формирования выводимой строки использует содержимое области памяти, размер которой совпадает с размером переменной целого типа и которая расположена в нужном месте стека. Сначала в соответствии со спецификацией формата двоичное представление содержимого выбранной области стека преобразуется в символьное представление, а затем включается в формируемую строку. Как будет показано позже, это происходит независимо от того, передан на самом деле второй параметр функции printf() или нет. Если ни одного параметра, соответствующего спецификациям формата форматирующей строки, не было передано функции printf(), то стековые данные вызывающей функции будут трактоваться как параметры, поскольку они занимают в стеке место предполагаемых параметров вызванной функции printf().
Вернемся к примеру. Допустим, что впоследствии было решено выводить только статическую строку, но при этом забыли указать переменную, соответствующую спецификации формата. В конечном счете функция printf() вызывается следующим образом:
printf(“this is the skeleton of the string, %i”); /* note: no argument. only a format string. */
Во время своего выполнения функция не знает, что ей забыли указать переменную, соответствующую спецификации вывода целого числа со знаком %i. Поэтому при формировании строки функция printf() прочтет целое число из области стека, в которую должен быть помещен второй параметр и которая занимает 4 байта под ее стековым фреймом. Если виртуальная память размещения второго параметра доступна, то программа продолжит свою работу и любые байты, оказавшиеся в области размещения второго аргумента, при работе функции будут проинтерпретированы и выведены как целое число. В результате будет напечатано следующее:
[dma@victim server]$ ./format_example this is the skeleton of the string, -1073742952
Отметим, что хотя при вызове функции printf() не был задан параметр функции, соответствующий спецификации вывода целого числа со знаком %i , тем не менее в формируемую строку было включено целое число. Функция прочитала из области стека, в которую был бы помещен незаданный параметр функции, какие-то данные и представила их в формате целого числа со знаком. В данном случае после представления найденных байтов в формате целого десятичного числа со знаком получилось число -1073742952.
Таким образом, если дополнить форматирующую строку своими спецификациями формата, то можно воспользоваться функцией printf() для просмотра содержимого стека, потому что функция printf() выведет содержимое областей стека в соответствии с заданными спецификациями формата.
Как будет показано дальше, возможность управления функцией printf() через входные данные программы может привести к образованию серьезной бреши в защите. При наличии программы с ошибками форматирующей строки, которая для формирования выводимой строки использует входные данные программы, злоумышленник сможет прочитать содержимое критических участков памяти. Такие участки памяти могут быть перезаписаны с использованием форматирующей строки с малопонятной спецификацией формата %n. Спецификация преобразования %n, известная также как указатель на целое, позволяет получить текущее число символов форматируемой строки в момент обработки указателя на целое. Как злоумышленник сможет воспользоваться ошибками форматирующих строк, будет объяснено далее во время изучения программы атаки, использующей ошибки форматирующей строки.
Читать дальше
Конец ознакомительного отрывка
Купить книгу