Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
dragondance — Ghidra的二进制代码覆盖率可视化插件 | Kitploit
工具/GitHubGitHub/0ffffffffh/dragondance
动态分析 (沙盒)代码分析逆向工程调试器模糊测试二进制分析
GitHub0ffffffffh/dragondance

dragondance

Ghidra的二进制代码覆盖率可视化插件

查看仓库
3004135年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

Dragon Dance

这是什么?

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 主界面

Dragon Dance 可以在同一会话中导入并使用多个覆盖率数据。(它还支持多会话,但目前 GUI 无法使用该功能)。您可以快速切换这些数据,或者对它们进行交集、差集、对称差集或求和运算。

Dragon Dance 允许您查看已执行指令的强度。这样您可以了解哪些指令执行得有多频繁。您还可以在函数图窗口中查看覆盖率可视化。

脚本

Dragon Dance 还支持自己的脚本系统。

它为您提供了一种灵活的方式来操作覆盖率数据。您可以对它们执行加载、删除、显示、交集、差集、对称差集、求和等操作。以下部分将包含脚本系统和 API。按 Alt + Enter 键执行脚本。

内置函数

内置函数是内部覆盖率操作的实现,为脚本系统提供接口。内置函数可以返回覆盖率对象变量,也可以不返回。内置函数可能具有别名。

它们接受 Built-in Arg 作为参数。参数可以是可变长度的。

Built-in Arg

Built-in Arg 是一个用于保存不同类型值的引用。Built-in Args 按从左到右的顺序传递。Built-in Arg 可以保存以下值类型:

  • 覆盖率数据对象(由内置函数返回)
  • 字符串
  • 整数(可以是十进制、十六进制或八进制形式)

变量

变量仅负责保存覆盖率对象。它们可以由内置函数加载。它们可以作为参数(Built-in Arg)传递给内置函数。

有两种类型的覆盖率对象:

物理覆盖率对象 和 逻辑覆盖率对象

物理覆盖率对象指向直接从覆盖率文件加载的覆盖率对象。它们在 GUI 上的覆盖率表中可见。因此,您可以通过 GUI 操作与它们交互。

逻辑覆盖率对象指向经过内置函数处理并返回结果的覆盖率对象。它们在 GUI 上不可见,但可以存在于变量中,直到被销毁。

覆盖率对象由 Variable 对象自动维护,适用于这两种类型的覆盖率对象。例如:``` cov1 = load("firstcoverage.out") cov2 = load("secondcov.out")

cov1 = diff(cov1,cov2)

root@kitploit:~
在此示例中,`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)

在这个例子中,三个物理覆盖率变量进入求和操作,求和操作返回逻辑结果覆盖率对象。然后,diff操作接受一个逻辑变量和一个物理变量,并覆盖名为rvar的变量。

在这种情况下,结果将被设置到rvar中,其之前的覆盖率值立即被销毁。因为这是一个逻辑对象,应该被删除以防止对象泄漏。如果你想要销毁一个包含物理覆盖率对象的变量,你必须调用内置的discard函数。所有内置函数将在下面详细介绍。

你可以使用嵌套的内置函数调用来编写复杂的脚本,例如可以这样写:

cres = diff(intersect(a, load("another.log"), c, d), sum(e,f) )

你不必逐行编写逻辑。

内置函数参考

以下API文档及其行为在最终版本发布前可能会发生变化。

clear()

属性描述
返回值无
最小参数数量0
最大参数数量0
描述此内置函数清除当前可视化的覆盖率,并将活动覆盖率设置为空。
别名无

cwd( String : workingDirectory )

属性描述
返回值无
最小参数数量1

diff( Variable : var1, var2, ..... varN )

属性描述
返回值Variable
最小参数数量2
最大参数数量不限
描述对给定可变长度的变量应用差集操作。并返回结果覆盖率变量。
别名无

discard( Variable : var1, var2, ..... varN )

属性描述
返回值无
最小参数数量1
最大参数数量不限
描述销毁变量,无论物理还是逻辑。它将首先销毁覆盖率对象,然后从变量列表中取消注册变量名称。此调用后,所有给定的变量变为未定义。
别名

distinct( Variable : var1, var2, ..... varN )

属性描述
返回值Variable
最小参数数量2
最大参数数量不限
描述对给定可变长度的变量应用异或(xor)操作。并返回结果覆盖率变量。
别名xor

