
Плагин для визуализации покрытия двоичного кода для Ghidra
Dragon Dance — это плагин для Ghidra для визуализации и управления данными покрытия бинарного кода. Данные покрытия могут быть импортированы из нескольких источников покрытия. На данный момент плагин поддерживает инструменты бинарной инструментации Dynamorio и Intel Pin. Dynamorio имеет собственный модуль сбора покрытия под названием "drcov". Intel Pin не предоставляет встроенного модуля сбора покрытия. Чтобы исправить отсутствие модуля, мне пришлось написать собственный модуль сбора покрытия для Intel Pin. Поэтому я написал модуль сбора покрытия для Intel Pin под названием ddph (Dragon Dance Pin Helper). Вы можете его использовать. Исходный код ddph можно посмотреть по этой ссылке. Если вам лень компилировать самостоятельно, вы можете использовать скомпилированные бинарные файлы, которые я предоставил для Windows, macOS и Linux.

Dragon Dance может импортировать и использовать несколько данных покрытия в одном сеансе. (Также поддерживается мультисессионность, но на данный момент это не доступно через GUI). Вы можете переключаться между ними или быстро применять операции пересечения, разности, исключения или суммы.
Dragon Dance позволяет просматривать интенсивность выполненных инструкций. Так вы можете получить подсказку, какие инструкции как часто выполняются. Также вы можете просматривать визуализацию покрытия в окне графа функций.

Dragon Dance также поддерживает собственную систему скриптинга.

Она предоставляет гибкий способ работы с данными покрытия. Вы можете выполнять операции загрузки, удаления, отображения, пересечения, разности, исключения, суммы. Следующий раздел будет содержать систему скриптинга и API. Нажмите клавиши Alt + Enter для выполнения скрипта.
Встроенные функции — это реализация внутренних операций покрытия, предоставляющая интерфейс для системы скриптинга. Встроенная функция может возвращать переменную объекта покрытия или ничего. Встроенные функции могут иметь псевдонимы. Они принимают Built-in Arg в качестве параметра. Параметры могут быть переменной длины.
Built-in Arg — это ссылка для хранения значений разных типов. Built-in Args передаются слева направо. Built-in Arg может хранить следующие типы значений:
Переменные отвечают только за хранение объекта покрытия. Они могут быть загружены встроенными функциями. Они могут передаваться как параметр (Built-in Arg) встроенным функциям.
Существует два типа объекта покрытия.
Physical Coverage Object и Logical Coverage Object
Physical Coverage Object указывает на объект покрытия, загруженный напрямую из файла покрытия. Они видны в таблице покрытия в GUI. Таким образом, вы можете взаимодействовать с ними через операции GUI.
Logical Coverage Object указывает на объект покрытия, который был обработан во встроенной функции и возвращен из нее в качестве результата. Они не видны в GUI, но могут существовать в переменной до тех пор, пока не будут уничтожены.
Объект покрытия автоматически поддерживается объектом Variable для обоих типов объекта покрытия. Например;``` cov1 = load("firstcoverage.out") cov2 = load("secondcov.out")
cov1 = diff(cov1,cov2)
В этом примере cov1 и cov2 являются переменными. И обе переменные имеют объект физического покрытия. Встроенная функция diff принимает обе переменные и устанавливает возвращаемое значение в переменную cov1. Эта операция перезаписи установит результирующий объект покрытия в переменную, но не удалит объект покрытия, так как это физический объект покрытия. Эти данные покрытия останутся в сеансе, а также в таблице GUI.
Давайте рассмотрим предыдущий пример так;```
cov1 = load("first.out")
cov2 = load("second.out")
cov3 = load("third.out")
rvar = sum(cov1,cov2,cov3)
rvar = diff(rvar, cov2)
В этом примере три физические переменные покрытия поступают на операцию суммы, и операция суммы возвращает логический объект покрытия. Затем операция разности принимает логическую и физическую переменную и перезаписывает переменную с именем rvar.
В этом случае результат будет установлен в rvar, а его предыдущее значение покрытия будет немедленно уничтожено. Поскольку это был логический объект, его следует удалить во избежание утечки объектов. Если вы хотите уничтожить переменную, содержащую физический объект покрытия, вам необходимо вызвать встроенную функцию discard. Все встроенные функции будут подробно описаны ниже.
Вы можете писать сложные сценарии, используя вложенные вызовы встроенных функций, например:
cres = diff(intersect(a, load("another.log"), c, d), sum(e,f) )
вам не нужно писать логику строка за строкой.
Следующая документация API и их поведение могут измениться до выхода финальной версии.
clear()
| Свойство | Описание |
|---|---|
| Возвращаемое значение | None |
| Минимальное количество параметров | 0 |
| Максимальное количество параметров | 0 |
| Описание | Эта встроенная функция очищает текущее отображаемое покрытие и устанавливает активное покрытие в null. |
| Псевдонимы | None |
cwd( String : workingDirectory )
| Свойство | Описание |
|---|---|
| Возвращаемое значение | None |
| Минимальное количество параметров | 1 |
| Максимальное количество параметров | 1 |
| Описание | Устанавливает текущую рабочую директорию по заданному пути. Все вызовы import без абсолютного пути после cwd будут искать файлы покрытия в текущей рабочей директории. |
| Псевдонимы | None |
diff( Variable : var1, var2, ..... varN )
| Свойство | Описание |
|---|---|
| Возвращаемое значение | Variable |
| Минимальное количество параметров | 2 |
| Максимальное количество параметров | Неограниченно |
| Описание | Применяет операцию разности к заданному набору переменных переменной длины. И возвращает результирующую переменную покрытия. |
| Псевдонимы | None |
discard( Variable : var1, var2, ..... varN )