玩转Ghidra主要数据显示窗口,第四篇

2020-12-02 9,065

在上一篇文章玩转Ghidra主要数据显示窗口,第三篇中,我们为读者介绍了Function Graph窗口,卫星导航功能,窗口联动,显示方式的自定义,以及Program Trees窗口。在本文中,我们将继续为读者介绍其他常用的窗口。

Symbol Tree窗口

当我们将一个文件导入到Ghidra项目中时,Ghidra会选择一个加载器模块来加载文件内容。当文件内容为二进制代码时,加载器将提取符号表信息,并将其显示在Symbol Tree窗口中。实际上,Symbol Tree窗口会显示与程序相关的导入、导出、函数、标签、类和命名空间等符号。

 

image.png 

 

1 Symbol Tree窗口

 

此外,对于Symbol Tree窗口中的6个文件夹来说,都可以通过该窗口底部的过滤器加以控制。随着我们对目标文件的了解越来越深,这个功能将变得更加有用,从而形成一个良性循环。此外,Symbol Tree窗口还提供了类似于命令行工具的功能,如objdump (-T) 


Imports文件夹

Symbol Tree窗口中的Imports文件夹列出了被分析的二进制文件导入的所有函数。只有当二进制文件使用共享库时,才需要关注该文件夹,因为静态链接的二进制文件没有外部依赖项,因此,也就不会导入外部函数。实际上,Imports文件夹不仅会显示导入的库,同时,还会进一步显示从该库导入的所有函数或数据。此外,只要单击Symbol Tree视图中的某个符号,所有联动的窗口都将跳转到这个选定的符号对应的内容处。在我们的Windows二进制文件示例中,单击Imports文件夹中的GetCurrentThreadId函数,反汇编窗口将自动跳转到该函数对应的导入地址表条目地址处,在本例中,该条目位于140002138处,如图2所示。

 

image.png 

 

2 导入地址表条目及其在Listing窗口中对应的地址

 

关于Imports文件夹,需要说明的一点是,它只显示在二进制文件导入表中已命名的符号。对于二进制文件使用dlopen/dlsym或LoadLibrary/GetProcAddress等机制自行加载的符号,则不会显示在Symbol Tree窗口中。

 

Exports文件夹

Exports文件夹用于显示文件的入口点。其中,包括程序的执行入口点,以及该文件导出的函数和变量。这些导出的函数通常位于共享库中,如Windows DLL文件。同时,导出的内容将按名称显示;对于选中的导出函数,相应的虚拟地址将在Listing窗口中高亮显示。对于可执行文件,Exports文件夹中将至少包含一项内容:程序的执行入口点。Ghidra将根据二进制文件的类型,将这个符号命名为entry_start。


Functions文件夹

Functions文件夹中显示了Ghidra在二进制中找到的所有函数。当我们将鼠标悬停在Symbol Tree窗口中的某个函数名称上的时候,将会显示关于该函数的详细信息,具体如图3所示。加载器在加载文件时,通常会利用各种算法、文件结构分析和字节序列匹配来推断用于创建该文件的编译器。在分析阶段,Function ID分析器将利用编译器识别信息执行基于哈希的函数体匹配,以识别可能已经链接到二进制文件的库函数体。当进行哈希匹配时,Ghidra会从哈希数据库(包含在Ghidra .fidbf文件中)中检索出匹配的函数名称,并将该名称添加为函数符号。哈希匹配在stripped型二进制文件上特别有用,因为它提供了一种独立于符号表的符号恢复方法。

 

image.png 

 

3 Functions文件夹

 

Labels文件夹

Labels文件夹相当于Functions文件夹的数据。二进制的符号表中包含的所有数据符号,都会在Labels文件夹中列出。此外,每当我们向数据地址添加一个新的标签名称时,该标签也将被添加到Labels文件夹中。


Classes文件夹

Classes文件夹存放Ghidra在分析阶段识别的每个类的数据和方法。对于每个类,Ghidra将显示已识别出的数据和方法,这些数据和方法可帮助您理解该类的行为。


Namespaces文件夹

Namespaces文件夹中,Ghidra可以创建新的命名空间,以用于组织各种名称,从而确保分配的名称在二进制代码中不会发生冲突。例如,我们可以为每个已识别出的外部库或每个使用跳转表的switch语句创建一个命名空间(允许在其他switch语句中重复使用跳转表标签而不发生冲突)。 


Data Type Manager窗口

Data Type Manager窗口用于通过数据类型存档系统来定位、组织和应用数据类型,并将其应用到文件中。存档代表了Ghidra从大多数流行的编译器所包含的头文件中积累的预定义数据类型的知识。通过对头文件进行处理,Ghidra掌握了常见库函数所期望的数据类型,所以,它能对反汇编和反编译器中的代码进行注释。同样,从这些头文件中,Ghidra也能理解复杂数据结构的大小和布局。实际上,Ghidra将所有这些信息都汇集到了存档文件中,以便在分析二进制文件时随时加以应用。

 

实际上,我们可以从BuiltInTypes树的根部看到像int这样的基本数据类型,需要注意的是,这些类型在数据类型存档文件中是不运行修改、重命名或移动的;并且,即使没有加载程序的情况下,它们也会显示在Data Type Manager窗口中(它位于CodeBrowser窗口的左下角)。除了内置类型外,Ghidra还支持用户自定义的数据类型,包括结构体、联合体、枚举类型等。它还支持作为派生数据类型的数组和指针类型。

 

实际上,我们打开的每个文件都会在Data Type Manager窗口中有一个对应的条目。而且,文件夹会使用当前文件的名称进行命名,因为文件夹内的条目是针对当前文件的。

 

此外,Data Type Manager窗口还会显示每个打开的数据类型存档的节点。虽然存档通常会自动打开,例如当程序引用存档时,但是,它也可以由用户手动打开。 

Console窗口

CodeBrowser窗口底部的Console窗口是Ghidra的插件和脚本(当然,也包括用户自己开发的插件和脚本)的输出区域,同时,该窗口也是在处理文件过程中查看Ghidra正在执行的任务的相关信息的去处。

Decompiler窗口

通过Decompiler窗口以及联动的其他窗口,我们可以同时查看和操作二进制的汇编代码和C代码。当然,Ghidra反编译器生成的C代码并不完美,但是,对于理解二进制代码还是非常有用的。反编译器提供的基本功能包括恢复表达式、变量、函数参数和结构字段。反编译器还经常能够恢复函数的块结构,这在汇编语言中往往会是看不出来的,因为汇编语言不是块结构的,而是大量使用goto语句来效仿块结构。

 

我们在Decompiler窗口中看到的代码,实际上就是在Listing窗口中选择的汇编函数所对应的C代码,具体如图4所示。一般来说,反编译后的代码要比Listing窗口中的代码更加容易理解。

 

image.png 

4  Listing和Decompiler窗口

 

Decompiler窗口的图标如图5所示。如果我们想比较多个函数的反编译版本,或者在Listing窗口中移动到其他地方时继续查看某个函数,我们可以使用Snapshot(快照)图标打开额外的反编译器窗口。此外,我们也可以使用Export(导出)图标将反编译后的函数保存到C文件中。

 

Decompiler窗口中,通过右键单击可以使用上下文菜单,以便执行与高亮显示的内容相关的操作。

 

image.png 

 

5 Decompiler窗口的函数参数选项

 

事实上,虽然Ghidra的反编译器的输出结果总是C代码,但我们分析的二进制代码可能根本就不是用C语言编写的,因此,反编译器的许多面向C语言的假设可能根本就不成立。

 

和大多数复杂的插件一样,反编译器输出的质量在很大程度上取决于输入的质量。Decompiler窗口中的许多问题和不规则性都可以追溯到底层反汇编的问题,所以,如果反编译的代码一塌糊涂,我们首先要做的事情就是改进反汇编代码的质量。 

小结

在本文中,我们为读者介绍了Symbol Tree窗口Data Type Manager窗口Console窗口,以及Decompiler窗口的使用方法。在下一篇文章中,我们将继续为读者介绍其他常用的窗口方面的知识。

 


本文作者:mssp299

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/148316.html

Tags:
评论  (0)
快来写下你的想法吧!

mssp299

文章数:51 积分: 662

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号