如何写一个反汇编?

我有兴趣编写一个x86拆信器作为一个教育项目。

我发现唯一真正的资源是Spiral Space的“ 如何编写反汇编程序 ”。 虽然这给出了反汇编器各个组件的高级描述,但我对一些更详细的资源感兴趣。 我也快速浏览了NASM的源代码,但是这是一个重量级的学习。

我意识到这个项目的主要挑战之一是我将不得不处理的相当大的x86指令集。 我也感兴趣的基本结构,基本的反汇编链接等。

任何人都可以指出我写的x86反汇编程序的任何详细的资源?

看看80386程序员参考手册的 第17.2节 。 反汇编器真的只是一个荣耀的有限状态机器 。 反汇编的步骤是:

  1. 检查当前字节是否是指令前缀字节( F3F2F0 ); 如果是这样,那么你有一个REP / REPE / REPNE / LOCK前缀。 前进到下一个字节。
  2. 检查当前字节是否是地址大小字节( 67 )。 如果是这样的话,如果当前处于32位模式,则以16位模式解码指令的其余部分的地址;如果当前处于16位模式,则解码地址以32位模式
  3. 检查当前字节是否是操作数大小字节( 66 )。 如果是这样,如果当前处于32位模式,则立即解码16位模式的操作数;如果当前处于16位模式,则立即解码32位模式的立即操作数
  4. 检查当前字节是否是段覆盖字节( 2E363E65 )。 如果是,则使用相应的段寄存器来解码地址,而不是默认段寄存器。
  5. 下一个字节是操作码。 如果操作码是0F ,那么它是一个扩展操作码,并读取下一个字节作为扩展操作码。
  6. 根据具体的操作码,读入并解码Mod R / M字节,Scale Index Base(SIB)字节,位移(0,1,2或4字节)和/或立即值(0,1 ,2或4个字节)。 这些字段的大小取决于操作码,地址大小覆盖,以及操作数大小覆盖以前解码。

操作码告诉你正在执行的操作。 操作码的参数可以通过Mod R / M,SIB,位移和立即值的值进行解码。 由于x86的复杂性,有很多可能性和很多特殊情况。 请参阅上面的链接以获得更全面的解释。

我会build议检查一些开源的反汇编,最好是歪曲 ,特别是“disOps(指令集数据库)”(CTRL +在页面上find它)。

文档本身充满了关于操作码和说明的多汁信息。

https://code.google.com/p/distorm/wiki/x86_x64_Machine_Code 引用

80×86指令:

一个80×86指令被分成许多元素:

  1. 指令前缀,影响指令操作的行为。
  2. 强制性前缀用作SSE指令的操作码字节。
  3. 操作码字节可以是一个或多个字节(最多3个整个字节)。
  4. ModR / M字节是可选的,有时可能包含操作码本身的一部分。
  5. SIB字节是可选的并且表示复杂的存储器间接forms。
  6. 位移是可选的,它是一个不同大小的字节(字节,字,长)的值,并用作偏移量。
  7. 立即数是可选的,它被用作由不同大小的字节(字节,字,长)构成的一般数字值。

格式如下所示:

 /-------------------------------------------------------------------------------------------------------------------------------------------\ |*Prefixes | *Mandatory Prefix | *REX Prefix | Opcode Bytes | *ModR/M | *SIB | *Displacement (1,2 or 4 bytes) | *Immediate (1,2 or 4 bytes) | \-------------------------------------------------------------------------------------------------------------------------------------------/ * means the element is optional. 

数据结构和解码阶段在https://code.google.com/p/distorm/wiki/diStorm_Internals

引用:

解码阶段

  1. [前缀]
  2. [取指操作码]
  3. [过滤操作码]
  4. [提取操作数]
  5. [文本格式]
  6. [hex转储]
  7. [解码指令]

每个步骤也解释。


原始链接保留历史原因:

http://code.google.com/p/distorm/wiki/x86_x64_Machine_Code和http://code.google.com/p/distorm/wiki/diStorm_Internals

从一些已经组装好的小程序开始,它给你生成的代码和指令。 让自己参考指令体系结构 ,手动完成一些带有体系结构参考的生成代码。 你会发现这些指令有一个非常刻板的结构, 运算符操作数不尽相同。 所有你需要做的就是翻译代码的hex或八进制表示来匹配指令; 有一点玩耍会发现它。

这个过程是自动的,是反汇编的核心。 理想情况下,您可能要在内部构造一个指令结构数组(或者如果程序非常大,则是外部的)。 然后,您可以将该数组转换为汇编程序格式的指令。

您需要从中加载一个操作码表。

基本的查找数据结构是一个特里,但是如果你不关心速度,一个表格就可以做得很好。

为了获得基本的操作码types,从表开始匹配。

有几种解码寄存器参数的方法, 然而,有足够的特殊情况需要单独实施其中大部分。

既然这是教育,看看ndisasm。

Checkout objdump来源 – 这是一个很好的工具,它包含许多操作码表,它的来源可以提供一个很好的基础,使自己的反汇编程序。