[Hack翻译]逆向工程简介

725 阅读10分钟

本文由 简悦SimpRead 转码,原文地址 geekpradd.github.io

逆向工程是网络安全和道德黑客中最有趣的领域之一。通过......

逆向工程是网络安全和道德黑客中最有趣的领域之一。通过这篇文章,我们将试图通过一步一步的方式来简化这一领域的想法。我们现在将重点关注简单的ELF Linux可执行文件,以后我们还将研究逆向工程的windows exe可执行文件和JVM的字节码等。所以,让我们开始吧!

什么是逆向工程?

简单地说,逆向工程是指解构任何工程对象以弄清其内部机制的过程。一个例子是破解游戏,破解者必须在他们的电脑上对游戏代码进行逆向工程,以便能够免费分发。

大多数非开放源码的软件都不提供源代码,而我们只有编译后的可执行代码。我们必须在某种程度上从可执行代码中找出soruce的内容(或其子集)。这在一般情况下是不容易做到的,因为机器/汇编代码是非常复杂的,而且还添加了很多编译器的优化功能。

一般来说,提供给我们的可执行文件可能不是二进制或汇编指令,也可能是任何虚拟机(比如说Java虚拟机)执行的平台独立字节码的形式。然而,我们在本教程中只看从C/C++代码生成的Linux可执行文件,因为这提供了该领域的一个相当好的概述。然而,要做到这一点,我们必须了解基本的汇编。

x86汇编简介

x86汇编是由非ARM(Intel/AMD)处理器使用的汇编指令代码,大多数CTF问题将使用这种指令代码。产生的指令可能因操作系统而异,我们将考虑linux的可执行文件(ELF格式)。在继续之前,请注意有各种不同的汇编语法,我们将在本教程中使用英特尔汇编语法,尽管替代的AT&T语法也很常见。

与高级语言相比,汇编语言的结构非常少,而必须依靠一些原始的操作。大多数汇编操作都发生在寄存器上,它是CPU上的特殊内存位置,比直接访问RAM要快得多,很多特殊的值都存储在这里。我们先来看看这些寄存器和它们的命名规则。

寄存器

寄存器可以被认为是CPU中的一个特殊内存位置。有6个通用寄存器和2个特殊寄存器可用。我们可以在这些寄存器上进行所有可能的汇编操作,如加值、减值等。

这8个寄存器被命名为 "EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP"。

然而,如果你翻阅任何汇编代码,你会看到寄存器名称的各种变化。你可以用不同的方式来调用不同的寄存器。以上的命名方式可以让你访问与每个寄存器相关的32位。现在在64位系统中,每个寄存器被分配了64位,可以通过使用RAX, RBX, RCX, RDX, RSI, RDI, RSP, RBP的名称来调用。

同样,如果你只想得到16位,你可以用 "AX, BX, CX... "来称呼它们,以此类推。要获得8位,你将使用`AL, BL, CL...'等等。下面的图可以更好地解释这个问题。

关于寄存器的更多细节,请看此链接通用寄存器可以用于计算,事实上,只有通过这些寄存器,你才能进行加减等操作。因此,如果你想把存储在两个不同内存位置的两个数字相加,你必须把存储在那里的数值加载到寄存器中,然后进行操作,再把这些数值写到内存位置。我们不会去研究这些操作的具体细节,而是在下面快速总结一下。

还有一件重要的事情要注意,就是ESP和EBP是用来存储堆栈的内存位置的。ESP指向堆栈的顶部,EBP(通常)指的是底部。因此,在堆栈上声明变量相当于从ESPEBP中加减值。请注意,你一般不需要知道具体的细节,但有一个模糊的概念就可以了。

还有几个FLAGS是由汇编使用的。把标志看成是一个特定的布尔变量,由汇编指令来设置。一些标志是零标志、符号标志等。我们在逆向工程中主要需要零标志,因为这个标志被多次用来确定控制流。

基本汇编操作

mov操作

mov操作是最简单的操作之一,它所做的就是移动数值(或赋值)。mov的语法如下。

mov destination, source

假设我想在EAX中设置数值12,那么我将运行操作。

mov eax, 12

还有一件事需要了解,那就是取消引用。假设寄存器ECX中的值是0x6665f,这是一个内存位置。因此,ECX'类似于一个指针。如果我想把存储在0x6665f的值加载到EAX`,我将使用以下命令。

mov eax, [ecx]

大括号[]的功能类似于C/C++中的*,它取消对内存位置的定义并输出该位置的值。

add操作

这是很简单的。考虑一下下面的汇编代码。

添加eax, ebx

这等同于:

eax = eax + ebx

sub操作

这也是类似的。考虑一下下面的汇编代码。

sub eax, ebx

这就相当于

eax = eax - ebx

cmp操作

这是一个非常有用的操作,用于比较数值。这个操作的结果可以和jump操作结合起来,支配控制流。考虑一下下面的代码。

cmp ecx, 15h
jz 0x7eb

