Стэк

Материал из Russian Underground
Перейти к: навигация, поиск

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

Stek.jpg

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

Важно помнить две вещи:

  1. Cтек растет в сторону уменьшения адреса в памяти.
  2. При использовании команд push и pop нужно быть осторожным, потому что если элемент был помещен в стек последним, то из стека он будет вытолкнут первым.

Пример работы со стеком

Рассмотрим пример работы со стеком на небольшой задаче. Допустим, нам необходимо сохранить значения регистров eax, ebx и edx в стеке, потом произвести с ними необходимые действия и вернуть исходные значения этих регистров. На ассемблере это будет выглядеть так:

push eax // Помещаем в стек значение регистра eax. 
         // При этом указатель стека (esp) уменьшится на размер регистра eax,
         // т.е. на 4 байта (значение esp уменьшится на 4)
push ebx // Аналогично, только в стек поместится значение регистра ebx
push edx // То же самое, только в стек помещается значение регистра edx
.......  // Тут производим какие-то действия с регистрами eax, ebx, edx так, 
         // что значения этих регистров изменяются
pop  edx // Берем значение из стека (по адресу esp) и помещаем это значение в регистр edx.
         // В edx окажется его исходное сохраненное значение. 

Как видите если мы с помощью команды push edx помещали значение регистра edx в стек последним, то для возвращения значения регистра edx, команда pop edx должна идти первой. Так что действует принцип "последним зашел - первым вышел". После того, как значение получено из стека и помещено в регистр edx, указатель вершины стека (регистр esp) увеличивается на размер регистра edx, т.е. на 4.

pop  ebx // Аналогично берем из стека значение по адресу esp и помещаем его в регистр ebx. 
         // esp опять же увеличивается на 4.
pop  eax // Сами догадайтесь =)

Надеюсь основы работы стека из примера вам понятны. Вот еще один небольшой пример:

push eax
pop  ebx

Как вы думаете, что получится после выполнения данного кода? Конечно же значение регистра eax поместится в регистр ebx! Почему? Все очень просто. Команда push eax поместит значение регистра eax в стек. Команда pop ebx возьмет из стека последнее помещенное в него значение и поместит его в регистр ebx. А что было помещено в стек последним? Значение регистра eax! Таким образом ebx станет равным eax. Ну теперь все понятно?

Стек в OllyDbg

Нам часто придется наблюдать операции программ со стеком, все вызовы процедур и функций выполняются с активным участием стека, поэтому, занимаясь крэкерством. Непосредственно увидеть оперирование программ со стеком можно в отладчике OllyDbg, вот скриншот окна отладчика, на нём выделена область 9 (малиновым) - она и отображает стэк любой исследуемой программы.

OllyDbg2.png

Личные инструменты
Пространства имён

Варианты
Действия
Навигация
Сцена
Материалы
Разное
Donate
Инструменты