Покрытие кода - процедура, которая помогает исследователям понять, насколько много фрагментов алгоритма приложения задействовано в обработке данных. Обычно эта процедура используется для того, чтобы найти уязвимые места программного обеспечения. В этой статье мы на практике посмотрим, как можно использовать этот инструмент для упрощения процедуры исследования кода приложения.

Набор инструментов и настройка стенда

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

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

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

На картинке в качестве базовых единиц используется количество базовых блоков из dll библиотек ОС Windows. Также можно брать в качестве базовых единиц:

  • строку дизассемблированного листинга

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

  • блоки между инструкциями вызовов функций - call

Для простоты будем использовать в статье подход к исследованию с использованием следующей базовой единицы - дизассемблированный код между условными переходами. Настало время определиться с инструментами.

Описание стенда и набора инструментов

Для исследований приложений будем пользоваться:

  1. IDA Pro в качестве навигатора по дизассемблированному коду

  2. Проект DinamoRIO как инструмент построения покрытия кода

  3. Плагин IDA Pro LightHouse как инструмент визуализации покрытия кода для исследования алгоритма

  4. Виртуальная машина Windows 10

  5. Virtual Box в качестве среды виртуализации

План исследования будет очень прост. Берем рандомное приложение из набора CrackMe. Будем пользоваться вот этим ресурсом. Чтобы не разбираться с тем, как передать данные приложению, желательно выбирать CrackMe, которые принимают параметры из командной строки - так будет проще запускать инструменты для покрытия кода. Вообще это не ограничение, при желании можно написать обертку и просто передавать ей параметры. Но так как мы хотим проверить работоспособность нашего подхода к исследованию, будем использовать наименее трудозатратный подход. В качестве подопытного образца возьмем вот это приложение.

Практика

При установке инструментов особых сложностей возникнуть не должно. Проблемы могут появиться при настройке плагина для IDA Pro. Чтобы его установить, нужно сделать следующие действия:

  • Открыть исследуемый файл в IDA Pro

  • В строке IDAPython набрать команду: idaapi.get_user_idadir()

  • Полученный путь скопировать в проводник, если в результирующей директории нет директории plugins, создать её

  • скопировать содержимое директории репозитория plugins в директорию, созданную в предыдущем шаге

  • перезапустить IDA Pro

После успешной установки, должно появиться дополнительная опция в меню File:

Теперь можно приступать к сбору данных о приложении. Для сбора информации о покрытии кода, будем использовать инструмент drrun.exe с плагином drcov. Результирующая командная строка будет выглядеть так:

drrun -t drcov -logdir ./ --  KeygenMe.exe

Выбирать инструмент drrun нужно в соответствии с разрядностью исследуемого файла, так как в релизной версии DinamoRIO есть несколько версий приложения. В нашем случае берем инструмент из bin32. В результате в директории будет создан файл с расширением ".proc". Это файл с информацией о покрытии кода. Его нужно загузить в IDA Pro через опцию, котрая появилась после установки плагина. Результат представлен ниже на снике:

Цетовая схема показывает какие участки кода работали чтобы алгоритм мог обработать подаваемые данные.

Кстати, если перевести в режим декомпиляции, то цветовая схема сохраняется. Теперь наглядно видно, какие условия у нас уже отработали и какие условия еще не запускались.

Выводы

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


Статья подготовлена экспертом OTUS - Александром Колесниковым в преддверии старта курса Reverse-Engineering. Professional.

Всех желающих приглашаем принять участие в бесплатном двухдневном интенсиве по теме: "Пишем дампер процессов"