让我们看看这是什么。cmp命令比较给定的值,在本例中是存储在ecx中的值和以十六进制给出的值21cmp本质上是减去这两个值,并设置一些我们之前谈到的FLAGS。在这里,如果两个值相等,那么减去的值将是 "0",所以 "ZERO "标志将被设置。

下一条指令jz代表 "跳过零"。因此,如果零标志被设置,程序将跳转到由0x7eb地址描述的代码位置(通过使用调试器可以很容易地看到)。因此,这类似于一个 "if "语句。

事实证明,我们可以巧妙地使用这种命令来构建forwhile和其他循环。我们将在下一篇文章中进行介绍。如果我们使用jz,而不是jle,那么如果满足ecx <= 15h,就会发生跳跃。事实上,有很多这样的条件式可以用来模拟控制流。

pushpop

这些对我们来说其实并不重要。语法大多是这样的。

push/pop register

这个操作负责向堆栈推送/平移数值。我们不会经常使用它。

test操作

这与cmp类似,只是它计算二进制的AND而不是减法。因此,如果给定的两个输入的二进制AND'是0',那么零标志被设置。

因此下面的`C'条件可以很容易地翻译成汇编。

if (eax == 0){
	// do stuff
}

相应的程序集将是。

test eax, eax
jz location_to_do_stuff

lea操作。

这是我们将在这里看到的最后一个操作。这与mov类似,但不是复制值,而是复制地址。

lea eax, [ecx]

上面的代码将把存储在ecx中的值(也就是地址)复制到eax中。请注意,mov会复制存储在ecx中的地址的值。因此lea加载的是地址而不是值。它代表了加载有效地址。

逆向工程的静态反汇编介绍。

到目前为止,已经看到了很多理论。现在让我们来看看如何将其付诸实践!

我们需要一个反汇编程序来获取和研究汇编代码。现在让我们使用一个静态反汇编程序。静态反汇编程序不允许我们运行该文件,但它提供了一个整齐的汇编代码反汇编分析。IDA是这方面的行业标准,从这里下载并运行IDA的免费版本

一旦你安装了IDA Free,你就可以开始工作并分析代码了。让我们用IDA解决这个CTFLearn挑战

下载文件并将其加载到IDA中。继续点击下一步,不要改变任何选项(例如,让IDA决定它是一个ELF!)。你应该到达以下屏幕:!

如果你运行该文件,你会发现你需要输入一个针脚才能工作。如果你输入任何随机的输入,它将输出 "PIN Salah!" 很明显,我们想找到PIN码,这就有了另一种可能性。

上面的分支显示了另一种可能性,你想得到 "PIN BENAR!"。观察一下,通过test,我们可以得到 "PIN Salah!"的唯一方法是EAX的值为0。

所以当我们输入错误的PIN码时,EAX被设置为0。汇编中的call意味着我们正在调用一个函数。双击那里,看看cek函数的代码是什么。

需要注意的一件事是,在逆向工程中,不要试图分析所有的东西,因为很多东西都是通过编译器生成的,可能很难理解。相反,要尝试深入了解程序的运行结构。

现在我们看到,在 "cek "的上层块发生的一切之后,有两条路线。一条路线是将eax设置为1,否则为0。很明显,我们想看的是当值被设置为1时,因为只有这时针才是正确的。

分支是由jnz决定的。这意味着 "如果不是零就跳过"。由于我们使用的是cmp,这意味着只有当零标志被设置时,我们才不会跳转(因此得到EAX为1)。

什么时候设置零标志?只有当[rbp+var_4] == eax时才会发生。然而上面两个movs显示现在[rbp+var_4]中的值与edi中的值相同,而eax中的值是在一个叫cs:valid的东西中。

这个cs:valid是什么?原来它只是IDA给存储在二进制中的一些值起的一个名字。如果我们双击它,我们会得到以下的值数据。

现在我们还没有看到我们的输入被储存在哪里。结果发现它被存储在EDI中。这在一般情况下是会改变的,但使用一个叫做动态反汇编程序(gdb)的东西,我们可以弄清楚(我们将在下一个教程中看到)。即使不知道这一点,我们也可以猜测,输入被存储在EDI中,正如我们将看到的,这个猜测被证明是正确的。

因此,如果我们的输入等于51615h(用十六进制表示),我们将在EAX中得到1,因此这一定是PIN码 将其转换为二进制,我们得到333333这个值。

让我们输入这个值,看看这个值是否正确。

的确,我们得到了 "PIN benar"! 这就是PIN,我们用一些巧妙的拆解和调查技巧找到了PIN!

这就总结了这个问题。这实际上是比较简单的逆向工程问题之一,因为我们只用一个静态反汇编程序就可以解决它。以后我们会看到一些更复杂的问题,必须使用其他工具如gdbradare2等来解决。

本教程就到此为止。请随意使用IDA尝试更多的问题,同时也要记得多用谷歌。理解汇编并不容易,一个人必须经常用google来弄清楚每个操作的作用。就这样,祝你玩得开心,继续黑下去吧


www.deepl.com 翻译