====== 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/