标 题: [翻译]多态变形技术教学_2
翻 译: arhat
时 间: 2006-06-03 21:19
链 接: http://bbs.pediy.com/showthread.php?threadid=26810
详细信息:

多态变形技术教学(2)-高级的方法

 

                

文档编号:

S001-F001

原作者:

Lord Julus

译者:

arhat[ptg]

 

审校:

KanxueCCDebuger

 

发布时间:

200661

原文:

http://vx.netlux.org/lib/static/vdat/tupolyii.htm

关键词:

多态 译码器 操作码 寻址

 

 

 

 


 

0     序言.......................................................................................................................... 3

1     指令集...................................................................................................................... 5

1.1      操作数长度和地址长度属性............................................................................ 5

1.2      指令格式........................................................................................................ 6

1.3      ModR/MSIB字节....................................................................................... 8

1.4      操作码.......................................................................................................... 15

1.5      指令............................................................................................................. 16

1.6      操作码表...................................................................................................... 18

1.6.1       主要的缩写词..................................................................................... 19

1.6.2       寻址方法的代码................................................................................. 19

1.6.3       操作数类型的代码.............................................................................. 20

1.6.4       寄存器代码........................................................................................ 20

1.6.5       One-Byte操作码表.............................................................................. 21

1.6.6       Two-Byte操作码表(第一个字节是0FH.......................................... 25

1.6.7       通过modR/M字节的5,4,3位确定操作码............................................. 29

1.6.8       条件的定义........................................................................................ 29

2     生成指令................................................................................................................. 32

2.1      随机寄存器选择器........................................................................................ 35

2.2      随机值选择器............................................................................................... 37

2.3      指令生成器................................................................................................... 37

2.4      垃圾生成器................................................................................................... 40

3     转向32............................................................................................................... 46

4     结束语.................................................................................................................... 49

 


0   
序言

 

嗨,朋友们本文的姊妹篇(29A#2.2_9<Analysis on the decryptor generation>)放到网上已经一年有余了,我可以大言不惭的说,这篇文章在当时的反响还是蛮不错的,也正因为如此,它上了29A病毒杂志的第二期。我在那篇文章结尾,曾大胆预言随着时间的推移,重心将会慢慢转向32Winodws编程上来。嗯, 至少现在看来Windows的好日子还没有到头,因此,我们认识到――“必须要熟悉”Windows 32位编程但问题来了,关于16位的知识我们还能依赖多少呢?对硬件来说,答案是0。尽管如此,微处理器还是大同小异的。你所掌握的16位知识仍可适用于32位。那么,我们还能用上多少老本呢?答案是“非常多”!

人们在接触Win32汇编程序之后可能会有所疑问,可以在Win32下完成多态引擎吗?好奇的我开始忙碌了事实上,到目前为止,我已经完成了你所需要的第1个多态引擎。

那么,我打算在这篇文章里说些什么呢?

如果你读过本文的姊妹篇,肯定知道那篇文章中所述的内容还没有过时!因此,本文就不再讨论那些(解密)话题了(搜索我写的加密文章,了解清楚),而是把精力集中在――真正隐藏解密的最好方法――垃圾生成上在本文中,我将介绍需要使用的指令,也将尽力以通俗易懂的方式描述。我还会谈到构成代码仿真器有那些难点,我会介绍编写Win32多态引擎时需要掌握的Win32知识时不待我,开始吧!

 

 

----------------------------------[  致谢  ]-----------------------------------

 

在一生中,总有一些人会对我们产生莫大的影响,他们理应得到所有的荣誉下面是其中的一部分:

 

          dark avenger, dark fiber, dark angel, darkman, mr.sandman,

        virtual daemon, qark, quantum, b0z0, wild worker, black baron,

        the unforgiven, murkry, shaitan, tatung, jacky qwerty, griyo,

      kid chaos, cicatrix, priest, liquid jesus, metabolis, nowhere man,

           opic, blue skull, hellfire, hellraiser, and many more...

 

我所掌握的知识只是他们的千分之一

 

特别感谢SLAM小组!

 

 

-------------------------------[  免责声明  ]----------------------------------

 

此文档仅用于学习Intel(c)公开的信息。不应当用这里揭露的信息危害任何人,作者将不会为滥用这些信息所造成的数据丢失或破坏负任何责任。本文全面介绍IntelIntel兼容微处理器生成操作码的方法。

 

 

---------------------------------[  起源  ]------------------------------------

 

本文很大一部分内容来自原始的Intel 386文档,具体的说,是微处理器指令。我必须对它们详加说明,因为这样一来,你会明白生成所需要的指令是非常简单的一回事。我还从Intel手册里引用了一些内容,比如说你肯定认识的、著名的操作码表最重要的是,你要知道怎样使用它们,说得更实际一点,你应该知道怎样优化它们?如果你知道,请告诉我…;)) 对我来说,没有什么可以比发现有人理解我所写的文章更令人高兴了