goto( Integer : offset )

属性描述
返回值无
最小参数数量1
最大参数数量1
描述通过给定偏移定位当前地址选择。实际地址值通过将偏移值加到镜像基址计算得出。
别名无

import( String : filePathOrCoverageName )

属性描述
返回值Variable
最小参数数量1
最大参数数量1

intersect( Variable : var1, var2, ..... varN )

属性描述
返回值Variable
最小参数数量2
最大参数数量不限
描述对给定可变长度的变量应用交集操作。并返回结果覆盖率变量。
别名and

show( Variable : var )

属性描述
返回值无
最小参数数量1
最大参数数量1
描述可视化给定的覆盖率变量。如果存在一个活动可视化的覆盖率对象且是逻辑的,该函数立即销毁之前的覆盖率对象并显示给定的对象。
别名

sum( Variable : var1, var2, ..... varN )

属性描述
返回值Variable
最小参数数量1
最大参数数量不限
描述对给定可变长度的变量应用求和操作。并返回结果覆盖率变量。
别名or, union

修复

Dragon Dance 可以在导入覆盖率数据文件时尝试修复 ghidra 中可能的误分析情况。在某些二进制文件上,由于编译器产生意外代码,ghidra 无法反编译函数的指令。Dragon Dance 检查已加载的镜像和覆盖率数据的完整性。如果它们彼此有效,并且地址属于可执行段但缺少指令反编译,则插件会询问是否修复。然后它尝试通过反编译原始段来修复。

在插件的未来版本中,可能包含更多的修复或针对镜像的变通方法。

安装

安装非常简单。

启动 Ghidra。

点击“文件”菜单,然后选择“安装扩展...”

点击窗口右上角的绿色加号图标

选择插件 zip 包,然后点击确定。

从列表中选择 dragondance

点击确定并重启 ghidra

启动 DragonDance

在插件安装后,首次将二进制文件加载到 Ghidra 时,Ghidra 应该会询问你是否要配置新安装的插件。

如果点击“是”按钮,DragonDance 插件应该立即出现。

如果点击“否”按钮,你需要手动激活。

要手动激活,

点击“文件”菜单,然后从反汇编窗口(CodeBrowser)中选择“配置”

点击配置工具窗口右上角的小插头图标。

从插件列表中找到 DragonDance 项,启用其复选框,然后点击确定。

Dragon Dance 窗口应该出现。

激活后,你应该能够在“窗口”菜单中看到 Dragon Dance 项。

收集覆盖率数据

如前所述,Dragon Dance 可以从 Dynamorio 和 Intel Pin 导入覆盖率数据。(目前来说)。实际上,这些是通用的二进制插桩工具。你需要使用适当的模块与它们一起收集覆盖率数据。Dynamorio 有自己的覆盖率模块,称为 drcov。你可以使用该内置模块收集覆盖率。

使用 Dynamorio

你可以使用以下命令从 Dynamorio 收集覆盖率数据:

drrun -t drcov -logdir [覆盖率输出目录路径] -- [要检查的可执行文件路径] [可执行文件参数]

输出将以 drcov.[可执行文件名].[ID].proc.log 格式放置到给定目录中。

使用 Intel Pin

如前所述,Intel Pin 不提供任何内置的覆盖率收集模块。你必须使用自定义的 pin 模块。幸运的是,我制作了自己的模块来从 Pin 收集覆盖率。这为我们带来了一些优势。我可以在需要时扩展它,或添加额外功能、选项。

虽然后续版本可能也能工作,但目前仅支持 Intel PIN 3.7。这些版本未立即在 Intel PIN 页面上提供,此处提供直接下载链接:

https://software.intel.com/sites/landingpage/pintool/downloads/pin-3.7-97619-g0d0c92f4f-gcc-linux.tar.gz

https://software.intel.com/sites/landingpage/pintool/downloads/pin-3.7-97619-g0d0c92f4f-msvc-windows.zip

https://software.intel.com/sites/landingpage/pintool/downloads/pin-3.7-97619-g0d0c92f4f-clang-mac.tar.gz

你可以访问 ddph 的源代码此处。我将分享适用于 Windows、macOS 和 Linux 的二进制文件。你也可以使用其构建 shell 脚本构建自己的二进制文件。

要使用 Intel Pin 收集覆盖率数据,请使用以下命令:

