181 lines
11 KiB
Plaintext
181 lines
11 KiB
Plaintext
|
|
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
|
|
Boot Infectors
|
|
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
|
|
By Dark Angel
|
|
Phalcon/Skism
|
|
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
|
|
|
|
As most of our readers have no doubt noticed, 40Hex articles have
|
|
traditionally covered file based viruses. It is time to fill in the hole and
|
|
cover the other large class of viruses, the partition table and boot sector
|
|
viruses, herein termed "boot infectors" for brevity.
|
|
File based viruses are executed after the operating system loads. Boot
|
|
infectors, however, latch onto the parts of the drive that are accessed by the
|
|
BIOS when it attempts to load the operating system itself. Therefore, there is
|
|
little that can be done to intercept the boot infector once it has
|
|
successfully installed itself onto a disk.
|
|
A brief explanation of the basics of disk terminology is in order. Each
|
|
disk is divided into 512 byte chunks called sectors. Due to an unfortunate
|
|
choice in terminology, however, the system BIOS uses the term "sectors"
|
|
differently. For our purposes, we will divide the disk into 512 byte blocks,
|
|
with block 0 residing on the beginning of the disk.
|
|
The system BIOS assigns three values to each block on the disk. The
|
|
values are known as sectors, cylinders (sometimes known as tracks), and heads
|
|
(sometimes called sides) and can be represented as a triple
|
|
(sector,cylinder,head). Each disk has a certain number of sectors (SEC),
|
|
cylinders (CYL), and heads (HDS). Cylinders are numbered from 0 to CYL - 1.
|
|
Heads are numbered from 0 to HDS - 1. Sectors, for some unfathomable reason,
|
|
are numbered from 1 to SEC. Block 0 corresponds to the triple (1,0,0) (sector
|
|
1, cylinder 0, head 0). Block 1 corresponds to (2,0,0), Block 2 with (3,0,0),
|
|
and so on, until Block SPH. Block SPH corresponds to (1,1,0), Block SPH+1 with
|
|
(2,1,0), and so on. Block 2*SPH is (1,2,0), Block 2*SPH+1 is (2,2,0), etc.
|
|
This continues until Block HPC*SPH, which is (0,0,1).
|
|
An introduction to the boot process is vital to understanding boot
|
|
infectors. When the system is reset, the BIOS checks the first block, triple
|
|
(1,0,0), of the first hard drive of the system (if any are installed, of
|
|
course) to absolute memory address 7C000. If the hard drive exists, the block
|
|
that was read in is checked for the signature 0AA55 (in reverse word format)
|
|
occuring at offset 1FE. This is the marker for a valid partition table. If a
|
|
partition table is found, the code residing in this block is executed at
|
|
0:7C00. If a valid partition table is not found (or the hard drive doesn't
|
|
exist), then the BIOS tries booting from the floppy drive. It again reads the
|
|
first block from the first floppy drive to absolute memory address 7C000. If
|
|
there is a readable disk in the drive, it will be loaded in and executed. No
|
|
check is made for the 0AA55 signature, although many boot sectors have it
|
|
there anyway just for consistency.
|
|
Technically, the first block of the hard disk is a boot sector just as it
|
|
is on floppies. However, it is sometimes given a different name because of the
|
|
partition table convention that allows multiple operating systems to reside on
|
|
a single drive. We will call it by the somewhat misleading name of partition
|
|
table. Another common name is the master boot record, for reasons that will
|
|
become clear momentarily. The partition table convention is basically a simple
|
|
structure at the end of the first block of the hard drive that defines where
|
|
each operating system exists on a given hard drive. The partition table
|
|
structure begins at offset 1BE in the block and consists of an array with four
|
|
entries. The format of each entry is:
|
|
|
|
Ofs Size Description
|
|
0 BYTE boot indicator, 0 = non-bootable, 80h = bootable
|
|
1 BYTE head the partition begins on
|
|
2 BYTE sector the partition begins on
|
|
3 BYTE cylinder the partition begins on
|
|
4 BYTE system indicator, indicates what OS resides in the partition
|
|
01 indicates DOS 12-bit FAT
|
|
04 indicates DOS 16-bit FAT
|
|
5 BYTE head the partition ends on
|
|
6 BYTE sector the partition ends on
|
|
7 BYTE cylinder the partition ends on
|
|
8 DWORD total number of blocks preceding the partition
|
|
0C DWORD total number of blocks in the partition
|
|
|
|
The code in the partition table loads the boot record of the active
|
|
partition (as indicated in the first bit of the partition table structure).
|
|
The boot record then loads the operating system that resides in its respective
|
|
partition.
|
|
When BIOS decides to boot from a floppy, it reads in the first block off
|
|
the floppy to 7C000. Floppies don't have partition tables, so this block is
|
|
the equivalent of the boot record of a partition on a hard disk.
|
|
In DOS, the boot record consists of three bytes for a JMP followed by the
|
|
following structure, sometimes known as the BIOS parameter block (BPB):
|
|
|
|
Offset Size Description
|
|
3 8 bytes OEM name and version (ASCII)
|
|
0B Word bytes per sector
|
|
0D Byte sectors per cluster
|
|
0E Word reserved sectors (starting at logical sector 0)
|
|
10 Byte number of FATs
|
|
11 Word number of root directory entries (32 bytes each)
|
|
13 Word total sectors in partition
|
|
15 Byte media descriptor
|
|
17 Word sectors per FAT
|
|
19 Word sectors per track
|
|
1B Word number of heads
|
|
1D Word number of hidden sectors
|
|
|
|
The rest of the boot record consists of code that loads and executes the
|
|
DOS system files, which then take over. There are a number of terms in the
|
|
above structure which may be unfamiliar, but don't fret; they will be
|
|
explained in due course.
|
|
First, however, it is important to note that nothing requires these
|
|
structures to exist! The partition table, for example, is merely a de facto
|
|
convention which was set up to allow operating systems to co-exist on a single
|
|
hard drive. The boot record structure defined above is used by DOS for DOS
|
|
programs. Of course, another operating system could interpret the structure,
|
|
but there is no requirement for a given operating system to use that format.
|
|
When infecting disks, however, keep in mind that certain programs require the
|
|
structures to be in place. DOS, for example, won't recognise partitions
|
|
properly without the partition table being at its usual location. Floppies
|
|
also won't work properly if the boot record is not loaded when DOS requests a
|
|
read to the first block. In other words, make sure that all requests to the
|
|
partition table or boot record return the partition table and boot record in
|
|
the appropriate locations. The other code may be changed with the only
|
|
drawback in such a scheme being easy detection of the code modifications. A
|
|
better approach is to redirect requests to the modified blocks to a stored
|
|
copy of the original. In other words, stealth.
|
|
Seeing these structures, the method of infection, conceptually, at the
|
|
very least, should be apparent. It's a simple matter to replace the code of
|
|
the partition table or boot record with your own. All your code has to do is
|
|
store the block somewhere else on the disk and replace the block with itself.
|
|
When the virus gains control, it needs to put itself in memory and then load
|
|
the original block into memory at 7C000 and then transfer control to this
|
|
code. Once it is in memory, it is free to infect any disks which come into
|
|
contact with the computer.
|
|
This is all nice and easy to say, but there are a few details which would
|
|
be helpful to know before plunging into writing a boot infector. When control
|
|
is transferred to either the partition table or boot record, CS:IP is set to
|
|
0:7C00. SS:SP is undefined, so most boot infectors set it to 0:7C00, which
|
|
causes the stack to be placed just below the loading area. This is sufficient
|
|
for the needs of most viruses.
|
|
Additionally, it would be nice to be able to locate empty space to store
|
|
the original boot sector or partition table. Here, the virus has a number of
|
|
choices. In hard disks, many viruses store the original partition table in the
|
|
unused space between the partition table and the first partition. The first
|
|
partition generally starts at triple (2,1,0) or later (some start as late as
|
|
(2,0,1), so there is a wealth of space in which to store the virus in that
|
|
area. A simple calculation reveals that there are (number of cylinders - 2)
|
|
sectors between (1,0,0) where the partition table is and (2,1,0) where the
|
|
first partition starts). Multiply that value by 512 and you have the number of
|
|
bytes you can store there. That's a large chunk of space you have at your
|
|
disposal. A virus may also store itself at the end of the root directory,
|
|
although it risks overwriting valid directory entries. The BPB contains
|
|
everything necessary to calculate the location and length of the root
|
|
directory.
|
|
An alternate approach, which is used by several viruses, is to alter the
|
|
file allocation table, or FAT. The FAT is an array of entries which describe
|
|
how the blocks on the disk are related. FAT entries are either 12 or 16 bits
|
|
long, depending on the disk. 12 bit FAT's are generally used in disks and
|
|
partitions with less than 20740 sectors and 16 bit FAT's are used in larger
|
|
disks and partitions. The location and size of the FAT can be found in the
|
|
BPB. Each entry in the FAT corresponds to a block on the disk. The FAT
|
|
describes a file's placement on the disk. By following the chain, you can find
|
|
the location of the blocks of the file, since they need not be contiguous. The
|
|
value of the FAT entry is the number of the next block in the chain, i.e. an
|
|
index to the FAT entry corresponding to the next block of the file, unless it
|
|
is one of the special values. If the value of the FAT entry is 0, then the
|
|
block is unused. If the value is -1 to -8 (FFF8-FFFF) then the block is the
|
|
last block in a file. If the value is -9 to -10h (FFF0-FFF7) then the block is
|
|
reserved (usually a bad block). The first and second entries in the FAT are
|
|
always -1. The third entry governs the first data area. The idea is for the
|
|
virus to find empty blocks, mark them as bad in the FAT, and store the code
|
|
there. This way, DOS thinks the blocks are bad and does not overwrite the
|
|
virus.
|
|
One important issue with partition table infectors is whether they should
|
|
preserve the partition table itself, i.e. leave the partition table structure
|
|
at offset 1BE in the first block of the disk. Similarly, should boot sector
|
|
infectors retain the BPB? This is a particularly interesting issue with
|
|
stealth viruses, viruses which redirect attempts at accessing the partition
|
|
table or boot sector. The advantage of retaining the structures is that DOS
|
|
will recognize the disks even when the virus is not loaded in memory.
|
|
Therefore, the virus is somewhat less vulnerable to detection. However, if the
|
|
virus does not keep the structure, then it will be more difficult for the user
|
|
to boot the computer without loading the virus in memory, since DOS will not
|
|
recognise the drive. This is an especially nifty feature, since primitive
|
|
cleaning attempts such as FDISK /MBR will fail against such a virus.
|
|
Within this motley assortment of information, you will find enough to aid
|
|
you in crafting an original boot infector. There is intentionally no code in
|
|
this tutorial, mainly because there is little virus-specific information
|
|
contained within. Many of the routines used in a boot infector are important
|
|
when writing any boot sector, so there is little importance in repeating the
|
|
code here.
|