写在前面
此系列是本人一个字一个字码出来的,包括示例和实验截图。本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正。 如有好的建议,欢迎反馈。码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作。如想转载,请把我的转载信息附在文章后面,并声明我的个人信息和本人博客地址即可,但必须事先通知我。
你如果是从中间插过来看的,请仔细阅读 跟羽夏学 Ghidra ——简述 ,方便学习本教程。请认准 博客园 的 寂静的羽夏 ,目前仅在该平台发布。
前言
如果通过Ghidra
图形界面来进行逆向分析工作,那么打交道最多的是各种形形色色的窗口,每个窗口各司其职,各有各的功能,这也是本教程的第一个重头戏。下面开始介绍。
CodeBrowser
CodeBrowser
应该是与我们打交道最多的窗口了,它也包含了各种小窗口:
我们先说一下菜单的主要职能:
- File :提供大多数文件操作的基本功能,包括打开/关闭、导入/导出、保存和打印选项。此外,一些选项是
Ghidra
特有的,例如工具选项,它允许您保存和操作CodeBrowser
工具,并解析C
源代码,它可以通过从C
头文件中提取数据类型信息来帮助反编译过程。 - Edit :提供与编辑相关的操作。其中
Tool Options
命令会打开一个新窗口,允许你控制与CodeBrowser
中可用的许多工具关联的参数和选项。恢复默认设置按钮(恢复为默认设置)始终位于右下角。
- Analysis :允许你重新分析二进制或选择性地执行单个分析任务。
- Navigation :这有助于文件内的导航。该菜单提供了许多应用程序支持的基本导航的功能,并为二进制文件添加了特殊的选项。虽然菜单提供了一种在文件中移动的方法,但在获得导航可用选项的经验后,您可能会使用工具栏选项或快捷方式。
- Search :提供内存、程序文本、字符串、地址表、直接引用、指令模式等搜索功能。
- Select :提供识别文件的一部分以用于特定任务的功能。选择可以基于子例程、函数、控制流,或者只需突出显示文件的所需部分。
- Tools :包括一些有趣的功能,允许您在桌面上放置额外的
SRE
资源。其中一个最有用的是处理器手册选项,它将显示与当前文件关联的处理器手册。如果您试图打开丢失的处理器手册,系统将为你提供包含该手册的方法(这个需要自己下载放置):
- Window :允许您为工作流配置
Ghidra
工作环境。这个菜单十分重要,本篇会重点关注。 - Help :提供丰富、组织良好和非常详细的选项。帮助窗口支持搜索、不同视图、收藏夹、放大/缩小以及打印和页面设置选项。
Ghidra
有一个十分好的地方就是,任何菜单功能和工具栏功能,都是可以修改热键的,没有的可以自行添加:
下面我们开始逐个输入它的子窗体。
Listing
Listing
窗口左侧的边距提供了有关文件的重要信息以及在文件中的位置。在列表窗口的右侧(垂直滚动条的右侧)还有一个额外的标记区域,它还提供了重要的信息和导航功能。滚动条指示您在文件中的位置,可用于导航。在滚动条的右侧是一些信息显示,包括书签,提供了对文件的更多信息。
这个窗口是打交道最多的窗口,这毋庸置疑。这个窗口的标题栏右侧从左到关闭按钮各有各的功能,下面从左到右依次介绍:
- 复制:复制选中内容,如果不可复制,则会显示错误信息。
- 粘贴:从剪贴板拷贝到当前位置,如果不可粘贴,则会显示错误信息。
- 鼠标悬浮工具提示:如果选中,如果鼠标光标悬浮到一个位置,如果有信息,则会显示内容。
- 浏览区域调整:这个应该算是能用到的功能,点中它之后,就可以弹出一个调整条,调整显示数据的宽度:
- 比较差异:用于比较两个文件之间的差异。
- 快照:创建一个断开的
Listing
窗体拷贝,也就是无论在新的窗体进行任何浏览操作,都不会影响到其他窗体。这对于同时看两个函数会十分有用。 - 概览区域显示:它会设置熵和概览是否显示。
下面介绍窗口内的内容:
- ① 边距标记:用于指示当前光标的所在行。
- ② 跳转流指示线:跳转指令如果满足跳转到指示。如果是虚线,则为条件跳转;如果为实线,则为绝对跳转。
- ③ 声明:显示对函数堆栈框架布局的最佳推算。
Ghidra
通过对堆栈指针和函数中使用的任何堆栈帧指针的行为进行详细分析,计算函数堆栈帧(局部变量)的结构。 - ④ 交叉引用:如果某个函数或者数据引用了该地址,就会显示该条目。如果将光标悬浮在上面,就会显示引用的函数汇编内容。
Function Graph
虽然汇编列表信息丰富,但通过查看基于图形的显示,程序流程可能更容易理解。这个功能在IDA
中使用空格键就可以在汇编和图标之间切换,而在Ghidra
,在Window
菜单中的Function Graph
项目中。
你会看到如下类似窗体:
在图形模式下,Ghidra
一次显示一个函数。Ghidra
通过使用传统的图像交互技术(如平移和缩放)来进行图形的导航。大型或复杂的函数可能会导致图形变得非常杂乱,使图形难以导航,右下角的卫星视图就是解决这个问题的。
Ghidra
使用不同颜色的箭头来区分函数块之间的各种类型的流。此外,当将鼠标移到流上以指示方向时,流将变成动画(见下图)。以条件跳转终止的基本块生成两种可能的流:默认情况下,满足跳转条件的箭头是绿色,不满足跳转条件的为红色。仅以一个潜在后续块终止的基本块使用蓝色的线指向要执行的下一个块。可以单击任意箭头以查看从一个块到另一个块的关联转换。由于默认情况下图形和列表工具是同步的,因此在列表视图和图形视图之间切换和导航时,文件位置通常保持一致。
当我们鼠标点击某个代码块,它的背景会显示一个高亮的光圈,与此同时卫星图也是:
如果我们想导航,鼠标拖住移动可以改变位置:
鼠标滚轮可以以鼠标指针为中心缩放:
按住Ctrl
键,可以鼠标框选多个代码块:
每个代码块的位置都是可以拖动的:
我们也可以将代码块组合/解散:
当然,这些都是一个个功能小小的缩影,具体细节就不扒了,比如右键菜单的项目,下面我们先介绍几个特殊的,先从代码块窗口开始:
标题栏右上角的按钮从左到右,依次介绍:
- 背景色设置:该按钮可以设置该代码块的背景色。
- 交叉引用:点击该按钮就会显示该代码块的交叉引用。
- 全屏:将代码块部分全屏显示。全屏之后该按钮图标改变,再次点击恢复。
- 组合:将代码块进行组合。
- 恢复组合:将原来的代码块重新组合。
下面介绍Function Graph
右上角的几个按钮,去掉开头的复制粘贴俩按钮,去除最后一个关闭按钮,开始从左往右依次介绍:
- 跳转到函数头:该按钮可以跳转到所在函数的首地址。
- 刷新:重新加载代码块图形。
- 重新布局:该按钮可以更改代码块各种布局,自己可以自行挑选。
- 代码块区域修改:和
Listing
的浏览区域调整的功能是一样的。 - 代码块焦点流线:设置当某个代码块获得焦点时,代码流指示线的样式。
- 快照:创建一个断开的
Function Graph
窗体拷贝,也就是无论在新的窗体进行任何浏览操作,都不会影响到其他窗体。这对于同时看两个函数会十分有用。
Program Trees
此窗口显示了组织为文件夹和片段的程序,并为您提供了在自动分析期间优化组织的能力。片段是地址连续范围的Ghidra
术语。
它是一个连接的窗口,因此单击窗口中的片段可以将您导航到列表窗口中的该位置。
Symbol Tree
将文件导入到Ghidra
项目中时,将选择Ghidra
加载程序模块加载文件内容。当以二进制形式存在时,加载器能够提取符号表信息。Symbol Tree
窗口包括与程序相关的导入、导出、函数、标签、类和名称空间。
这个窗口是十分重要的,提供了类似于命令行工具的功能,如objdump
、readelf
和dumpbin
。下面详细介绍每个文件夹的职责。
Import
该文件夹列出了被分析的二进制文件导入的所有函数。只有当二进制文件使用共享库时,它才有用。静态链接的二进制文件没有外部依赖,因此没有导入。它列出导入的库,其中包含从该库导入的每个项(函数或数据)的条目。单击符号树视图中的任何符号将所有连接的显示跳转到选定符号。
Exports
该文件夹列出了文件中的入口点。这些包括程序的执行入口点,如在其头部分中指定的,以及文件导出供其他文件使用的任何函数和变量。导出的函数通常在共享库中找到。导出的条目按名称列出,当选择导出时,相应的虚拟地址将在列表窗口中突出显示。对于可执行文件,该文件夹始终至少包含一个条目——程序入口。Ghidra
根据二进制文件的类型将该符号命名为entry
或者_start
。
Functions
该文件夹包含Ghidra
在二进制文件中识别的每个函数的列表。如下图所示,将鼠标悬停在符号树窗口中的函数名上会生成一个弹出窗口,其中包含函数的详细信息。作为加载过程的一部分,加载程序使用各种算法,包括文件结构分析和字节序列匹配,以推断用于创建文件的编译器。在分析阶段,函数ID
分析器利用编译器标识信息来执行基于散列的函数体匹配,以便标识可能已链接到二进制的库函数体的存在。当进行散列匹配时,Ghidra
从散列数据库(包含在Ghidra.fidbf
文件中)检索匹配的函数名称,并将该名称添加为函数符号。哈希匹配在解构二进制文件上特别有用,因为它提供了一种独立于符号表存在的符号恢复方法。
Labels
该文件夹是与Functions
文件夹等效的数据。二进制符号表中包含的任何数据符号都将列在该文件夹中。此外,无论何时向数据地址添加新标签名称,该标签都将添加到Labels
文件夹中。
Classes
文件夹包含Ghidra
在分析阶段识别的每个类的条目。在每一项下,Ghidra
列出了识别的数据和方法,这些数据和方法可以帮助理解类的行为。
Namespaces
在该文件夹中,Ghidra
可以创建新的名称空间以提供组织方式,并确保分配的名称在二进制文件中不冲突。例如,可以为每个已标识的外部库或使用跳转表的每个switch
语句创建命名空间。
Data Type Manager
该窗口允许您使用数据类型存档系统定位、组织数据类型并将其应用于文件。档案代表了Ghidra
对预定义数据类型的累积知识,这些数据类型是从最流行的编译器包含的头文件中收集的。通过处理头文件,Ghidra
可以理解公共库函数所期望的数据类型,并可以相应地注释反汇编和反编译器列表。类似地,从这些头文件中,Ghidra
了解复杂数据结构的大小和布局。所有这些信息都收集到存档文件中,并在分析二进制文件时应用。
即使没有加载程序,内置类型树的根也会显示在数据类型管理器窗口(CodeBrowser
窗口的左下角)中,其中包含无法在数据类型存档中更改、重命名或移动的基本类型,如int
。除了内置类型之外,Ghidra
还支持创建用户定义的数据类型,包括结构、联合、枚举和类型定义。它还支持数组和指针作为派生数据类型。
更多详情使用介绍,将会在之后使用中涉及。
Console
CodeBrowser
窗口底部的Console
窗口用作Ghidra
的插件和脚本输出区域,包括自己开发的插件和脚本,并且是在处理文件时查找Ghidra
正在执行的任务信息的地方。
Decompiler
Decompiler
反编译器窗口允许通过连接的窗口同时查看和操作二进制文件的汇编和C
表示。Ghidra
反编译器生成的C
表示并不总是完美的(所以不要过度依赖),但它在帮助您理解二进制文件方面非常有用。反编译器提供的基本功能包括恢复表达式、变量、函数参数和结构字段。反编译器通常还能够恢复函数的块结构,这种块结构在汇编语言中往往变得模糊。
反编译器窗口显示Listing
窗口中所选函数的C
表示。根据您使用汇编语言的经验,反编译代码可能比Listing
窗口中的代码更容易理解。即使是初学者也应该能够识别反编译函数中的无限循环。
如果要比较多个函数的反编译版本,或者在列表窗口中移动到其他位置时继续查看特定函数,可以使用快照按钮打开其他(断开连接的)反编译器窗口。导出按钮允许您将反编译函数保存到C
文件中。
反编译是一个非常复杂的过程,反编译理论仍然是一个活跃的研究领域。与反汇编不同,反汇编的准确性可以根据制造商的参考手册进行验证。事实上,虽然Ghidra
的反编译器总是生成C
源代码,但反编译器正在分析的二进制文件可能最初是用C
以外的语言编写的,反编译器的许多面向C
的假设可能根本不成立。
与大多数复杂的插件一样,反编译器也有一些特性,其输出的质量在很大程度上取决于输入的质量。反编译器窗口中的许多问题和不规则性可以追溯到底层反汇编的问题,因此如果反编译代码没有意义,您可能需要花费时间改进反汇编的质量。在大多数情况下,这涉及使用更精确的数据类型信息注释反汇编,这将在之后的博文中讨论。
这个窗口十分重要,之后会在实验中继续介绍如何配合使用。
Bytes
该窗口提供了文件字节级内容的原始视图。默认情况下,字节窗口在CodeBrowser
的右上角打开,并提供程序内容的标准十六进制转储显示,每行16
字节。该窗口兼作十六进制编辑器,可以使用窗口工具栏中的设置工具配置为显示各种格式(扳手图标)。在许多情况下,将ASCII
显示添加到字节窗口可能会有帮助。
Defined Data
该数据窗口显示当前程序、视图或选择中定义的数据的字符串表示,以及相关的地址、类型和大小。与大多数列窗口一样,您可以通过单击列标题按升序或降序对任何列进行排序。双击窗口中的任何行会导致列表窗口跳转到选定项的地址。
当与交叉引用一起使用时,定义的数据窗口提供了一种方法,可以快速发现一个感兴趣的项目,并只需点击几次即可跟踪到程序中引用该项目的任何位置。
当然,该列表可以设置过滤器,只需点击该窗口标题栏上的齿轮按钮:
每次设置数据类型过滤器时,Ghidra
将根据新设置重新生成定义的数据窗口内容。
Defined Strings
该窗口显示已在二进制文件中定义的字符串,可以通过右键单击列标题行来添加列。可能最有用列之一是Has Encoding Error
标志,它可能表示字符集问题或字符串识别错误。除此窗口外,Ghidra
中还提供了大量字符串搜索功能。
Symbol Table
该窗口提供二进制文件中所有全局名称的摘要列表。默认情况下显示八列,如下图所示。该窗口具有高度可配置性,可以在显示中添加和删除列,以及在任何列上按升序或降序排序。前两个默认列是名称和位置。名称只不过是在某个位置定义的符号的符号描述。
符号表连接到Listing
窗口,但提供控制其与列表窗口交互的能力。双击任何符号表位置条目将立即跳转到列表视图以显示所选条目。这为快速导航到程序列表中的已知位置提供了一个有用的工具。
同样,它也可以设置过滤器(齿轮图标),用于过滤自己需要的信息。
Symbol References
和Symbol Table
差不多。此外,该窗口的内容由右上角的三个图标(S
、I
和D
)控制。这些选项相互排斥,意味着一次只能选择一个选项:
- S :选择此图标时,窗口将显示在符号表中选择的符号的所有引用。
- I :选择此图标后,窗口将显示您在符号表中选择的函数的所有指令引用。
- D :选择此图标后,窗口将显示您在符号表中选择的函数的所有数据引用。如果未选择函数入口点或函数未引用任何数据符号,则此列表将为空。
Memory Map
该窗口显示程序中存在的内存块的摘要列表。请注意,当讨论二进制文件的结构时,Ghidra
术语内存块通常被称为节。窗口中显示的信息包括内存块(段)名称、开始和结束地址、长度、权限标志、块类型、初始化标志,以及源文件名和用户注释的空间。起始地址和结束地址表示程序段在运行时映射到的虚拟地址范围。
双击窗口中的任何开始或结束地址,将列表窗口(以及所有其他连接的窗口)跳转到指定地址。窗口工具栏提供了添加/删除块、移动块、拆分/合并块、编辑地址和设置基址的选项。当使用非标准格式反向工程文件时,这些功能特别有用,因为Ghidra
加载程序可能没有检测到二进制文件的段结构。
Function Call Graph
在任何程序中,一个函数既可以调用,也可以被其他函数调用。函数调用图窗口显示给定函数的近邻。出于我们的目的,如果Y
直接调用X
或X
直接调用Y
,我们将Y
称为X
的近邻。当您打开函数调用图窗口时,Ghidra
确定光标所在函数的邻居,并生成相关显示。此显示在程序文件中使用的上下文中显示函数,但它只是全局的一部分。
总结
在本篇当中,我们介绍了基本常用的窗口,并做了详细的了解。当然学会这些不是特别够,这些并不完整,算是个抛砖引玉,剩余的功能还请自行探索。
下一篇,我们就开始接触逆向的部分,正式走入Ghidra
的世界。
下一篇
跟羽夏学 Ghidra ——数据