二进制检测和软件断点有什么区别?

逆向工程 ollydbg 断点 小工具
2021-06-11 00:41:18

不要被问题的标题所迷惑。这是一个解释。

让我们以英特尔 Pin 为例。他们声称

将 Pin 视为“即时”(JIT) 编译器的最佳方式。然而,这个编译器的输入不是字节码,而是一个普通的可执行文件。Pin 拦截可执行文件的第一条指令的执行,并为从该指令开始的直线代码序列生成(“编译”)新代码。然后它将控制转移到生成的序列。

但是,软件断点(根据 Eldad Eilam 的 Reversing: Secrets of Reverse Engineering)是:

软件断点是调试器在运行时添加到程序代码中的指令。这些指令使处理器暂停程序执行,并在执行期间到达时将控制权转移到调试器。

基本上,Intel PIN 和例如 OllyDBG 都做了大致相似的事情:通过插入自定义指令来改变执行流程。我知道,使用 PIN,您可以做更多的事情,然后在特定条件下暂停,但这不是重点。

所以,我的问题是 JIT 编译(如在 Intel PIN 中)和软件断点(如在 OllyDBG 或任何其他调试器中)之间的主要区别是什么?

1个回答

英特尔 Pintool不是JIT 编译器。您引用的解释只是使用了 JIT 编译的类比,因为存在逻辑相似性。恕我直言,这不是一个经过深思熟虑的类比,应该非常轻视。

我将详细解释这三个概念:

即时编译

事实上,JIT 编译的概念与这个问题并不真正相关,但我会继续讨论它:

JIT 编译主要用作解释语言的性能改进,但一些更高级的语言使用它(例如 .Net 和 java)。

当执行未编译的代码时,基本上有一个循环处理序列中的每个字节码(类似于处理器如何一个接一个地执行指令)。该循环基本上将字节码指令实现为 CPU 指令,修改状态上下文(类似于 CPU 寄存器,只是通常更大和更高级别)。

与 CPU 指令相比,这个过程很慢,而且通常没有充分的理由——这就是解释器的设计方式。JIT 来了。这基本上是说,该循环可以在第一次运行时生成 CPU 指令,然后执行这些指令,而不是实现处理每个字节码指令的循环。为简化起见,JIT 是在执行代码之前将语言的字节码转换为 CPU 指令集的过程,让 CPU 指令运行而不是解释器循环。通常编译后的代码被缓存到它不会被再次编译。

软件断点

软件断点是一条特定指令(在 x86: 中int 3,同时编码为0xcc0xcd0x03),它告诉 CPU 用户(在 CPU 术语中,这通常意味着开发人员)想知道它何时执行并暂停执行以进行进一步检查。当它遇到一个中断处理机制时,它会触发并且进程的执行被处理该中断的调试器挂起。然后调试器通常让开发人员检查代码,修改它,然后恢复执行。调试器通过用软件断点中断替换单个指令(或其中的一部分)来设置软件断点,并在稍后恢复执行时将其设置回原始指令。

二进制仪器(Pintool)

使用 Binary Instrumentation,Pintool 等工具处理二进制可执行文件中的代码(类似于 JIT 编译器处理字节码或脚本的方式),并通过插入多种类型的附加代码来创建“修复”或修改的可执行代码。当断点不够用时,或者当您想要分析大量可执行文件时,通常会执行此操作。示例包括修改所有jump指令(例如,记录所有跳转的源和目标)。

正如您所说,与二进制检测引擎提供的能力相比,软件断点非常有限,因此我专注于技术实现而不是两者的优势。