В КУРСЕ?

Разбираемся в теме

Ghidra показала C-код: почему это ещё не восстановленный исходник?

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

Машинные инструкции и удобное представление

Дизассемблирование показывает инструкции анализируемой архитектуры. Декомпиляция помогает представить их действие на более высоком уровне. В Ghidra для такого преобразования используется промежуточное представление p-code, после чего формируется текст, похожий на C. Между строкой этого текста и отдельной машинной инструкцией нет обязательного соответствия один к одному. Одна операция может участвовать в нескольких выражениях, а привычная конструкция исходного языка после компиляции выглядеть иначе. Поэтому количество строк в окне декомпилятора не доказывает ни размер исходной функции, ни сложность её авторского варианта.

Имя переменной тоже может быть гипотезой

Автоматическое имя помогает ссылаться на объект, но обычно не объясняет его назначение. Если аналитик переименовал переменную в length, это ещё не означает, что программа действительно хранит в ней длину. Основанием должны стать наблюдения: где значение создаётся, с чем сравнивается и как используется дальше. Полезно вести отдельные записи: установлено, предположено, требуется проверить. Например, установлено, что значение сравнивают с нулём; предположено, что оно обозначает число элементов. Такая запись позволяет улучшать понимание, не превращая удобное название в неподтверждённый факт. Особенно важно это при передаче анализа другому человеку.

Уточнение типа меняет читаемость

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

Одинаковое поведение не раскрывает авторскую запись

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

Попробуйте на практике

На бумаге составьте протокол анализа условной функции. Она принимает целое число от нуля до ста; для входов 2 и 7 известны ответы 4 и 14.

  1. Запишите отдельно исходные наблюдения: допустимый диапазон аргумента и две известные пары входа и выхода. Пока не называйте назначение функции.
  2. Предложите две возможные записи вычисления, согласующиеся с данными: умножение на два и сложение аргумента с собой.
  3. Проверьте обе записи для входов 0, 1 и 100. Отметьте, различают ли новые проверки именно эти два варианта.
  4. Добавьте третью гипотезу: функция возвращает удвоенное значение только при входе меньше десяти, а иначе ноль. Найдите проверку, которая отделит её от первых вариантов.
  5. Сформулируйте вывод с границей уверенности: какие гипотезы различены, а какую авторскую запись установить не удалось.

Как проверить результат. Для входа 100 первые два варианта дают 200, третий даёт 0. Первые два по этим результатам не различаются; протокол не утверждает, что исходный текст программы восстановлен.

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

Можно ли сразу переименовывать всё по первой догадке?

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

Почему после уточнения структуры изменился текст функции?

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

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

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

Зарегистрироваться
← К списку материалов