Copy Link
Add to Bookmark
Report
xine-1.009
/-----------------------------\
| Xine - issue #1 - Phile 009 |
\-----------------------------/
Mutation Engines
by JHB
Since I first heard about the idea of a Mutation engine I was
interested to see the code that would explain how such a devious piece of
code could work. I had taken apart several viruses, but most mutation
engines due to thier nature are difficult to dissassemble. So after
seeing other people's code I decide to try my hand at this type of coding.
This article will illustrate the path I took in designing and building a
Mutation Engine.
To start I will try to define what a Mutation engine is, its code that
can be link or added to a regular program or virus that will:
1 Encrypt itself as well as the program that is linked to it
2 Create a Decryptor that will be run first before the main program
3 Each Decryptor that it creates has a different signature
Ok, now lets explain the defination, a signature (when refering to code)
is a piece of code that should be unique to that code. An example of this
is the signature:
EA 05 00 C0 07
Which is the hex code for
jmp 07c0:0005
This (which some may reconize) is the first line of code for the Stoned
virus though it is short piece of code, placing this piece of code in the
first part of the boot sector use to cause many Av products to false
alarm. (not tested lately)
Now a true mutation engine could alter this code to some other code
that would accomplish the same thing, though this is possible it would
make the engine huge. Mutation Engine writers have taken a easier way out
they encrypt the main code and the engine then put a decryptor as the
first thing that is run.
This means that the only signature that has to alter is the decryptor,
this is the main type of engine that is created these days.
The first part of the creation process is to create a
encryptor/decryptor that this should be fairly simply encrytion. I played
with the standard xor/add/sub but they were spotted immeditaly by TBAV and
F-prot as encrypted code. Since the main idea of a mutation engine is to
fool both people and scanners this was not a good start. Well while
reading the usenet group I saw a mention of a encryption that uses
shl/shr. Many people may wonder if you use a shl/shr the leading bit or
end bit is lost this is not true it is moved the carry flag. By simply
adding this to the front or end of the register (or word) you can have
reversible encrytion. Now TBAV will find most of these except for even
number shifts like 2,4,8 while F-prot seems to miss most of these( only
in heurstices and the /parnoid). (I was told this is because the shl 2,4,8
code can also be used as a quick multiply or divide, so tbav will not flag
this encryption). So I soon had this as a decryption module
mov bx,offset virus_code
decrypt:
mov cx,4 ;encrytion key
mov ax,cs:[bx] ;get the word to encrypt
again:
clc ;not needed I was young forgive me ;)
shl 1 ;ok so ax before this code is
; ax 1000 0000 0000 0000 cf = 0
;after the shl
; ax 0000 0000 0000 0000 cf = 1
jnc no_high_bit ;
inc ax ;this simpy makes ax =
; ax 0000 0000 0000 0001
no_high_bit:
dec cx
jcxz done_unencr ;ok done shifting it again
jmp short again ;shift it again
done_enencr:
mov cs:[bx],ax ;Store the decrypted code
add bx,2 ; move our pointer
dec dx ;track how much is left
jnz decrypt
virus_code:
Ok, so there we have a decryptor now use a shr and you have the
encryption routine (its in the code read it ;) ).
Ok now at this point I have a encryption engine that will fool TBAV
and F-prot ( unless you use the f-prot /paranoid which the average user
just does not do) but this is not a mutation engine. Well one simple
mutation is to change the registers its a simple thing just requires some
research that debug or a decent assembly book will show. All assemble
instructions are built in a pattern take
push ax which in hex is
50h or 1001 0000b
now
push bx is
53h or 10010 011b
note that the 3 last bits are they only thing that changes this follows
through so that for the word registers
ax = 000 0
cx = 001 1
dx = 010 2
bx = 011 3
sp = 100 4
bp = 101 5
si = 110 6
di = 111 7
Ok so with some simple and/or instruction we can change the registers
any other register of course we must not just randomly change registers
we have to track which register we have use and make sure that we change
all bx to cx.
This is where some people start to get lost because we start treating
code we are going to run as data. Take this example:
mov cx,0004 ;b90400h
becomes
shift_reg:
db 0b9h ;10111 001 <- cx
dw 0004
Now the mutation for this code might look like this
mov ax,[shift_reg] ;
and ax,11111000h ;this will isolate the mov
;instruction
or ax,00000111 ;this would make the instruction
;mov di
A better way would be to use a random number generator and get a number
between 0-7 then OR that into it rather than the constant I used. Of
course you must track what registers you use as you go.
Now using this technique we have a limited mutation engine and just so
you do not forget F-prot still catches it. So the next simple mutation use
a sorta undocumented form of the shl instruction.
shl AX,1 D1 E0 1101 000 1 1110 0000 <-USUAL CODE
SHL AX,1 D1 F0 1101 111 1 1110 0000 <-UNDOC
SHL AX,1 C1 E0 01 <-USUAL CODE
SHL AX,1 C1 F0 01 <-UNDOC
D1 F0 <-APPEARS THAT NEITHER FP OR TB FIND IT
Now the unuasual part while all of the above code does the same thing
shift the bits in the AX reg left the ones with the F0h are not used by
many assemblers. (Though I have read that a shareware Assembler may use
these codes maybe to track code that was produced by it). Using the
"undocumented" form will fool f-prot every time but the c1 f0 01 will flag
tbav with (and I love this flag) " 1 found instruction that will require
an 80186 processor or above" Like they have add no instructions to the
code set after the 8086!! But for a virus generated code this would not be
a flag you want. Since any flag that was not there before will cause a
problem.
Ok so we have a simple mutation a reversible simple encryption and at
least 4 forms of the decryptor code not including the mutation of the
registers. The next part is to add do nothing or noise code. This is
where careful creativity comes into play. Noise instructions or Do
nothing bytes are instructions that actauly do, do something they just do
not affect your code. NOP, XCHG AX,AX are some examples of do nothing
code. In the early days of mutation engines and herustic scanners just
adding nops and xchg code could make the virus unscannable. But as
scanners improved they now will watch for such do nothing code, either
ignoring it and seeing the real code or warning the user that there is
code that serves no purpose but to hide a virus. Again I found that you
could use some of these ideas say 1 or two nops in a row but too many and
TBAV went to red alert. So I thought instead of using just one byte
instructions why not have routines that called interrupts. just find
ones that do not affect to many regs or put push regs code pop regs this
way none of the real code is affected. An Example
noise_6:
push ax ;1 get the shift flags only affects the
mov ax,0200h ;3 ax reg so push it then pop it.
int 16h ;2
pop ax ;1
end_noise_6:
Combine all these ideas togther and you can have an interesting piece
of code that will produce several differnt variations on the decryptor.
Well thats about all for me. If your realy interested in fooling with
making a mutation engine get ahold of of as many source codes as you can
and examine them then attempt one on your own. Even if you fail in
making a viable mutation engine you will understand them far better. I
did not bother to make my code a true engine its an example thats all.