PracticU

Стек и Регистры процессора

Без субтитровС субтитрами
PracticU › Курс хакинга - Hacking - Взлом серверов и сетей - Пентест OSCP › Стек и Регистры процессора
Словарь терминов:
функция - Именованный участок кода, который выполняет задачу, принимает входные параметры и может возвращать результат.
безопасность - Защита систем, данных и сетей от угроз, несанкционированного доступа и повреждения.
память - Быстрое энергозависимое устройство, где компьютер держит данные и программы во время их работы. Очищается при выключении.
переменная - Именованное место в памяти, где хранится значение, которое может меняться во время работы программы.
динамический - Определяемый и меняющийся во время работы, а не заданный заранее.
адрес - Значение, которое однозначно определяет объект: устройство в сети, ячейку памяти или ресурс.
число - Тип данных для хранения числовых значений, целых или дробных.
защита - Средства и меры, оберегающие систему, данные или сеть от сбоев, потери и несанкционированного доступа.

Стек и Регистры процессора
Лекция разбирает, как устроены стек, регистры процессора и вызов функций: что кладется в стек, как процессор помнит, куда вернуться после функции, и почему это важно для безопасности. Все показано пошагово в отладчике Immunity Debugger на примере Notepad.
Области памяти программы
1. Код (text): команды программы, которые процессор исполняет. Доступен для чтения и исполнения.
2. Инициализированные данные: глобальные переменные фиксированного размера с начальным значением, например int со значением 3.
3. BSS: глобальные переменные фиксированного размера без начального значения. При запуске они заполняются нулями.
4. Heap (куча): динамические структуры, которые растут во время работы программы. Память под них выделяется во время исполнения, например через malloc. Растет вверх.
5. Stack (стек): локальная память функций. Растет вниз.
Как работает вызов функции
1. Что попадает в стек: при вызове функции сначала кладутся параметры, затем адрес возврата (следующая команда, которую нужно выполнить после функции), после этого сохраняется EBP.
2. Регистры: ESP указывает на вершину стека, EIP на следующую исполняемую команду, EBP на базу кадра функции. Локальные переменные удобно адресовать относительно EBP.
3. Сохранение регистров: функция сохраняет в стеке регистры, которые собирается менять, и восстанавливает их перед выходом, чтобы главная программа продолжила работу без изменений.
4. Возврат: команда return берет адрес возврата из стека и загружает его в EIP. Стек при этом не очищается, указатель просто сдвигается.
5. Порядок байтов: в памяти x86 многобайтовые числа хранятся в обратном порядке (little endian), поэтому в дампе памяти значения выглядят перевернутыми.
Обратите внимание
EIP хранит только один адрес, поэтому адрес возврата обязательно лежит в стеке. Если программа записывает данные за пределами своего буфера, она может испортить сохраненный адрес возврата, и тогда процессор перейдет по постороннему адресу. Защита это запрет исполнения команд из секций данных: в 64-битных системах и на процессорах с NX-битом это включено по умолчанию, а в 32-битных системах его нужно включать вручную через DEP.
Студент понимает, как функции используют стек и регистры и почему память, предназначенная для данных, не должна исполняться.

Содержание лекции: Стек и Регистры процессора

  1. 00:00

    Введение: стек и регистры процессора

  2. 00:58

    Сегменты данных и переменные

  3. 01:49

    Размер переменной и тип int

  4. 03:58

    Стек и локальные переменные функций

  5. 06:00

    Отладчик Immunity Debugger

  6. 10:07

    Регистр EIP и следующая команда

  7. 12:29

    Порядок байтов little-endian

  8. 18:59

    Стек растет вниз и адрес возврата

Расшифровка лекции: Стек и Регистры процессора

