/-----------------------------\ | 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.