Стековый кадр
Сте́ковый кадр (от англ. stack frame) — механизм передачи аргументов и выделения временной памяти (в процедурах языков программирования высокого уровня) с использованием системного стека.
Технология
[править | править код]Обычно системный стек используется для сохранения адресов возврата при вызове подпрограмм, а также сохранения/восстановления значений регистров процессора.
Передача аргументов
[править | править код]При вызове процедуры аргументы отправляются в стек, и только потом производится вызов подпрограммы. Таким образом, процедура получает стек, на вершине которого лежит адрес возврата, а под ним — аргументы, с которыми она была вызвана.
При возвращении из процедуры (или после него, см. ниже) аргументы должны быть сняты со стека.
Выделение временной памяти
[править | править код]Если указатель стека сместить «выше» (в сторону увеличения стека), то часть памяти в стеке окажется незадействованной (в том числе и при вызове третьей процедуры) и может использоваться процедурой по своему усмотрению, вплоть до момента возврата в вызвавшую её процедуру. Таким образом, языки высокого уровня организуют переменные, существующие только внутри процедуры (язык Си называет их «автоматическими»).
Перед возвратом процедура должна вернуть указатель стека в оригинальное положение (то есть на адрес возврата).
Соглашения для разных языков программирования
[править | править код]Различные компиляторы языков высокого уровня по-разному подходят к организации стекового кадра в зависимости от особенностей аппаратной платформы и стандартов конкретного языка. Основные отличия касаются порядка передачи аргументов в стек и их снятия со стека при возврате.
Недостатки стекового кадра
[править | править код]Стековый кадр — удобная технология выделения временной памяти для передачи произвольного числа аргументов или внутреннего использования. Однако она имеет ряд недостатков.
Производительность
[править | править код]Передача данных через память без необходимости замедляет выполнение программы (по сравнению с программами на языке ассемблера, в которых большинство аргументов и временных данных размещают в регистрах процессора).
Для уменьшения обращений к локальным переменным программа оптимизируется при компиляции для использования регистров вместо переменных в памяти или для хранения их промежуточных значений.
Некоторые языки используют соглашения вызова, поддерживающие передачу целочисленных аргументов через регистры.
Безопасность
[править | править код]Стековый кадр перемещает данные приложения с критическими данными — указателями, значениями регистров и адресами возврата. Это, в сочетании с архитектурными особенностями некоторых процессоров (а именно — направлением роста стека), делает злонамеренное перекрытие критических данных в результате переполнения буфера очень легко достижимым (разумеется, прежде всего, программа должна содержать ошибку, которая позволит выполнить переполнение).
Такое «неудачное», с точки зрения переполнения буфера, направление роста машинного стека имеют аппаратные платформы: X86.
Атака по переполнению буфера в стеке обычно реализуется следующим образом:
- Атакующая программа отправляет на сетевое соединение (или другое средство межпроцессного взаимодействия) блок данных, заведомо больший размера буфера целевой программы.
- Неправильно написанная (уязвимая) процедура позволяет лишним данным быть записанными дальше границ буфера (т. е. допускает его переполнение), через начало стекового кадра и адрес возврата. Блок данных скомпонован так, чтобы адрес возврата в стеке замещался адресом кода эксплойта, который находится в том же загруженном блоке данных (выполнение этого кода с привилегиями выполняемой программы и есть цель атаки).
- При возврате из уязвимой процедуры управление через измененный адрес возврата передается на код эксплойта.
См. также
[править | править код]В статье не хватает ссылок на источники (см. рекомендации по поиску). |