Привіт і ласкаво просимо назад.
У цьому уроці ми розглянемо те, що називається очищенням стека.
Існує два способи очищення стека.
Хто чистить стек?
Це може бути або caller, тобто головна функція, або callee, тобто дочірня
функція.
Існує дві назви для цих різних способів очищення стека.
У ситуації, коли викликач очищає стек, це називається угодою CDECL, і вона посилається
на угоду мови C.
У другій ситуації, коли стек очищає викликач або функція, що викликається,
використовується угода STDCALL, також відома як угода Microsoft, оскільки
цей метод реалізовано в усіх API від Microsoft, а API - це не що інше, як набір функцій.
У цьому випадку під Microsoft API мається на увазі сукупність усіх функцій Microsoft.
Тож давайте подивимось, як вони виглядають у коді.
У першому випадку, коли за очищення стека відповідає головний або той, хто викликає, ви впізнаєте
цей код.
Ось приклад, який ми розглядали в попередньому уроці, де у нас є дві функції: головна і дочірня
функція.
А тут ми просто намагаємося обчислити, що Y дорівнює MX плюс C.
Отже, ми виштовхуємо три значення в стек, а потім
викликаємо дочірню функцію.
А після повернення функції ви очищаєте стек.
Отже, це рядок, який ви бачили раніше, де ви додаєте - 12.
Отже, 12 тут, оскільки їх три, ви кладете
три СЛОВА до стопки.
Тож тепер вам доведеться його почистити.
Ось чому ви додаєте 12 до -, щоб вказівник - перемістився вниз до початкової позиції, в якій він був до того,
як було зроблено поштовхи.
Тож саме тут абонент відповідає за очищення стека.
Тому ми називаємо це з'їздом CDECL або конференцією CDECL.
Тепер давайте розглянемо іншу конвенцію - STDCALL.
Отже, тепер ми перепишемо той самий код, але замість того, щоб очищати стек, функція буде
очищати стек.
Ось як це виглядає.
Отже, тут ви помітили, що я вже видалив цей рядок, де абонент очищає стек.
Зараз калієр чистить стос.
Тож як каліє чистить стос?
Пам'ятайте, що callee має функцію повернення.
До речі, функція return приймає параметр.
У цьому випадку ви можете передати йому параметр.
Зазвичай параметром, який ви йому передаєте, є кількість байт, які ви хочете очистити.
Отже, в даному випадку це 12.
Отже, ви пройшли 12.
Отже, RET 12 тут має дві функції, два значення.
Перше, що вона зробить, це витягне цю адресу зі стеку в регістр -, щоб вона могла повернутися
до неї після виклику.
Друга річ, яку він робить, це очищає стек.
Це означає, що до вказівника стеку додається 12.
У цьому і полягає сенс RET 12.
RET
12 означає те ж саме, що і ADD 12 до -.
Ось як функція виклику або дочірня функція очищає стек.
Отже, зараз ми розглянемо другий спосіб очищення стеку і подивимося, як він працює в коді.
Використовуйте x64dbg.
Що я зробив, так це взяв попередній код, код 72. Я взяв попередній код, а саме цей код тут,
72 Stack convention,
і змінив певні частини.
Тож це та частина, яку я змінив.
Я видалив цей рядок, який містив код для очищення стеку.
Ось цей рядок я видалила.
Дозвольте мені показати вам ще раз.
Це рядок, який я видалила.
Я тільки що його завалив.
А потім я пішов у печеру коду і додав і змінив return тут, щоб додати параметр для повернення.
Тож я пішов до печери кодів і додав сюди 12, а C - це шістнадцяткове значення 12.
Тож це дві зміни, які я зробив.
Після цього я виправив його і зберіг під іншим
ім'ям файлу, новим ім'ям файлу, і назвав його 73-Cleaning-Stack-With-RET.
Це все.
Тому я закликаю вас зробити це також для того, щоб у вас була додаткова практика з програмування на асемблері.
Тож давайте повернемося до основної функції і подивимося, як вона працює.
Поставте точку зупинки за цією адресою і перейдіть до неї.
Потім переступайте через нього
по черзі, і ви побачите, що тепер три, А і п'ять штовхаються до стопки.
Тож наступний - п'ятий.
Отже, тепер у нас є три в стопці: три, десять і п'ять.
Ці троє. Зараз ми зробимо крок назустріч цьому виклику.
Отже, коли ви ввійдете в цей виклик, він виштовхне зворотну адресу до стеку.
Отже, ця адреса буде виштовхнута до стеку наступною.
Тож подивимося, як це станеться.
Ми входимо у виклик, і тепер зворотна адреса виштовхується на вершину
стека, а під нею - три попередні виштовхування: три, десять і п'ять.
А тепер давайте переступимо через це.
Він перемістить ці дані, п'ять, десять і три в регістри
-, -, і -.
Тож давайте переступати через рядок за рядком, і він рухається один, два і три.
Всі три значення зі стеку тепер переміщуються в -, -, і -.
Потім він виконує обчислення.
Тож нехай так і буде.
І ось тут все по-іншому.
Тут ми зробимо дві речі.
Він витягне це значення зі стеку, і в той же час очистить стек так, що вказівник
стеку переміститься за цією адресою, 6448, і вкаже на цю адресу, за якою він знаходився
до натискання кнопки в головній функції.
Тож давайте зробимо крок і подивимось, як це відбувається.
І там, дійсно, з'являються всі три вищезгадані адреси.
Він виводить цю адресу у вікні - зареєструватися.
Ви бачите - тепер він має цю адресу, і він повернувся туди, а також очистив стек.
Отже, тепер новий вказівник стеку, верхня частина вказівника стеку - це нова адреса внизу.
Ось як ваш виклик очищає стек, і цей метод
називається конвенцією STDCALL.
Отже, ось як можна почистити стопку,
і ви повинні знати обидва способи очищення стопок.
Це важливо знати, щоб не заплутатися в тому, чому іноді ви бачите
ADD - 12, а іноді не бачите його. Якщо ви не бачите цього рядка після
виклику, це означає, що використовується угода STDCALL, де повернення, де дочірня
функція очищає стек.
Якщо ви бачите ADD - після виклику, це означає, що використовується угода CDECL, CDECL
- це та сама, CDECL угода, де саме той, хто викликає, очищає стек.
І якщо ви збираєтеся вставляти код у будь-які програми, ви повинні бути обережними з очищенням стеку, якщо
ви не використовуєте RET для очищення стеку.
Крім того, якщо ви хочете використовувати RET для очищення стека, то вам не слід очищати стек
тут.
Просто передайте параметр у стек, що містить кількість байт, які ви хочете очистити.
Отже, вам потрібно вибрати або це,
або це, якщо ви збираєтеся вставляти код в інші програми, які ви зламуєте.
На цьому відео все.
Дякуємо за перегляд.