【问题标题】:How IDA pro creates assembly code from binaries?IDA pro 如何从二进制文件创建汇编代码?
【发布时间】:2018-03-25 04:33:32
【问题描述】:

如何从已编译的二进制文件中创建程序集?

我正在学习 x86 汇编编程。所以我开始了解 gdb、objdump 和 IDA pro,这些是从二进制文件创建程序集的程序。我想知道他们如何从二进制文件创建程序集?当我在记事本中打开二进制文件时,它会显示很多符号、数字和字母。我的疑问是他们如何从编译的二进制文件创建程序集?

【问题讨论】:

  • 用记事本打开非文本文件没有用。这只是字节,但有些恰好在 ASCII 范围内,有些则不在。某些字节显示为数字和字母只是巧合。
  • IDA 所做的事情很复杂,这就是该程序如此昂贵的原因。

标签: assembly binaryfiles ida


【解决方案1】:

Assembly 与机器码(大致)有 1:1 的对应关系1,因此从原则上讲,反汇编并不复杂:只要你有一个机器码块及其所在的地址必须加载,您从第一条指令开始并开始解码。

在 RISC 架构上,这项工作通常更容易,因为机器指令通常具有固定大小,通常非常规则 - 例如,“经典”ARM 和 PowerPC 使用固定大小的 32 位指令,其中部分位指定汇编指令、参数等。在 x86 上,情况要复杂一些,既因为它是一个可变长度指令集,又因为它随着时间的推移不规则地演变。

一般来说,一条汇编指令由一个或多个字节的前缀组成(可以转换回汇编前缀,例如replock,指定该指令对不同的段或与默认值不同的大小,或完全选择不同的子指令集 - 参见例如 VEX 前缀),一个操作码(一个指定指令的字节加上可能的部分参数),然后是参数(有一些规则的编码来指定立即数、寄存器或内存操作数,以及它们的各种寻址模式)。有关通用 x86 指令格式的更详细说明,请参阅this nice diagram(以及一般该站点)。

一旦它解码了指令,反汇编器必须解析相对地址/跳转(将它们应用于代码中的当前位置)并发出相应的程序集,可能为跳转目标组成标签名称(或者只是离开跳转目标作为普通地址)。

现在,这只是低级部分,这是“原始”反汇编程序(例如ndisasm)可以做的。但是,除了特殊情况(如 MS-DOS 中的 COM 文件),可执行文件不仅仅是 CPU 执行的原始代码,而是更结构化的二进制格式。

通常,一个可执行文件包含几个部分,这些部分可以包含不同类型的数据。通常有一段用于汇编代码(通常命名为.text),加上几个用于程序数据(可变和不可变,零初始化,合并资源,...)的部分以及加载器的其他附件信息,例如来自动态链接库和重定位信息。更复杂的可执行检查工具(例如 objdump、nm 或 dumpbin)可以解析可执行格式、解码它们的结构,并且 - 如果需要 - 反汇编它在代码段中找到的代码。

除此之外,诸如 IDA 之类的工具增加了相当多的智能——它们解析可执行格式、部分执行加载器的工作(对代码应用重定位)、反汇编代码并对其执行大量分析- 它尝试遵循代码流,如果可用则传播类型信息(通常从 OS API 开始,其入口点是众所周知的),检查对全局数据的访问模式以推断其类型,...


  1. 也就是说,减去 cmets 和“高级”功能,例如宏、标签名称和跳转,您将计算目标地址的最佳方法留给汇编器。此外,同义词指令之间的区别(例如je/jz)显然丢失了 - 反汇编程序通常只会在解码操作码时发出可能的同义词之一。

【讨论】:

    【解决方案2】:

    更简洁的答案是 IDA Pro 是一个“递归下降”工具。这意味着,在识别出二进制标头和部分之后,它会从文本段的开头(更具体地说,在入口点)开始反汇编代码。之后,它将开始跟随分支,递归地向下遍历代码,尝试识别并跟随这些分支,而不是简单地假设代码从文本段的开头开始顺序对齐。

    这工作非常非常好,不像线性反汇编那样容易混淆,但它仍然无法通过跳转表和其他动态计算的分支跟随分支。

    【讨论】:

      猜你喜欢
      • 2010-11-01
      • 2011-09-05
      • 2018-10-06
      • 2013-01-19
      • 1970-01-01
      • 2017-01-03
      • 2011-05-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多