如何仅通过检查二进制图像来识别处理器指令集?

逆向工程 拆卸 机器码
2021-06-27 21:52:03

约束:

我正在对未知出处的二进制固件映像进行逆向工程,该映像在我无法物理访问的设备上运行也就是说,我无法拆开设备,甚至没有其功能的框图,也无法通过目视检查或询问对象的创建者来识别微处理器。从字面上看,唯一可用的是二进制图像。

问题:

我的问题是:鉴于这些限制,可以采用哪些工具或理论方法通过检查二进制文件来识别处理器的指令集?

迄今为止的研究:

当然,我曾尝试将反汇编程序用于各种流行的 ISA,例如 ARM、x86 和 MIPS。我还对研究论文进行了文献搜索,但根本没有找到任何东西。

理想情况下,我想要的是一种工具,它可以检查二进制文件,然后报告“75% 的可能性这是瑞萨 M16C 的代码”。

2个回答

本演示文稿提供了一种方法。

标题:自定义虚拟机二进制程序的逆向工程

作者:Alexander Chernov 和 Katerina Troshina

  • 二进制程序的初始标记。数据段和代码段的标识。可能会使用有关程序目的的先验信息或什至一些文档提示。在这一步,代码的入口点(或多个入口点)被识别。
  • 通过识别子程序边界重建子程序结构。识别子程序返回(RET)指令。很自然地期望代码段中的最后一条指令是返回指令。RET 指令通常将子程序分开,因此我们可以预期,在许多(甚至大多数)情况下,CALL 指令应该在 RET 指令之后立即传递控制权。
  • 使用代码执行从某个固定地址开始的假设来识别无条件跳转 (JMP) 指令。
  • 调用指令的识别。调用指令类似于无条件跳转。通过对初始化代码的调查,可以识别出 CALL 指令的几个候选者,并且在对整个代码进行验证之后,一个候选者仍然存在。
  • 通过查看指令的位编码并检查它是否可能是相对于下一个指令字的偏移量来恢复绝对和相对跳转和调用。通过这种方式,可以识别相对跳转、调用和条件跳转的候选对象。
  • 通过观察内存-内存复制操作的加载-存储模式来识别内存加载和存储指令。
  • 对虚拟机寄存器结构和寄存器宽度的观察。这个 VM 可能有多少个寄存器以及它们有多宽。
  • 通过与识别的条件跳转配对来观察算术和逻辑运算。

这是非常难以执行的。鉴于没有初始信息,您必须使用模式匹配和概率近似来启发式地浏览它。

我已经在这样的工具上工作了两年(我已经编写了大量有用的工具,这些工具注定要由我自己用于工作,我计划有一天分享,但不会很快)。它有效,但还不够成熟,不能扔在丛林中。我的方法如下:如果可能,检测二进制格式的数据结构,通过使用多指令集编码(ARM、x86、MIPS 等)反汇编一大块二进制代码,然后启发式评估(使用 bads 和其他一些东西:] ) 更接近...

但有趣的是,您的问题之前曾在这里,并且给出了一种有趣的方法并被认为是一个答案。它使用与生物学类似的方法来确定系统发育距离。