IO — Ivan Labs

Чтение дизассемблированного кода, когда вы годами не писали ассемблер

3 мин чтения
Реверс-инжиниринг

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

Сначала декомпилированный псевдокод, потом сырой ассемблер

Современные инструменты (Ghidra, декомпилятор Hex-Rays от IDA) автоматически конвертируют ассемблер обратно в псевдокод, похожий на C. Начинайте оттуда — это гораздо более читаемо, чем сырой ассемблер, и для большинства задач анализа достаточно точно само по себе.

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

Паттерны, которые стоит распознавать, а не запоминать

  • Пролог/эпилог функции — узнаваемая последовательность в начале и конце большинства функций, которая настраивает и разбирает кадр стека. Вы будете видеть одну и ту же форму снова и снова; её распознавание говорит вам «функция начинается/заканчивается здесь» без понимания каждой инструкции в ней.
  • Сравнения, за которыми следуют условные переходы — так выглядит оператор if на уровне ассемблера. Инструкция сравнения, за которой следует переход-если-равно (или подобное), — это версия ветвления в дизассемблированном коде.
  • Циклы как переход назад к более раннему адресу — цикл в исходном коде становится, на уровне ассемблера, сравнением и переходом назад к точке раньше в коде.
  • Ссылки на строки — декомпиляторы и дизассемблеры обычно показывают вам фактическую строку, на которую ссылается фрагмент кода (сообщение об ошибке, URL, строка формата). Это часто самый быстрый способ сориентироваться в незнакомом коде — найдите знакомую строку и работайте наружу оттуда.

Практическая стратегия чтения

  1. Сначала смотрите на декомпилированный псевдокод, а не на сырой ассемблер.
  2. Находите узнаваемые строки и работайте назад от места, где на них ссылаются — это часто приводит вас к релевантной логике быстрее, чем чтение сверху вниз.
  3. Следуйте за вызовами функций наружу от точки входа, а не читайте каждую функцию изолированно — контекст от вызывающего часто проясняет, что делает функция, ещё до того, как вы полностью прочитали её тело.
  4. Сравнивайте с кодом, который вы написали сами (см. наше руководство по началу работы с реверс-инжинирингом), когда паттерн выглядит незнакомым — воссоздание минимального примера и компиляция его самостоятельно часто быстрее, чем попытка разобраться в нём только по документации.

Что реально нужно запомнить (короткий список)

Реалистично, только: как выглядит сравнение-затем-переход, как выглядит вызов/возврат функции, и как распознать цикл. Всё остальное — конкретные мнемоники инструкций, соглашения о регистрах — вы усвоите постепенно просто из повторяющегося воздействия, так же как чтение иностранного языка становится легче с объёмом, а не с предварительным запоминанием.

Частые вопросы

Нужно ли мне писать ассемблер, чтобы хорошо его читать?

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

Стоит ли читать сырой ассемблер или декомпилированный псевдокод?

Начинайте с декомпилированного псевдокода (из Ghidra или Hex-Rays от IDA), когда он доступен — его драматически легче читать, и обычно достаточно точен для анализа. Переходите к сырому ассемблеру, когда вывод декомпилятора неясен или когда нужно понять точное низкоуровневое поведение, которое он абстрагирует.

Какой самый быстрый способ освоиться с этим?

Скомпилируйте небольшие, известные программы самостоятельно (см. наше руководство по началу работы с реверс-инжинирингом) и сравните ваш исходный код с дизассемблированным/декомпилированным выводом бок о бок — распознавание паттернов, для которых вы уже знаете ответ, гораздо быстрее, чем попытка разобраться в незнакомом коде с нуля.

Нужна помощь с этим?

Свяжитесь со мной, и я помогу разобраться.

Связаться со мной

Похожие статьи

Поделиться:X / TwitterLinkedIn