Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #32, ИЮЛЬ 2003 г.

СТЕК 2, ПЕРЕЗАГРУЗКА

Alex Shark

Спецвыпуск Xakep, номер #032, стр. 032-020-1


(qqqqqwww@e-mail.ru, http://nevod.nm.ru)

ЧТО ТАКОЕ BUFFER OVERFLOW И КАК ЭТО ЮЗАТЬ?

К сожалению, никому не дано понять, что такое стек. Ты все должен увидеть сам. Съешь красную пилюлю - и я покажу тебе дизассемблер и что творится на самом деле в компьютере. Съешь синюю - и ты проснешься в привычном мире окон...

Читатель берет зеленое колесо и проваливается в канализацию...

ЧТО ТАКОЕ СТЕК

Тем, кто знаком с понятием стека, можно пропустить этот абзац. Представь, ты попал в мир Великого Дани. Ты сидишь в школьном классе, у всех на партах стоят телефоны, но рты у всех заклеены скотчем. Есть бумага и ручки, передавать листики запрещено, потому что можно ненароком оторвать руку или ногу товарищу. Есть главный перец, его зовут Ядро. Есть кедр, который умеет складывать числа. И еще один умеет их умножать. Ядру приспичило посчитать формулу 2*3+10. Он берет три листка, пишет на первом - 2, на втором - 3, на третьем - свой телефон. Кладет это все на стол (это и есть стек), звонит Умножителю. Тот берет эти листики, рвет и кладет листок с цифрой 6. После чего перезванивает Ядру. Тот докладывает в кучу листок с числом 10 и опять листок с телефоном Ядра. Звонит Складывателю. Тот вытаскивает три листика, рвет и кладет листок с числом 16, после чего перезванивает Ядру. Все, Ядро доволен и сияет.

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

ПОСЛЕДНИЙ, НА ВЫХОД!

Наиболее распространенный вид стека - это LIFO (Last In First Out, последним пришел - первым ушел). Если сравнить с листками, то кладут листки друг на друга, а берут начиная с верхнего. Если взять последний листик и попытаться еще раз вытащить данные, то происходит исчерпание стека. То есть вершина и позиция не могут проходить друг сквозь друга. Есть еще вид стека FIFO, похожий на конвейер. Такой стек, как правило, имеет четкий размер, и при занесении в стек позиция записи передвигается вперед, при вытаскивании вершина передвигается в том же направлении. То есть они просто ходят по кругу. Система очень напоминает работу с потоками данных.

ЧТО ТУДА ПОПАДАЕТ?

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

Содержание  Вперед на стр. 032-020-2