Полный текст первых минут лекции «Стек и Регистры процессора» из видеокурса PracticU – субтитры с временной меткой для каждого абзаца. Так можно прочитать и найти нужные темы ещё до начала обучения.

  1. 00:02

    Добро пожаловать на лекцию про стэк и регистры. На этой лекции мы поймем, из чего составлен этот стэк, как он пополняется, какие у нас есть регистры в процессоре.

  2. 00:13

    Мы это прямо увидим с помощью дебагера от латчика. Это будет очень интересная лекция. Давайте только напомним, что во время запуска программы, во время запуска экзешника, у нас сначала копируется код программы.

  3. 00:26

    Вот этот вот текст, они его называют текст-сегмент или код-сегмент. Он копируется внутрь памяти оперативной, чтобы компьютер работал быстро.

  4. 00:38

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

  5. 00:52

    И этот сегмент в read-only находится с правами доступа read-only и execute, то есть право исполнения. Далее, выше него находятся сегменты с памятью, то есть данными.

  6. 01:06

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

  7. 01:18

    И у них фиксированный размер и заранее известный. Например, переменная val, это ее название, ее могли назвать любым другим именем. назвали val от слова value наверняка значение просто какая-то переменная ячейка в памяти которая обозначается именем val и у него уже есть значение поэтому это

  8. 01:39

    называется инициализированные данные у нее значение 3 в момент ее создания в нее уже сразу же записывается значение 3 потом можно будет поменять во время программы во время исполнения и самое важное что у нее есть фиксированный размер. То есть нам заранее известно размер и значение этой переменной. И

  9. 01:59

    размер это int. int это значит 32 бита и это могут быть цифры. 32 бита это 32 единички нуля. Из них можно сделать 4 миллиарда вариаций, то есть 4 миллиарда разных чисел. Но в случае integer мы делаем, используем его от минус 2 миллиардов до плюс 2 миллиарда. Это

  10. 02:20

    вот случай интеджера. Если вам не нужно такое количество битов. Если вам не надо 32 бита, не надо 4 байта в памяти, вы можете попросить другой тип данных, и тогда вам выделится меньше памяти и меньше будут траты.

  11. 02:34

    Но мне самое главное вам показать, что в этом отсеке памяти, в этом разделе памяти, в этом сегменте памяти сидят переменные с фиксированным размером и заранее известным значением. То есть в момент инициализации, в момент создания переменной

  12. 02:49

    у нее уже есть значение. А в BSS, который выше этого, следующий отсек, сидят тоже переменные с фиксированным размером, но у них нету значения во время инициализации, и в них вставляется нолик. Это называется Uninitialize, то есть не инициализированные

  13. 03:08

    данные. У них фиксированный размер, но они не имеют значения в момент создания. Далее мы переходим на хип. В хипе сидят списки, динамичные списки, то есть списки, которые могут увеличиваться во время работы программы. Например, моя программа принимает из клавиатуры новых учеников в класс. И я не знаю, как программист, сколько учеников будут

  14. 03:33

    в классе, кто запустит мою программу. И мой список все время растет и, например, увеличивается. И тогда нам нужна переменная, которая будет указывать на этот список, и она будет расти по мере надобности.

  15. 03:46

    И для этого у нас есть динамичная память, размер которой не фиксирован заранее. И мы используем команды как malloc, чтобы взять еще кусок динамичной памяти. Это называется heap.

  16. 03:58

    И эта динамичная память растет кверху, то есть с нулевых адресов кверху растет, растет, растет. И сколько будет использовано, столько будет использовано.

  17. 04:08

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

  18. 04:21

    Например, у меня в программе на сайте есть вспомогательная функция для главной программы, которая говорит, проверь для этого номера паспорта, его абонемент еще действительен или нет.

  19. 04:34

    Или другая функция, которая помогает главной программе проверить для этого абонемента, для этого номера паспорта, этот фильм разрешен или нет.

  20. 04:44

    То есть главная программа вызывает вспомогательные куски кода, которые называются функции. Они там что-то делают и возвращают ответ главной программе.

  21. 04:54

    Преимущество функции то, что, во-первых, все поделено на логические блоки и не одной кашей, не одними макаронами. То, что называется, все подряд идет, а все поделено на логические блоки.

  22. 05:07

    Если мне надо в двух разных местах проверить абонемент, мне не надо писать код проверки абонемента по номеру паспорта 2, 3, 5 раз.

  23. 05:15

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

  24. 05:21

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

  25. 05:39

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

  26. 05:54

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

  27. 06:06

    Давайте перейдем на настоящий Windows, на десятку, запустим дебаггер, отладчик и посмотрим, что происходит в настоящей памяти. Я запускаю Immunity Debugger, это бесплатный отладчик, бесплатный дебаггер, вы его можете скачать.

  28. 06:20

    И мы что делаем с помощью этого дебаггера? Мы ему говорим, открой какую-то программу и после каждой его команды, после каждой команды, которую ты делаешь, возвращайся ко мне в отладчик.

  29. 06:32

    То есть отладчик говорит, например, запускай команду, там, программу Notepad, но не запускай ее одним махом, а запускай каждую строчку отдельно, каждую команду отдельно и после каждой команды возвращайся ко мне в отладчик.

  30. 06:45

    Я хочу посмотреть, что происходит в памяти. Вот мы загрузили Notepad, мы видим здесь список всех команд, который внутри этого экзешника, то есть мы смотрим сейчас на память, на этот машинный код, который загрузился с этого notepad, с этого блокнота в память нашего компьютера,

  31. 07:02

    в оперативную память, и мы видим, что происходит. И мы видим первое, что я смотрю на CPU, видите? Это view, это вид на процессор, и здесь есть все команды.

  32. 07:12

    У нас есть разные виды, я сейчас не буду переходить в другие и вас путать. Нас сейчас интересуют команды, мы хотим посмотреть на этот view CPU. И вот список всех команд.

  33. 07:22

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

  34. 07:37

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

  35. 07:49

    То есть i8 это то, что написано в экзешнике. И его интерпретация, и его перевод на языке ассемблера, чтобы нам было легче на это смотреть.

  36. 07:59

    Это как бы такая расшифровка называется disassembler. И левая колонка это адрес памяти, в которой сидит эта команда. То есть команда i8, которая на языке ассемблера расшифровывается как код, это кодировка.

  37. 08:13

    Она сидит в памяти, в нашей операционной памяти, по адресу ff1860. Запомните этот адрес 1860, потому что мы сейчас будем вызывать функцию и потом возвращаться обратно.

  38. 08:27

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

  39. 08:34

    Видите, она сейчас находится на паузе, то есть мы можем перезагрузить ее сначала. Он загружает все в память и перед тем, как делать первую команду, переходит на паузу.

  40. 08:43

    То есть он все загрузил, готов к исполнению первой команды. И он ждет, чтобы мы ему дали команду либо play, либо сделать только один шаг.

  41. 08:51

    Я не делаю play, я хочу сделать пошагово и посмотреть, что происходит внутри памяти после каждой команды в экзешнике. Так мы видим, что у нас адрес памяти 1860, и в нем есть команда call, вызвать функцию по адресу ff20c2.

  42. 09:06

    Это адрес, который сидит от кода этой функции. Мы сейчас пройдем пошагово и посмотрим, что происходит в регистрах, что происходит в памяти, что происходит в стеке.

  43. 09:16

    Мы с вами рассмотрим, как работает компьютер, и потом поймем, в чем проблема, и как хакеры этим воспользовались.

  44. 09:23

    Это называется атака Buffer Overflow. Так, давайте сейчас вернемся к нашим делам. Нам надо сейчас запустить эту функцию, но нам надо запомнить, куда вернуться, потому что когда мы ее закончим, нам надо знать, куда вернуться.

  45. 09:37

    И для этого у нас есть регистры и есть стэк. Вот справа мы видим вот эти вот регистры. Видите, процессор регистры. Это 64-битный процессор, и регистры – это маленькие его помощники.

  46. 09:50

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

  47. 10:03

    Сюда он кладет ту информацию, которая ему нужна. Это как рабочий стол для вас. И эти регистры, их совсем немножко, и они вплотную рядом с памятью.

  48. 10:11

    Например, видите адрес 1860, это где сделать следующую команду? Это прописано в регистре EIP. Регистр EIP указывает процессору, какую следующую команду сделать.

  49. 10:23

    И вот, заметьте, что он всегда будет указывать этот регистр EIP на следующую команду. И процессор идет туда, в эту ячейку памяти, которая прописана в EIP, и исполняет команду, в этом случае команда E8 call на такую-то функцию.

  50. 10:37

    Давайте сейчас вот нажмем на эту стрелочку, видите, это Step Into, то есть сделать один шаг, включая вход в функцию. То есть если есть вызов функции, сделать один шаг и войти в эту функцию, если она вызывается.

  51. 10:50

    Кстати, рядом есть Step Over, это значит сделать один шаг, но если есть функция, быстро-быстро всю функцию исполнить и вернуться на главную программу.

  52. 11:01

    То есть я не заинтересован смотреть пошагово внутри функции. В моем случае я заинтересован пошагово смотреть внутри функции, я нажимаю Step Into.

  53. 11:10

    И заметьте, мы сейчас перепрыгнем на адрес ff20c2. Мы прямо на него перепрыгнем, то есть мы с адреса 1860 перепрыгнем на этот адрес. Но не просто перепрыгнем, а вызовем функцию.

  54. 11:21

    И вот мы действительно перепрыгнули на этот адрес ff20c2. Это адрес в памяти, и здесь первая команда какая? Поместить в ECX в значение, которое есть вот в таком-то отделе памяти.

  55. 11:34

    То есть мы в реестр ECX хотим поместить какое-то значение из памяти. Команда Move это копировать. Но меня сейчас интересует EIP. Реестр EIP.

  56. 11:45

    Этот регистр, видите, указывает теперь на этот следующий адрес. Далее у нас есть команда Push ESI. Что это за Push ESI? Перед тем, как мы перейдем к ней, давайте предыдущую команду посмотрим.

  57. 11:57

    Видите, ECX копировал то, что было в памяти 4.2.1.0. Видите, реестр ECX поменял свой цвет. Потому что у него значение поменялось, и мне дебаггер показывает то, что изменилось другим цветом.

  58. 12:10

    Я сейчас ищу в дампе памяти, то есть в списке адресов памяти, вот этот 42100, ff42100. И вот я вижу, что в этом 42100 написано 11f0e3d4.

  59. 12:24

    И вот это вот значение должно было скопироваться в реестр ECX. И заметьте, что он действительно скопировался только в обратном порядке.

  60. 12:33

    И это что-то новое, что мы видим в первый раз. что данные копируются в обратном порядке в память. Почему это происходит?

  61. 12:40

    Потому что мы работаем по стандарту, который называется Little Indian. По этому стандарту самые маленькие числа, например, 11, видите, самое маленькое число, записывается в самый маленький отсек памяти.

  62. 12:53

    То есть нижний адрес несет себе нижнее число. Но с нашей точки зрения это выглядит наоборот. Есть стандарт Big Indian, и там это все выглядит намного лучше, как мы привыкли. Короче, знайте, что всегда то, что в памяти, сидит в обратном порядке по байтам.

  63. 13:11

    Каждые две числа – это отдельный байт, и это сидит в обратном порядке. Так, мы с вами рассмотрели первую команду move внутрь реестра памяти. Мы увидели, что реестр поменялся. Это маленькая память рядом с процессором.

  64. 13:29

    И мы увидели, что с главной памяти, вот с этого адреса в главной памяти, был скопирован в реестр какое-то значение. Еще стоит заметить, что он мне пытается помочь, и для каждого байта, вот для каждых двух цифрок, он пытается их расшифровать по стандарту ASCII.

  65. 13:47

    То есть, ну это мне совершенно не помогает в этом случае, просто он пытается. Это в конце концов просто числа, которые сидят в памяти. Это оперативная память, да, это RAM.

  66. 13:58

    Давайте только немножко это все увеличим, и мы можем, кстати, сказать ему по 16 байтов показывать мне. То есть он мне показывает сейчас восьмиричные системы измерения, то есть в 8 байтах, а я могу ему сказать, покажи мне в 16 байтах.

  67. 14:13

    Видите, у нас есть теперь 16 байтов в каждой строчке, и адреса идут 10, 20, 30, потому что это эксодоцимальные, все числа в эксодоцимальной системе измерения. То есть у нас есть адрес и значение.

  68. 14:26

    Я могу ему сказать, покажи мне это в каждой строчке на экране, там, например, Unicode, расшифруй это по Unicode, по стандарту Unicode.

  69. 14:35

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

  70. 14:50

    То есть это вся память, это в конце числа, и вопрос, как их расшифровывать. Например, я сделаю disassemble, и он меня их превратил в команды, то есть расшифровал по стандарту, каждое число значит какая-то команда.

  71. 15:02

    То есть все зависит от нашего стандарта, как мы его расшифровываем. И в конце концов в памяти сидят просто числа. Это могут быть данные, это могут быть команды.

  72. 15:15

    Все зависит от как мы их понимаем, по какому стандарту мы их расшифровываем. И внизу вот мы видим этот hexdump, то есть просто эти числа в памяти.

  73. 15:25

    А наверху мы видим эту же память, уже расшифрованную по стандарту команд. Так, давайте перезагрузимся. Начнем сначала.

  74. 15:33

    Так что у нас мы начинаем сначала, включили отладчик notepad и первая команда call И заметьте адрес, который у нас сейчас 1860, это наш текущий адрес И мы вызываем функцию по адресу F20C2 И вот у нас сейчас EIP указывает на текущую команду

  75. 15:55

    Какие у нас еще есть интересные регистры У нас есть еще регистр ESP, который указывает нам на стэк, на адрес стэка Мы сейчас это все увидим с вами.

  76. 16:08

    И внизу у нас есть еще флажки. Флажки – это результаты вычислений. Вот эти вот флажки – это, например, результат вычисления, был ли ноль или не был нулем.

  77. 16:18

    Вышел он из границ разрешенного или не вышел из разрешенных границ. То есть вот эти вот флажки – это результаты разных сравнений и вычислений. Мы это скоро тоже увидим.

  78. 16:29

    То есть у нас есть регистры, у нас есть флажки. Сказать, по правде, есть еще много чего, но мы сейчас не на уроке ассемблера. Я вам хотел показать, что такое регистры, как они работают, и мы рассмотрим 5 регистров, и рассмотрим стэк и обычную память.

  79. 16:48

    Смотрите, что если я нажму на память, она превратится в доллар. Что значит доллар? Доллар это означает база. Вот я хочу считать этот адрес в памяти базовым, и тогда относительно него, я могу говорить относительно этой базы, возьми приплюсуй 5, приплюсуй 10.

  80. 17:06

    То есть работать не с абсолютными числами, а с относительными числами. Это называется offset. То есть относительно какой-то базы я работаю.

  81. 17:17

    И я могу решить, что база будет наверху, и тогда у меня моя текущая команда будет база плюс два, offset плюс два. И вот этот вот базовый адрес, он часто используется.

  82. 17:30

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

  83. 17:45

    Так, и у нас есть EBP, видите, EBP, который указывает на начало, на базу для нашей текущей функции, для нашего текущего стека. Еще раз, у нас есть стек.

  84. 17:57

    Стек это наш черновик, отдел памяти, в котором сидят переменные нашей функции. Вот мы сейчас зайдем в функцию, у нас откроется этот черновик, этот стек.

  85. 18:08

    И в этом стеке, видите, сейчас адрес, давайте я вам сейчас покажу, какой у него адрес, здесь плохо видно, вы все поймете, не беспокойтесь. Видите, ESP указывает на адрес 53FEDC.

  86. 18:22

    Вот этот вот адрес, это там, где стек, вот внизу мы его прямо и видим. 53FEDC, это адрес памяти, в котором сидят данные стека. На данный момент там что-то сидит в этом стеке, и в тот момент, когда мы перейдем внутрь функции, мы в этот стэк, в этот отдел памяти, положим число во время вызова функции, положим число не просто так, а в которое

  87. 18:49

    нам надо вернуться потом. То есть видите стэк, заметьте, DC был, да, вот этот DC, и он взял и поднялся наверх на D8, то есть стэк уменьшается каждый раз, каждый раз, когда мы кладем в него число, он уменьшается, его адрес становится меньше, это все адреса в памяти.

  88. 19:07

    И он сохраняет, заметьте, вот этот вот 1865, то есть команда call функции положила в стэк адрес возврата, в который надо прийти по окончанию этой функции.

  89. 19:20

    Так функция знает, куда перейти потом, когда мы вернемся. Видите, и мы вернемся на 1865, а сейчас мы перепрыгнули на адрес 20c2. Давайте запустим все заново и еще раз посмотрим.

  90. 19:35

    Видите, мы находимся в адресе 1860, и нам надо по окончанию функции, по окончанию кола, вернуться на 1865. Поэтому адрес возврата мы положим в стэк, чтобы знать, куда вернуться.

  91. 19:49

    Стэк – это отдельный регион памяти, как бы наш черновик такой, в который мы кладем вещи, кладем информацию, потом забираем информацию. И на этот стэк всегда указывает регистр ESP, который указывает на адрес этого стэка.

  92. 20:04

    Видите, мы прыгнули, сделали команду call, и в наш стэк попал адрес 1865, это адрес возврата. Я вам показываю, что происходит во время вызова функций.

  93. 20:15

    И заметьте, что, кстати, адрес ESP тоже поменялся, то есть хедер стэка. Давайте я вам еще раз продемонстрирую. Я делаю каждый раз стрелочку налево и демонстрирую.

  94. 20:25

    Мы начали с 1860. Вызываем функцию на ff20c2, эту функцию, которую мы вызовем. По окончанию этой функции мы должны вернуться на адрес 1865.

  95. 20:36

    Чтобы не потерять место, куда нам надо вернуться, потому что у нас в регистре и EIP есть место только для одного адреса, чтобы EIP, который указывает на следующую команду, не потерялся, мы его сохраним в стеке.

  96. 20:51

    Видите, в адресе D8 сохранился адрес возврата на 1865. Почему это надо? Потому что в компьютере в EIP, где исполняются следующие команды, То есть в регистре EIP есть место только для одного адреса.

  97. 21:06

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

  98. 21:17

    Далее мы видим команду move ECX. Видите, этот ECX мы уже рассматривали. Сейчас у нас, видите, стек дальше идет по нулям и он уменьшается. Его адреса уменьшаются, потому что стек растет в минус, то есть он уходит к нулевым адресам.

  99. 21:34

    И мы видим команду push ESI. Что такое push ESI? Сохранив стэк, push в стэк, вот это вот команда на языке ассемблера, номер у него, видите, системный 56, push ESI, то есть сохранив стэк то, что есть в реестре ESI.

  100. 21:52

    Почему он это сохраняет? Потому что он хочет испортить реестр ESI, сохранить там новое значение. Посмотрите, там через 2-3 строчки там есть новое значение зайдет в этот ESI.

  101. 22:02

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

  102. 22:16

    Потом, когда мы закончим все делать и перед тем, как возвращаться, мы возвратим и восстановим это значение ESI. Давайте посмотрим, как это все происходит.

  103. 22:26

    То есть мы делаем push ESI. Вот наш ESI. Где он? Вот он. Видите? FF1860. Мы его прямо видим здесь. Это вот значение этого реестра, этого помощника, этой памяти, которая рядом с центральным процессором.

  104. 22:41

    И она должна зайти вот в этот адрес FAD4. Давайте исполним одну команду и увидим, что действительно в FAD4 поместится значение, которое есть в ESI.

  105. 22:51

    Вот этот вот 1860. И также ESP должен сдвинуться. ESP это первая значимая верхушка стека. Видите, он указывает ESP на FAD8. Вот этот FAD8 указывает процессору, где сейчас находится стэк, какой адрес в памяти.

  106. 23:11

    Мы видим, что это вот этот вот адрес. Мы исполняем одну команду. Мы видим действительно, что ESP сдвинулся. Видите, у него другой цвет стал. И 1860 попал в этот адрес памяти, где были до этого нули.

  107. 23:25

    Видите, то есть стэк сдвинулся вверх. Голова стэка сдвинулась вверх. Видите, он изменился, поэтому он таким цветом стал. Все, что изменяется в команде во время исполнения команды, меняет свой цвет.

  108. 23:36

    И он поменял свой цвет, значит стэк сдвинулся наверх. Если вы помнили, до этого он был D8. И в него сохранилось значение.

  109. 23:45

    И EIP сдвинулся на следующую команду 20C9. И следующая команда какая? Сохранить EDI. Следующая команда говорит ему сохранить

Полный курс: Курс этичного хакинга онлайн

Предыдущая лекция: Секции оперативной памяти

Следующая лекция: Переполнение стекового буфера - Buffer overflow - Fuzzer

Другие курсы этого направления

  • Курс хакинга - Hacking - Взлом Active Directory - OSCP
  • Курс хакинга - Hacking - Тестирования сайтов на уязвимость
  • Курс хакинга - Hacking - Взлом Android приложений