如何写一个反汇编程序?

时间:2009-05-29 03:50:28

标签: x86 disassembly

我有兴趣将x86解析器编写为教育项目。

我找到的唯一真实资源是Spiral Space,“How to write a disassembler”。虽然这给出了反汇编程序各种组件的高级描述,但我对一些更详细的资源感兴趣。我还快速浏览了NASM's源代码,但这对于学习有点重要。

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

有人能指出我编写x86反汇编程序的任何详细资源吗?

5 个答案:

答案 0 :(得分:62)

查看section 17.280386 Programmer's Reference Manual。反汇编真的只是一个美化finite-state machine。反汇编的步骤是:

  1. 检查当前字节是否为指令前缀字节(F3F2F0);如果是这样,那么您就有REP / REPE / REPNE / LOCK前缀。前进到下一个字节。
  2. 检查当前字节是否是地址大小字节(67)。如果是,则如果当前处于32位模式,则以16位模式解码其余指令中的地址;如果当前处于16位模式,则解码32位模式下的地址
  3. 检查当前字节是否为操作数大小字节(66)。如果是,则如果当前处于32位模式,则以16位模式解码立即操作数,或者如果当前处于16位模式,则以32位模式解码立即操作数
  4. 检查当前字节是否为段覆盖字节(2E363E2664或{{1 }})。如果是这样,请使用相应的段寄存器来解码地址而不是默认的段寄存器。
  5. 下一个字节是操作码。如果操作码是65,则它是扩展操作码,并将下一个字节作为扩展操作码读取。
  6. 根据特定操作码,读入并解码Mod R / M字节,Scale Index Base(SIB)字节,位移(0,1,2或4字节)和/或立即值( 0,1,2或4个字节)。这些字段的大小取决于操作码,地址大小覆盖和先前解码的操作数大小覆盖。
  7. 操作码会告诉您正在执行的操作。操作码的参数可以从Mod R / M,SIB,位移和立即值的值解码。由于x86的复杂性,有很多可能性和许多特殊情况。请参阅上面的链接以获得更详尽的解释。

答案 1 :(得分:22)

我建议查看一些开源的反汇编程序,最好是distorm,特别是“disOps(Instructions Sets DataBase)”(ctrl +在页面上找到它)。

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

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

  

80x86说明:

     

80x86指令分为a   元素数量:

     
      
  1. 指令前缀,影响指令的行为   操作
  2.   
  3. 强制前缀用作SSE指令的操作码字节。
  4.   
  5. 操作码字节,可以是一个或多个字节(最多3个整字节)。
  6.   
  7. ModR / M字节是可选的,有时可能包含部分内容   操作码本身。
  8.   
  9. SIB字节是可选的,表示复杂的内存间接   形式。
  10.   
  11. 位移是可选的,它是不同大小的值   字节(字节,字,长)并用作   偏移量。
  12.   
  13. 立即是可选的,它用作构建的一般数字值   从不同大小的字节(字节,   字,长)。
  14.         

    格式如下:

    /-------------------------------------------------------------------------------------------------------------------------------------------\
    |*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.   
  7. [提取操作数]
  8.   
  9. [文字格式]
  10.   
  11. [Hex Dump]
  12.   
  13. [解码指令]
  14.   

每个步骤也都有解释。


原始链接由于历史原因而保留:

http://code.google.com/p/distorm/wiki/x86_x64_Machine_Codehttp://code.google.com/p/distorm/wiki/diStorm_Internals

答案 2 :(得分:6)

从一个已组装的小程序开始,它既为您提供生成的代码,也为您提供指令。使用instruction architecture获取参考资料,并手动完成一些生成的代码和体系结构参考。您会发现这些指令具有非常典型的 inst op op op 结构,具有不同数量的操作数。您需要做的就是翻译代码的十六进制或八进制表示以匹配指令;一点点玩耍都会揭示它。

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

答案 3 :(得分:4)

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

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

要获得基本操作码类型,请从表格开始匹配。

有一些解决寄存器参数的库存方法;但是,有足够的特殊情况需要单独实施其中的大多数。

由于这是教育性的,请看一下ndisasm。

答案 4 :(得分:2)

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