====== Reverse Engineering и стек процессора ======
===== Введение =====
Одним из важнейших аспектов обратной разработки **Reverse Engineering** является понимание **архитектуры процессора** и, в частности, **работы стека**.
===== Архитектура x86/x64 и стек =====
==== Что такое стек? ====
Стек — это структура данных типа **LIFO** (Last In, First Out), которая используется для хранения временных данных, таких как:
* Аргументы функций
* Локальные переменные
* Возвращаемые адреса после вызова функций
==== Регистр ESP/RSP ====
В архитектуре x86:
* `ESP` — регистр Stack Pointer, указывает на вершину стека
В архитектуре x64:
* `RSP` — 64-битный стековый указатель
==== Работа стека в ассемблере ====
Пример простейшего вызова функции:
push ebp ; сохраняем предыдущий кадр стека
mov ebp, esp ; создаём новый фрейм стека
sub esp, 0x20 ; резервируем 32 байта под локальные переменные
...
mov esp, ebp ; восстанавливаем стек
pop ebp ; восстанавливаем старый ebp
ret ; возвращаем управление вызывающему коду
==== Пример вызова функции ====
; вызывающий код
push 0x2 ; аргумент 2
push 0x1 ; аргумент 1
call add_numbers ; вызов функции
...
add_numbers:
push ebp
mov ebp, esp
mov eax, [ebp+8] ; первый аргумент
add eax, [ebp+12] ; второй аргумент
pop ebp
ret
**Разбор:**
* `[ebp+8]` — это первый аргумент (находится выше сохраненного EBP и адреса возврата)
* `[ebp+12]` — второй аргумент
* `ret` — извлекает адрес возврата из стека
==== Визуализация стека ====
Когда функция вызывается, стек выглядит так (снизу вверх):
[ebp+12] — второй аргумент
[ebp+8] — первый аргумент
[ebp+4] — адрес возврата (EIP)
[ebp] — сохранённый ebp вызывающей функции
[ebp-4] — локальная переменная 1
[ebp-8] — локальная переменная 2
...
==== Команды работы со стеком ====
^ Команда ^ Описание ^
| `push reg` | Помещает значение регистра в стек, `ESP -= 4` |
| `pop reg` | Извлекает значение из вершины стека в регистр, `ESP += 4` |
| `call addr` | Помещает адрес следующей инструкции (`EIP`) в стек, затем прыгает по адресу |
| `ret` | Извлекает адрес возврата из вершины стека и прыгает на него |
===== Использование в Reverse Engineering =====
==== Отладка с помощью x64dbg, IDA, Ghidra ====
Инструменты позволяют анализировать вызовы функций, структуру стека, и регистры:
* Отображение `call stack` и `stack view`
* Анализ локальных переменных
* Распознавание аргументов функции
==== Распространённые приёмы защиты ====
* **Stack obfuscation** — запутывание структуры вызовов
* **SEH Overwrite** — атака через обработчик исключений
* **Return Oriented Programming (ROP)** — использование `ret` для обхода DEP
==== Reverse Engineering в практике: распаковка и декомпиляция ====
* Анализируем стек для отслеживания аргументов
* Ищем возвращаемые значения
* Отслеживаем, как программа взаимодействует с API
===== Советы по анализу стека =====
* Используйте **stack comments** в IDA для маркировки значений
* При анализе `ret` всегда проверяйте, что в стеке по адресу `[esp]` — правильный адрес возврата
* Определяйте calling convention: `cdecl`, `stdcall`, `fastcall`, `thiscall`
* Следите за соответствием push/pop пар
===== Заключение =====
Понимание работы стека — фундаментальный навык для любого инженера, занимающегося реверсом. Он позволяет точно определять логику исполнения, отлаживать, выявлять уязвимости и производить полную реконструкцию логики бинарного файла.
===== Полезные ссылки =====
* https://reverseengineering.stackexchange.com/
* https://wiki.osdev.org/Stack
* https://ghidra-sre.org/
* https://x64dbg.com/
* https://www.hex-rays.com/products/ida/