总的来说,本文分成2大部分:指令说明和具体的多态引擎技术。


 

                            .-------------------.

----------------------------|       PART I      |-----------------------------

                            '-------------------'

 

1   
指令集

 

1.1  操作数长度和地址长度属性

80386执行指令时,可以用1632位的地址访问内存空间。因此,每条使用内存地址的指令都与1632位的地址长度属性相关。16位地址暗示指令使用16位的位移,生成16位的地址偏移(段相对地址),就像有效地址计算一样。32位地址暗示使用32位的位移,生成32位的地址偏移量。同样,访问word16位)或doubleword32位)的指令具有1632位的操作数长度属性。

默认的组合,指令前缀,和(保护模式下的程序除外)段描述符里的长度说明位决定了这个属性。

运行在实模式或虚拟8086模式里的程序在默认情况下使用16位的地址和操作数。

指令的内部编码包括两个以字节为单位的前缀:地址长度前缀――67H,操作数长度前缀――66H。指令的段属性对这些前缀不起作用。下表显示了默认值与前缀混合后可能产生的结果。

隐式使用栈的指令(例如:POP EAX)同样具有1632位的栈地址长度属性。带16位栈地址长度属性的指令使用16位的SP栈指针寄存器;带32位栈地址长度属性的指令使用32位的ESP寄存器来构成栈顶的地址。


 

    .-------------------------------------------------------------------.

    | Segment Default D = ...  |   0    0    0    0    1    1    1    1 |

    | Operand-Size Prefix 66H  |   N    N    Y    Y    N    N    Y    Y |

    | Address-Size Prefix 67H  |   N    Y    N    Y    N    Y    N    Y |

    |--------------------------+----------------------------------------|

    | Effective Operand Size   |  16   16   32   32   32   32   16   16 |

    | Effective Address Size   |  16   32   16   32   32   16   32   16 |

    |-------------------------------------------------------------------|

    | Y = Yes, this instruction prefix is present                       |

    | N = No, this instruction prefix is not present                    |

    '-------------------------------------------------------------------'

 

所以,从根本上说,一条指令肯定会有一个操作数和/或一个地址。我们可以有各种各样的1632位组合,也可以不考虑默认值。这些前缀可以出现多次,但只有最后一个起作用。

 

1.2  指令格式

所有的指令编码都是下图显示的、一般指令格式的子集。一条指令的组成部分可以包含:可选的指令前缀,一个或二个主操作码字节,或由ModR/M字节和SIBScale Index Base)字节组成的地址说明符,如果需要的话,还可以包含位移量,立即数字段。

较小的编码字节可以在主操作码内定义。这些字段定义操作的方向,位移量的大小,寄存器编码,或符号扩展;编码的字段依操作的类型而定。

许多涉及内存里的操作数的指令在主操作码字节后都有一个寻址形式字节。这个字节被称为ModR/M字节,详细说明所使用的寻址形式。ModR/M字节的某些编码指示第二个寻址字节――SIB字节,它跟在ModR/M字节之后,在完全确定寻址形式时需要它。

寻址形式可以直接在ModR/MSIB字节后包括位移量。如果包括位移量,它可以是8-16-32位的。

如果指令指定一个立即操作数,立即操作数将总是跟在位移字节后,如果指定的话,立即操作数总是指令的最后一个字段。

下面是被认可的指令前缀编码:

 

   F3H    REP prefix (仅用于字符串指令)

   F3H    REPE/REPZ prefix (仅用于字符串指令)

   F2H    REPNE/REPNZ prefix (仅用于字符串指令)

   F0H    LOCK prefix

 

