Читаем Защита от хакеров корпоративных сетей полностью

Как было упомянуто ранее, стек позволяет решить многие задачи. Во-первых, обеспечить локальное хранение переменных и данных функции. Во-вторых, передавать параметры в вызываемую функцию. В этой части главы будет рассказано, как компиляторы передают параметры вызываемым функциям и как это влияет на стек. Кроме того, будет уделено внимание разъяснению вопросов использования стека в командах процессора вызов функции call и возврата из нее ret.

Основные сведения

Стековый фрейм функции (stack frame) – область памяти, выделяемая всякий раз, когда вызывается функция. Она предназначается для временного хранения параметров, содержимого регистра EIP и, возможно, любых других регистров, а также локальных переменных функции. Ранее внимание читателя было заострено на использовании стека при хранении локальных переменных, а теперь будет рассказано о других возможностях его использования.

Для того чтобы понять, как работает стек, следует немного знать о командах процессора Intel call и ret. Команда call – основная команда для существования функции. Команда позволяет выполнить другую часть кода, запомнив при этом адрес точки возврата в стеке. Для этого команда call работает следующим образом:

1) проталкивает в стек адрес следующей команды, который является адресом точки возврата – точки, куда процессор передаст управление (возвратится) после выполнения функции;

2) передает управление по указанному в команде call адресу для выполнения команд функции.

А команда ret делает противоположное. Ее задача состоит в том, чтобы возвратиться из вызываемой функции к команде, следующей за командой call. Для этого команда ret выполняет следующие действия:

1) извлекает из стека сохраненный адрес точки возврата;

2) передает управление по только что извлеченному из стека адресу точки возврата.

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

Передача параметров в функцию. Простой пример

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

На рисунке 8.4 приведена программа, которая поясняет структуру фреймового стека функции и его использование в командах call и ret.

Рис. 8.4. Пример программы, демонстрирующей использование стека в командах вызова и возврата

Дизассемблирование

Приведенная на рис. 8.4 программа была скомпилирована как консольное приложение Windows в режиме построения окончательной версии Release. Результаты дизассемблирования функций callex и main приведены на рис. 8.5 и демонстрируют машинный код функций callex и main после компиляции. Обратите внимание на передачу по ссылке буфера памяти buffer из функции main функции callex. Другими словами, функция callex получает указатель на буфер buffer, а не копию содержащихся в нем данных. Это означает, что все изменения в буфере buffer, выполненные в функции callex, тут же отражаются на содержимом буфера buffer в main, поскольку на самом деле это одна и та же переменная.

Рис. 8.5. Дизассемблированный вид функции callex

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже