写在前面
此系列是本人一个字一个字码出来的,包括示例和实验截图。本人非计算机专业,可能对本教程涉及的事物没有了解的足够深入,如有错误,欢迎批评指正。 如有好的建议,欢迎反馈。码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作。如想转载,请把我的转载信息附在文章后面,并声明我的个人信息和本人博客地址即可,但必须事先通知我。
你如果是从中间插过来看的,请仔细阅读 跟羽夏学 Ghidra ——简述 ,方便学习本教程。请认准 博客园 的 寂静的羽夏 ,目前仅在该平台发布。
前言
虽然标题起的是“引用”,但不会仅仅讲这个。我们将会涉及函数、交叉引用相关的知识。话不多说,下面开始。
交叉引用
先讲最简单的:交叉引用。我们经常在Ghidra
看到有这样的注释:
************************************************
* FUNCTION *
************************************************
undefined variable()
undefined AL:1 <RETURN>
tstruct Stack[-0x18]:16 lstruct XREF[1,3]:00401185(W),
00401189(W),
0040118f(W),
00401196(W)
variable XREF[4]: Entry Point(*),
main:0040137c(c),
00402238, 00402318(*)
00401162 55 PUSH RBP
其中XREF
就是所谓的交叉引用。如果你在某个函数中调用了其他函数,或者引用了其他数据,这都属于交叉引用的范围。好,寂静的羽夏讲完了这,下面轮到函数。
函数
函数,是一个十分简单又十分复杂又十分重要的东西。从汇编层面,函数就是一个重复使用的一个汇编代码片段,可以传参,完成功能,也可以返回一个值作为结果。
在逆向过程中,我们有时候遇到过这样的问题,比如一串代码被识别为数据(ShellCode 会经常遇到),我们转化为代码之后,我们还需要将其转为函数,方便分析:
点击之后,我们就可以创建一个函数。
在分析一个函数的功能之后,我们会习惯加个注释,以后的时候方便继续或者回顾,Ghidra
有添加注释的功能,热键是;
,一个英文状态的分号。注释有五种,下面介绍一下:
-
EOL Comments
:这个也许是最常用的注释类型是行结束EOL
注释,它位于列表窗口中现有行的末尾。若要添加注释,请使用分号唤出对话框,并选择EOL Comments
选项卡。默认情况下,EOL
注释显示为蓝色文本,如果在“注释”文本框中输入多行,则将跨越多行。每一行都将缩进,以便在反汇编的右侧对齐,现有内容将向下移动,以便为新注释留出空间。您可以通过重新打开对话框随时编辑注释。删除注释的最快方法是单击列表窗口中的注释,然后按Delete
键。Ghidra
本身在自动分析期间添加了许多EOL
注释。只有在拥有与特定数据类型相关联的信息时才能这样做。这些信息通常包含在类型库中,这些类型库显示在数据类型管理器窗口中。
-
Pre/Post Comments
:预注释Pre Comments
和后注释Post Comments
是在给定反汇编行之前或之后出现的完整行注释。将鼠标悬停在截断的注释上,将显示完整的注释。默认情况下,预注释显示为紫色,后注释显示为蓝色,以便轻松地将它们与列表中的正确地址关联。
-
Plate Comments
:它允许您对注释进行分组,以便在列表窗口中的任何位置显示。该注释居中并放置在以星号为界的矩形内。我们检查过的许多清单都包括一个简单的板注释Plate Comments
,在边界框中包含单词函数。当在所选函数中的第一个地址打开注释对话框时,你可以选择用您自己的、信息更丰富的注释替换此通用板注释。除了替换默认板注释之外,Ghidra
还将注释添加为反编译器窗口顶部。如果创建Plate Comments
时光标位于反编译器窗口的顶部,结果将是相同的。
-
Repeatable Comments
:可重复注释输入一次,但在整个反汇编过程中可能会自动出现在许多位置。可重复注释的行为与交叉引用的概念有关。基本上,在交叉引用的目标输入的可重复评论在交叉引用源处得到回应。因此,单个可重复注释可能会在反汇编中的多个位置得到响应(因为交叉引用可以是多对一)。在反汇编列表中,可重复注释的默认颜色为橙色,回应注释为灰色,使其易于与其他类型的注释区分开来。
当EOL
注释和可重复注释在同一地址时,只有EOL
注释在列表中可见。如果删除EOL
注释,可重复注释将在列表中显示。
其实,在Ghidra
还有一种注释:附注Annotations
。它可以在其设置注释对话框中通过指向程序、URL
、地址和符号的链接注释做注释。符号名称更改时,注释中的符号信息将自动更新。当使用注释来启动指定的可执行文件时,你可以提供可选参数以获得更多控制。
其实,本练习还有函数相关的,体现如何传递参数的,这就当课外练习了,这个不是我们本教程的重点,这个是前置知识。
实验
有关本篇博文寂静的羽夏就介绍这些,下面开始动手,破解crakeMe
,也就是第四个练习。这次先从源码的角度,来分析这个破解这个练习。下一篇博客园博文,我们将从逆向者的角度,来分析这个程序。
通过比对源码,我们看到如下伪代码:
if (local_14 != 4) break;
iVar1 = crackMe();
if (iVar1 == 0) {
puts("抱歉,没成功哦,再试一次!");
}
else {
puts(">> 祝贺破解成功!");
}
也就是说,第四个练习是调用crackMe
,判断是否非零决定是否成功。我们跟进去:
bool crackMe(void)
{
int iVar1;
iVar1 = getKey();
return iVar1 == 0x123456;
}
这个函数很简单,调用getKey
函数,看看是否返回值是0x123456
,如果是返回真,反之为假,这个是判断是否破解成功的依据。接下来我们看看getKey
干了啥:
int getKey(void)
{
int local_c;
puts("请输入密钥:");
__isoc99_scanf("%d",&local_c);
return local_c;
}
可以看到,该函数只是读取一下输入内容,作为整数返回到调用者。
至此,简单的博文就到此结束。
下一篇
跟羽夏学 Ghidra ——导航