Эксперт OTUS - Александр Колесников поделился с нами полезной статьёй, которую написал специально для студентов курса Reverse-Engineering. Basic.
Приглашаем вас записаться на demo day курса, в рамках которого наши преподаватели подробно расскажут о программе курса, а также ответят на интересующие вас вопросы.
Доброго времени суток! В этой статье будет рассказано, как знание JavaScript и концепций работы современного программного обеспечения могут помочь в reverse engineering, а так же продемонстрировано, как можно использовать тулзу для динамической инструментации для анализа любого ПО на Linux, Windows, Android и iOS.
Frida
Вероятно, многие читали уже про феноменальную космическую мощь сабжевого фреймворка, но вся его слава обычно распространялась на Android и iOS. Об использовании для мобильных платформах можно прочитать здесь, а здесь можно найти даже интересные примеры для конкретных задач. Что же под капотом? На официальном сайте есть вот такая картинка:
Что это значит для конечного пользователя? Для фреймворка можно использовать скрипт для взаимодействия с функциями, которые находятся в движке V8, каким-то способом загруженного в адресное пространство исследуемого процесса, причем загрузка может быть как в процессе исполнения бинарного файла, так и добавление механизма загрузки уровне исходного кода. Касательно способов загрузки в память процесса, Frida может быть использована в 3-х видах:
Injected - запуск приложения и автоматическая загрузка V8 движка в память процесса;
Embedded - вид загрузки, который используется при патчинге исследуемого приложения. Frida предоставляет библиотеку - «frida-gadget», которая может быть использоваться для загрузки в процесс на этапе запуска самим приложением;
Preloaded - использование распространенного в Linux подобных операционных системах механизма - операционная система может позволить загрузить сторонний код в память процесса и запустить его на старте.
Как видно из списка, существует много опций для очень подробного исследования любого приложения.
Windows
Начнем практическую часть с изучения приложения под операционную систему Windows. Задание взято отсюда. Приложение представляет собой исполняемый файл и предлагает пройти 5 уровней защиты от отладки. Если запустим, то получаем вот такой вывод:
Похоже, что информация о расположении флагов есть, нужно только попасть к этой части памяти до того, как она будет уничтожена. Под отладчиком придется проходить много трюков и проверок. Для этого найдем функции, которые отвечают за логику нейтрализации отладчика. Из вывода приложения видно, что таких функций будет 5. Попробуем их найти с помощью radare2.
Найдем функцию через перекрестные ссылки. Сначала данные по строкам, которые были на экране. Посмотрим, что есть внутри функций, что должно остановить использование отладчика:
Стандартный способ: запатчить возвращаемое значение WinAPI функции, но это только 1 флаг. Патчить каждый очень долго и может не принести нужного результата. К тому же остальные функции уровней, которые используют другие подходы, которые нужно еще разобрать и понять как заставить вывести исполнение программы на создание флага.
Frida-Trace
Приложение, которое умеет ставить перехватчики на функции, перечисленные в качестве параметра. Перехватчики работают с названиями функций, поэтому использование этого инструмента полезно, если исследуемый файл содержит отладочные символы. В задании отладочные символы отсутствуют и могут использовать перехваты только для WinAPI функций. Попробуем это применить во благо себе. Возьмем любую функцию, которая есть в импортах этого файла, и попробуем посмотреть, какие данные она обрабатывает. Например, «WriteFile»:
Итак, frida-trace создала файлы с расширением js, которые имеют одинаковые названия с функцией WinAPI и находятся в директории «__handlers__». Посмотрим, что находится внутри:
Файл генерируется автоматически и содержит 2 функции, которые синхронно будут выполняться, как только будет вызвана функция «WriteFile». Таким образом, можно просматривать параметры, которые передаются в функцию, и данные, которые функция возвращает. Чтобы разобраться, сколько есть переменных, которые передаются в функцию, можно воспользоваться официальной документацией или прибегнуть к дизассемблеру. Воспользуемся первой опцией. Официальная документация содержит следующее определение для функции:
Итого 5 переменных. Мы можем их в общем виде представить как шестнадцатеричные значения с помощью функции log или send. В итоге скрипт приобретет следующий вид:
В результате перехват будет выглядеть так:
Хороший результат, таким образом, мы можем изучить любые данные передаваемые в WinAPI, но что, если нужно просмотреть информацию из функции, которая относится только к приложению? К сожалению, в этом случае frida-trace нам помочь не сможет, но есть и другие инструменты. Так как приложение быстро завершает свою работу, то единственный инструмент, который нам может помочь - frida.
Frida
Основной модуль, который предлагает интерактивный интерфейс для модификации и работы с уже работающим процессом. Этот инструмент может работать как инжектор в процесс на этапе запуска так и с версией, которая запускает отладочный сервер для работы с приложением. Запустим приложение:
Запущен интерактивный сеанс, приложение еще не начало выполнение, но процесс уже создан и загружены все библиотеки, которые использует приложение. Для всех платформ вызов функции «help» возвращает одно и тоже сообщение, которое есть на скрине выше. Дальше всё пойдет по наитию и используя документаций из официального сайта.
Базовые операции с помощью Frida выполняются за счет модулей:
Process - функции, которые используются для взаимодействия с характеристиками процессов;
Memory - функции, которые позволяют взаимодействовать с объектами в памяти;
Interceptor - функции, которые позволяют настраивать перехват для областей памяти и конкретных функций.
Используем модули для создания перехвата функции печати строки «Your flag is at [address]». Для этого необходимо по перекрестным ссылкам найти адрес, откуда вызывается функция:
На первых строках функции radare2 проставляет информацию об перекрестных ссылках - все 5 ссылок ведут к каждому из функций, которые используются для генерации флагов. Следовательно, можно попробовать получить данные именно из этой функции. Нужный адрес будет передаваться в качестве парного параметра с шаблоном «Your flag is at [address]». Для этого найдем смещение для функции, которая принимает в качестве параметров шаблон и адрес.
Итак, нас интересует смещение 0x57с4 от начала исполняемого файла. Чтобы провести мониторинг функции по смещению, нам необходимо узнать базовый адрес исполняемого файла и написать перехват для просмотра данных. Исходный код перехватчика будет следующим:
Запустим frida и продолжим исполнение приложения:
В итоге - мы видим 3 флага, которые были получены даже без анализа каждого из уровней приложения. Неплохой результат за 1 действие. Остальные 2 можно решить используя дополнительные функциии frida.
Native call
Заключительная часть статьи продемонстрирует, как можно получить все флаги, кроме 4го (этот будет на самостоятельное изучение). Frida предоставляет возможность вызывать любые функции исследуемого приложения. Делает она это за счет использования объекта NativeFunction. Чтобы им воспользоваться, достаточно просто определить прототип функции, которую мы хотим вызвать и далее согласно прототипу передать в нее значения. Давайте попробуем вызвать функцию для 1го уровня. Для этого возьмем адрес функции и определим ее прототип. Все вместе это будет выглядеть так:
Запустим код:
Как видно по картинке, теперь мы можем запускать любую часть приложения для того, чтобы получать данные от любых функций приложения. Однако есть только одна небольшая поправка. Иногда запуск функции возможен только после запуска главного потока приложения. Это связано с тем, что некоторые структуры и файлы еще просто не загружены в адресное пространство исследуемого приложения. Собственно, теперь нужно только запустить код перехватчика, который вы видели выше и получить все флаги.
Итог
Использование фреймворков вроде frida может сделать процесс исследования тривиальной, но и в тоже время увлекательной задачей. Между тем, frida позволяет учить новый язык программирования, который до этого считался языком для фронтенда сетевых ресурсов.
Узнать о курсе подробнее.