下面是段重叠前缀:

 

   2EH    CS segment override prefix

   36H    SS segment override prefix

   3EH    DS segment override prefix

   26H    ES segment override prefix

   64H    FS segment override prefix

   65H    GS segment override prefix

   66H    Operand-size override

   67H    Address-size override

 

 

      80386 指令格式

 

   P  .---------------------------------------------------------------.

   R  |  INSTRUCTION  |   ADDRESS-    |    OPERAND-   |   SEGMENT     |

   E  |    PREFIX     |  SIZE PREFIX  |  SIZE PREFIX  |   OVERRIDE    |

   F  |---------------------------------------------------------------|

   I  |     0 OR 1         0 OR 1           0 OR 1         0 OR 1     |

   X  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|

   E  |                        NUMBER OF BYTES                        |

   S  '---------------------------------------------------------------'

 

   R  .---------------------------------------------------------------.

   E  |  OPCODE  |  MODR/M   |  SIB  |   DISPLACEMENT   |  IMMEDIATE  |

   Q  |          |           |       |                  |             |

   U  |---------------------------------------------------------------|

   I  |  1 OR 2     0 OR 1    0 OR 1      0,1,2 OR 4       0,1,2 OR 4 |

   R  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|

   E  |                        NUMBER OF BYTES                        |

   D  '---------------------------------------------------------------'

 

这也是说,我们的指令最小可以是1字节,最大可以是16个字节长度。

 

1.3  ModR/MSIB字节

在许多80386指令里,ModR/MSIB字节跟在操作码字节之后。它们包含如下信息:

 

  *  这条指令所使用的索引类型或寄存器号

  *  所使用的寄存器,或所选指令的详细信息

  *  基址,变址和比例因子信息

 

ModR/M 字节分为3个字段,包含的信息是:

 

  *  mod字段,占用字节的2个最高位,与r/m字段结合起来可以形成32种不同的组合:8个寄存器和24个索引方式

  *  Reg字段,占用mod字段之后的3个位,指定寄存器号或多于3个位以上的操作码信息。Reg字段的意义由指令的第一个(操作码)字节确定

  *  r/m字段,字节的最后3位,可以把寄存器指定为操作数的位置,或者和上面所述的字段结合起来形成寻址方式编码的一部分

 

基址索引和32位寻址形式的比例索引需要SIB字节。ModR/M字节的某些编码位指示SIB字节的存在。SIB字节包括如下的字段:

 

  *  ss字段,占用字节中最高的2位,指定比例因子

  *  变址字段,占用ss字段后的3个位,指定变址寄存器的寄存器号

  *  基址字段,占用字节最后的3个位,指定基址寄存器的寄存器号

 

 

ModR/MSIB字节格式

 

                                 MODR/M BYTE

 

                     7    6    5    4    3    2    1    0

                    .------------------------------------.

                    |  MOD   | REG/OPCODE  |     R/M     |

                    '------------------------------------'

 

                          SIB (SCALE INDEX BASE) BYTE

 

                     7    6    5    4    3    2    1    0

                    .------------------------------------.

                    |   SS   |    INDEX    |    BASE     |

                    '------------------------------------'

 

现在让我们认真考虑它们实际的应用吧。下面有2个表,利用它们可以任意生成指令。第一行指定所用的寄存器。如果你用8位寻址方式,将用8位寄存器,16位寻址用16位寄存器,32位寻址用32位寄存器。虽然你用了相同的编码,但实际上,不是你而是处理器解释它们。此后,是4个部分8种可能的编码寻址方式。第1个双编号列包含MODR/M字段,以及此后,如果你在MODR/M字段之后安置REG字段,你可以得到的十六进制编码。象往常一样,这将生成8种类型*4个部分*8个寄存器=256变体的矩阵。

 

ModR/M字节的16位寻址表


 .--------------------------------------------------------------------------.

 | r8(/r)                   | AL  | CL  | DL  | BL  | AH  | CH  | DH  | BH  |

 | r16(/r)                  | AX  | CX  | DX  | BX  | SP  | BP  | SI  | DI  |

 | r32(/r)                  | EAX | ECX | EDX | EBX | ESP | EBP | ESI | EDI |

 | /digit (Opcode)          | 0   | 1   | 2   | 3   | 4   | 5   | 6   | 7   |

 | REG =                    | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 |

 |--------------------------+-----------------------------------------------|

 |                | Mod R/M |         ModR/M Values in Hexadecimal          |

 |----------------+---------+-----------------------------------------------|

 | [BX + SI]      | 00  000 | 00  | 08  | 10  | 18  | 20  | 28  | 30  | 38  |

 | [BX + DI]      | 00  001 | 01  | 09  | 11  | 19  | 21  | 29  | 31  | 39  |<