pin -t ddph.[so,dylib,dll] [ddph 选项] -- [要检查的可执行文件路径] [可执行文件参数]

ddph 有一些收集选项。

-o:使用此选项可以指定覆盖率输出文件名。(默认值: ddph.out)

-l:可以指定操作日志文件名。如果将此选项传递为"no",ddph 将不执行日志记录操作。(默认值: ddph.log)

-p:捕获详细级别。此选项可以是 reduced 或 high。high 级别逐个捕获所有指令并构建预处理执行块。这将提供更密集的覆盖率输出,但比 reduced 慢。reduced 级别使用 pin 的 trace 块,因此比 high 级别快得多。但这不会在覆盖率输出上造成巨大差异。如果你不想做特定的事情,请考虑使用 reduced 级别。(默认值: reduced)

对于 macOS 用户: 从 macOS 10.11(OS X El Capitan)开始,操作系统附带了一个名为 System Integrity Protection SIP 的安全层。这会阻止用户模式进程尝试对另一个进程进行注入或修改,即使你在 root 权限下运行。

要克服这种阻止,你必须禁用它。请按照以下步骤操作。

重启 macOS

在启动过程中,按住 Command + R 键并保持按下。

系统最终会进入恢复模式

从“实用工具”部分打开终端

输入 csrutil status 并按回车。你应该看到 SIP 已启用。

输入 csrutil disable 并按回车。

再次输入 csrutil status 以确认是否已禁用。然后重启操作系统,让其正常启动。现在你可以使用二进制插桩工具了。

构建说明

首先,下载 ghidra(最新版本,目前为 9.1.2)和 dragondance``` $ wget https://ghidra-sre.org/ghidra_9.1.2_PUBLIC_20200212.zip $ wget https://github.com/0ffffffffh/dragondance/archive/master.zip $ unzip ghidra_9.1.2_PUBLIC_20200212.zip $ unzip master.zip

root@kitploit:~
接下来安装 gradle 和 jdk```
$ sudo apt install openjdk-11-jdk
$ wget https://services.gradle.org/distributions/gradle-5.2.1-bin.zip
$ sudo unzip -d /opt/gradle gradle-5.2.1-bin.zip

创建新的配置文件``` $ sudo vi /etc/profile.d/gradle.sh

root@kitploit:~
并将以下内容添加到每个后续登录的PATH中,以添加gradle。```
export GRADLE_HOME=/opt/gradle/gradle-5.2.1
export PATH=${GRADLE_HOME}/bin:${PATH}

立即执行,无需注销``` $ source /etc/profile.d/gradle.sh

root@kitploit:~
我们现在可以继续构建dragondance```
$ cd dragondance-master/
$ gradle -PGHIDRA_INSTALL_DIR=/home/ubuntu/ghidra_9.1.2_PUBLIC
> Task :buildExtension

Created ghidra_9.1.2_PUBLIC_20200506_dragondance-master.zip in /home/ubuntu/dragondance-master/dist

BUILD SUCCESSFUL in 29s
5 actionable tasks: 5 executed
ubuntu@ubuntu:~/dragondance-master$ 

你可能需要调整路径到你下载Ghidra的位置。现在你可以在 dragondance-master/dist 中找到构建好的扩展。

我希望引入的功能

命令提示符风格逐行执行脚本。

上下文变更感知

基于函数(例程)的覆盖可视化

执行流感知

脚本中更多内置功能

自有覆盖数据库格式,以便更快保存和加载,并在会话中保留最新更改。

伪代码着色。(Ghidra 未为此提供 API。因此我必须研究 Ghidra 的源代码,找出实现方法或变通方案。)

UI 增强

项目作者

Oğuz Kartal (@0ffffffffh)

下载工具
最大参数数量
1
描述使用给定路径设置当前工作目录。在cwd之后的所有没有绝对路径的导入调用,覆盖率文件将在当前工作目录中搜索。
别名无
del
描述从物理覆盖率文件导入覆盖率数据。接受相对或绝对路径。或者之前物理加载的覆盖率名称。如果给定路径是绝对路径,import直接从该路径加载。否则,它会在当前工作目录下查找加载。在这两种情况下,import都会检查该覆盖率数据是否已经加载(通过路径)。如果已加载,返回缓存的覆盖率变量。或者如果给定值是一个物理覆盖率的名称,它从其会话中查找覆盖率映射,如果存在则返回覆盖率对象。
别名get, load
无