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

МЕТОДЫ БОРЬБЫ
С ВИРУСАМИ

В этой главе описаны наибо-
лее эффективные методы
борьбы с вирусами, защиты
от проникновения и лечения.
Приведены алгоритмы необ-
ходимых действий при подо-
зрении на наличие вируса
в компьютере. Описаны меры
по предотвращению "эпиде-
мии" путем создания про-
граммы-блокировщика. 

Рассмотрен пример создания
программы-антивируса.
Представлены исходные тек-
сты программ с подробными
комментариями. 



В предыдущих главах состоялось знакомство с компьютерными вируса-
ми, поражающими Flash BIOS, документы текстового процессора
Microsoft Word 6.0 for Windows, файлы разных операционных систем
и прочие. Пришло время рассмотреть различные способы борьбы с ними. 

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

Таким образом, на 100% защититься от вирусов практически невозмож-
но (подразумевается, что пользователь меняется дискетами с друзьями
и играет в игры, а также получает информацию из других источников,
например из сетей). Если же не вносить информацию в компьютер из-
вне, заразиться вирусом невозможно - сам он не родится. 

Итак, что же можно посоветовать, чтобы сталкиваться с вирусами как
можно меньше или, по крайней мере, только сталкиваться, не допуская
их на жесткий диск своего винчестера. В первую очередь - самые эле-
ментарные правила "компьютерной гигиены": проверка дискет на нали-
чие вируса самыми надежными антивирусными программами, такими, 



например, как AVP или DrWeb. Очень хорошо, если на жестком диске
установлен ревизор Adinf. Многие пользователи добавляют строку за-
пуска ревизоров, антивирусов, антивирусных мониторов в конфигура-
ционный файл AUTOEXEC.BAT - тоже весьма действенно. 

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

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

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

Стоит также заметить, что программы-детекторы не слишком универ-
сальны, поскольку способны обнаружить только известные вирусы. Не-
которым таким программам можно сообщить специальную последова-
тельность байт, характерную для какого-то вируса, и они смогут
обнаружить инфицированные им файлы - например, это умеет Notron
AntiVirus или 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. Усаживаем перед собой хозяина компьютера и подробно расспраши-
ваем его о событиях, предшествующих возникновению сбоев. Выяс-
нить нужно следующее. 

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

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

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

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

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

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

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



а) Идеально, если вирус (если это действительно он) самостоятель-
но извещает всех о своем присутствии, например, выводит на эк-
ран сообщение типа "I am VIRUS!". 

Вирусы проявляют себя различными способами: проигрывают ме-
лодии, выводят на экран посторонние картинки и надписи, имити-
руют аппаратные сбои, заставляя дрожать экран. Но, к сожалению,
чаще всего вирусы специально себя не обнаруживают. К антиви-
русным программам прилагаются каталоги с описаниями вирусов
(для AidsTest они хранятся в файле aidsvir.txt, для DrWeb -
в файле virlist.web). Наиболее полным является гипертекстовый
каталог avpve, входящий в состав антивирусного пакета Е. Каспер-
ского. В нем можно не только прочитать достаточно подробное
описание любого вируса, но и понаблюдать его проявления. 

От настоящих вирусов следует отличать так называемые "студен-
ческие шутки", особенно широко распространенные на компью-
терах ВУЗов и школ. Как правило, это резидентные программы,
которые периодически производят напоминающие работу виру-
сов видео- и аудиоэффекты. В отличие от настоящих вирусов,
эти программы не умеют размножаться. Наличие такого рода
программ на "бухгалтерских" компьютерах маловероятно. 

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

4. Не перегружая компьютер, запускаем (можно прямо с винчестера)
антивирус, лучше всего 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-сеансе. 

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

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

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



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

- дисковые кэш (SMARTDRV, NC_CASHE); 

- упаковщики дисков (DblSpace, DrvSpace, Stacker); 

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

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

а) Обнаружение загрузочного вируса. Загружаемся с чистой дискеты
и, запустив DiskEditor, заглядываем в сектор 0/0/1 винчестера.
Если винчестер разделен (при помощи fdisk) на логические диски,
то код занимает приблизительно половину сектора и начинается
с байт FAh 33h COh (вместо 33h иногда может быть 2Bh). Закан-
чиваться код должен текстовыми строками типа "Missing operating
system". В конце сектора размещаются внешне разрозненные бай-
ты таблицы разделов. Нужно обратить внимание на размещение
активного раздела в таблице разделов. Если операционная система
расположена на диске С, а активен 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 обеспечивает пошаговую трассировку кода,
команда г отображает текущее содержимое регистров. Чтобы ви-
зуально распознать наличие вируса по коду, конечно, необходим
определенный опыт. Вот на что надо обращать особое внимание: 



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

Start: 

call Metka
Metka: pop<r> 

- Наличие в начале файла строк типа "PkLite", "Ь291"или "diet"
подразумевает обработку программы соответствующим упаковщиком; 

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

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

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

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

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

а) Выделение загрузочного вируса. Как уже говорилось выше, если
вирус заразил винчестер, необходимо при помощи программы
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.com и test.exe. Вот их исходные тексты
на языке Assembler. 

test.com 

cseg segment 

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

org -lOOh
Start: 

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



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

mov ah,4Ch 

int 21h 

cseg ends 

End Start 

test.exe 

cseg segment 

assume cs:cseg, ds:cseg
Start: 

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

mov ah,4Ch 

int 21h 

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), четвертые - вообще во всех каталогах
винчестера. Поэтому воспользуемся программой типа it, чтобы
скопировать приманки во все каталоги диска (запускаем из кор-
невого каталога): 

rt copy a:\test.* . 



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

rt del test* 

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

rt dir test.* >test.txt 

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

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

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

1. Прежде чем перейти к рассмотрению этого вопроса, вспомним неко-
торые принципы функционирования MS DOS. 

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

СОМ-программа представляет собой часть кода и данных, которая
начинается с исполняемой команды и занимает не более 64Кбайт.
Например, такую структуру имеет командный процессор
COMMAND.СОМ операционной системы MSDOS до версии 6.22
включительно. 

Структура ЕХЕ-программы гораздо сложнее. В начале файла
ЕХЕ-программы располагается заголовок (см. приложение). Поля
ReloCS и ExelP определяют расположение точки входа в программу,
поля ExeSP и ReloSS - расположение стека, поля PartPag
и PageCnt - размер корневого сегмента программы. Размер некоторых 

6-1436 



программ, вычисленный по полям PartPag и PageCnt, может не со-
впадать с реальным размером файла. Такие программы называются
"сегментированными" или "содержащими внутренние оверлеи".
Опытные авторы вирусов избегают заражать такие программы. Пос-
ле заголовка может размещаться специальная таблица, точное место
расположения которой определяется полем TablOff, а размер - по-
лем ReloCnt. В этой таблице хранятся адреса тех слов в коде про-
граммы, которые модифицируются операционной системой во время
загрузки программы. Например, просматривая файл программы при
помощи утилиты HackerView, можно видеть команду call
0000:1234h. В процессе загрузки программы MS-DOS подставит вме-
сто нулей нужный сегментный адрес, и все будет работать коррект-
но. Кстати, если в поле TablOff указано число 40h или больше,
то, скорее всего, это программа в формате Windows. Подобный
формат имеет, например, командный процессор Windows 95
COMMAND.COM. Несмотря на свое расширение, он имеет в нача-
ле знаменитые символы "MZ" и длину 95Кбайт. 

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

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

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

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

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

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

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



Излечение пришло после использования антивирусов: 

DrWeb с: /сир /а1
и
AidsTest с: /f /g /q 

3. При помощи ранее описанных методов заразим две приманки: 

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 в командной строке в качестве параметра, то дизас-
семблер будет работать в соответствии с новыми инструкциями. Ана-
логичную операцию проделаем для файла testexe. 

б* 



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

- файлы увеличили свою длину на 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 байта), вирус получает возможность корректного
обращения к ячейкам памяти относительно кодового сегмента: 

mov cs:Data[si], xxxx. 

Не случайно 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 и ExelP, восстанавливает расположение
стека по сохраненным в data_18 и data_19 значениям полей ReloSS
и ExeSP и передает управление на ReloCS+ES+10h:ExeIP (ES -
сегмент PSP; ES+lOh - сегмент начала программы; 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. Еще несколько особенностей, с которыми иногда можно встретить-
ся при дизассемблировании кода вируса и изучении листинга. Код
вируса может быть зашифрован. В этом случае в начале вирусного
кода должен располагаться расшифровщик. Вообще говоря, рас-
шифровщиков может быть много, но первый всегда существует.
Если расшифровщик меняется от одного зараженного файла к дру-
гому, значит имеем дело с полиморфным вирусом. Вырожденный
случай - зашифровываются только сохраненные в теле вируса бай-
ты. Для СОМ-файла вполне достаточно пошагово пройти расшиф-
ровщик в отладчике, дождаться его завершения и сохранить на вин-
честер расшифрованный код вируса. Полученный файл можно
дизассемблировать. Для ЕХЕ-файла такое не подходит, так как в
памяти после загрузки отсутствует заголовок, и полученный файл
не может быть дизассемблирован именно как ЕХЕ. Вероятно, при-
дется писать специальную программу расшифровки на основе изу-
ченного по листингу алгоритма расшифровщика. 



Расшифровщик может быть совмещен с алгоритмами, противодей-
ствующими трассировке кода вируса с использованием отладчиков.
Ознакомиться с ними можно в специальной литературе, посвящен-
ной борьбе с НСК. Авторы вирусов, как правило, редко изобретают
что-то новое и используют широко известные методы. 

Эвристические анализаторы кода 

Эвристическим анализатором кода называется набор подпрограмм, ана-
лизирующих код исполняемых файлов, памяти или загрузочных секторов
для обнаружения в нем разных типов компьютерных вирусов. Рассмот-
рим универсальную схему такого кодоанализатора. Действуя в соответ-
ствии с этой схемой, кодоанализатор способен максимально эффективно
задействовать всю информацию, собранную для тестируемого объекта. 

Основные термины: 

Событие - это совокупность кода или вызов определенной функ-
ции операционной системы, направленные на преобразование сис-
темных данных, работу с файлами или часто используемые вирус-
ные конструкции. 

Цепочка связных событий - это набор событий, которые должны
быть выявлены в порядке их следования. 

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

Эвристическая маска - набор действий, выявленных при проверке
файла. 

Эвристическое число - порядковый номер первой из совпавших эв-
ристических масок. 

События распознаются при помощи подпрограмм выявления событий,
в которых могут использоваться также таблицы с данными. Остальные
данные просто хранятся в массивах и не анализируются. Рассмотрим
функциональную схему эвристического анализатора (рис. 6.1.). 

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

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 ];]++)
if(Events[MaskEvents[i][j]]==0) goto nextMask; 

" 

else
for(e=0,j=2;j<MaskEvents[i][1];j++) { 

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

goto nextMask; 

else e=Events[MaskEvents[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 nextMaskI; 

NumberHeurist=i+1; 

break; 

nextMaskI: 

} 

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

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

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

Блокировщик вируса 

Рассмотрим пример. В дисплейном классе ВУЗа эпидемия, часть машин
заражена неизвестным вирусом. До конца сессии - несколько дней,
выключение машин из учебного процесса смерти подобно (в первую 



очередь для обслуживающих класс сотрудников). Ситуация усугубляет-
ся тем, что студенты постоянно переносят программы на дискетах с од-
ной машины на другую. Как ограничить распространение эпидемии,
пока вирус не уничтожен? 

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

Разумеется, надо попытаться запустить блокировщик раньше всех ос-
тальных программ, например, в файле config.sys: 

install c:\util\stopsvc.com 

Но если вирус успел заразить command.com или стартует из загрузочно-
го сектора, то антивирус-блокировщик не поможет. 

Листинг программы, блокирующей распространение вируса SVC-1740: 

;; Резидентный блокировщик вируса SVC-1740
;; (с) К. Климентьев, Самара 1997
cseg segment 

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

org 100h 

Переходим к инициализации программы
Start: 

jmp Install 

;0бработчик прерывания INT 21 h .
lnt21: 

[Проверим номер функции, если 83h -
;то это запрос присутствия вируса 

cmp ah, 83h 

jnz Skip21 

;0тветим, что вирус присутствует
mov dx, 1990h 



;3апускаем оригинальный обработчик прерывания
Skip21: 

db OEAh ;Код команды JMP
Ofs21 dw ?
Seg21 dw ? 

Инициализируем программу
Install: 

.Проверим, не инсталлирована ли уже эта программа. Если
инсталлирована, выведем сообщение об этом и выйдем из программы.
;Вторую копию программы инсталлировать не имеет смысла 

mov ah,83h 

int 21 h 

cmp dx, 1990h 

jz Already 

.Считаем оригинальный вектор прерывания INT 21 h
mov ax,3521h
int 21h
mov Ofs21, bx
mov Seg21, es 

.Установим наш вектор прерывания INT 21h
mov ax, 2521h
mov dx.offset lnt21
int 21h 

[Выведем сообщение об успешной инсталляции программы в памяти
mov ah, 9 

mov dx, offset OkMes
int 21h 

.Выйдем из программы, оставив обработчик резидентным
mov dx, offset Install
int 27h 

;Выведем сообщение о том, что вирус
;или наша программа уже в памяти
Already: 

mov ah, 9 

mov dx, offset BadMes 



int 21 h
ret 

.Сообщения программы 

OkMes db "Yeah! STOPSVC installed now!",13,10 

db "(c) KostyaSoft, Samara 1997$"
BadMes db 7, "Perhaps, virus is in memory already. Sorry $"
cseg ends 

Пример антивируса 

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

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

В качестве языка программирования выбран С. Приоритетным призна-
но использование таких библиотечных процедур, форматы которых
идентичны во многих системах программирования. Поэтому, например,
использовалась процедура _dos_findfirst(), а не findfirst(). Программа
была написана и отлаживалась в системе, программирования JPI
TopSpeed С v3.01, а также была проверена на Borland C++ v3.1. Кроме
того, контролировалось наличие, идентичность по функциям и форма-
там вызова использованных библиотечных функций в системах про-
граммирования Microsoft C++ v6.0 и Watcom C++ vlO.0. Но если что-
то и не совпадет, откорректировать программу любому программисту не
составит труда. 

Основу программы составляет алгоритм обхода дерева каталогов и по-
иска в них файлов с расширениями "СОМ" и "ЕХЕ". 

В тот момент, когда обнаружен очередной потенциально зараженный
файл, вызывается функция infectedQ с именем файла в качестве пара-
метра. Задачей этой функции является проверка указанного файла на
заражение и возврат соответствующего признака. 



В случае положительного результата на заражение вызывается функция
cure(), которая и выполняет операцию исцеления зараженной программы. 

Если требуется написать программу для лечения для какого-либо другого
вируса, достаточно просто изменить содержимое процедур cure() и infectedQ. 

Итак, как же узнать, заражена программа или нет? В прошлых главах
это делалось чисто визуально, теперь же требуется определить формаль-
ные признаки зараженности. 

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

Разумеется, неправильно было бы использовать для детектирования
файла такие ненадежные признаки, как, например, 60 секунд во време-
ни создания файла. Во-первых, это может быть признаком случайного
изменения (например, при упаковке/распаковке некоторыми архивато-
рами). Во-вторых, слишком многие вирусы используют для самоопозна-
ния одинаковые признаки. Наконец, эти признаки могут принадлежать
совершенно здоровой программе (как в истории с антивирусом antitime
и сигнатурой MsDos). 

Вообще говоря, сигнатура - это множество N пар <Pi,Bi>, i=l.N, где
Pi - расположение i-го байта, Bi - значение i-го байта. Но на практике
часто используют непрерывные сигнатуры, для которых важно опреде-
лить только место расположения первого байта и длину сигнатуры. 

Какой должна быть длина сигнатуры? Вообще говоря, чем больше -
тем лучше, в идеале в сигнатуру должна входить вся неизменяемая
часть вируса, что гарантирует однозначность распознавания. Но это не-
вероятно увеличит объем антивируса (а известные программы лечат
тысячи вирусов) и замедлит процесс распознавания. Таким образом,
целесообразным следует считать количество от нескольких байт до не-
скольких десятков байт - не больше. Остановимся на цифре 6. 

Итак, в качестве сигнатуры вируса SVC-1740 выберем 6 байт вируса,
которые размещены начиная с 1724-го байта, если считать от конца за-
раженного файла (с 16-го байта вируса). Вполне возможно, что эти
6 байт совпадают для всех вирусов семейства SVC. Но вероятность
того, что машина сразу заражена несколькими вирусами одного семей-
ства, крайне мала. А вот выбор в качестве сигнатуры шести первых байт
вируса был бы точно ошибочным, потому что, как уже говорилось
выше, подобное начало характерно для очень большого числа вирусов. 



Итак, сигнатура OB4h 83h OCDh 21h 5Eh 56h длиной б байт расположена
начиная с 1724-го байта, если считать от конца зараженной программы. 

Теперь рассмотрим вопрос лечения программы. Фрагменты заражен-
ной программы, которые необходимо восстановить для излечения, оп-
ределены ранее. 

Напомним, что вирус SVC-1740, заражая программу, дописывается в ее
конец, сохраняя в своем теле первые 24 байта оригинальной программы.
Поэтому для излечения как ЕХЕ, так и СОМ-программ, вполне доста-
точно переписать сохраненные 24 байта в начало программы без учета
того, что большая их часть не была изменена, и отсечь 1740 вирусных
байт в конце зараженной программы. 

Но с методической точки зрения, следуя стратегии заражения, необхо-
димо в СОМ-программе восстановить только первые три байта,
а в ЕХЕ-програмее - 6 ранее измененных слов заголовка. 

Поэтому для функции cure() предусмотрен именно второй алгоритм
лечения, хотя он более медленный и сложный. 

Итак, для СОМ-файла считываем 3 байта, с 80-го по 78-й, если считать
от конца файла, и переписываем их в начало файла, для ЕХЕ-файла -
перемещаем 6 слов согласно таблице 6.1. и отсекаем последние
1740 байт. 

Таблица 6.1. Таблица перемещений для ЕХЕ-файла 

Источник, отсчет от
конца файла 

Приемник, отсчет от
начала файла 

78 

2 

76 

4 

66 

14 

64 

16 

60 

20 

58 

22 




Демонстрационный антивирус-фаг 

для вируса SVC-1740. 

"**"***************"**"**"*"*******"*"*"**^ 

#include <stdio.h>
^include <dos.h> 



^include <dir.h> 

^include <str.h> 

^include <process.h> 

^include <errno.h> 

^include <bios.h> 

^include <io.h> 

#include <fcntl.h> 

^define F_FOUND 0 

#define PATH_LEN 128
^define DRIVE_LEN 4
ftdefine BLANK_LEN 80 

#define BAD 1
^define GOOD 0 

#define DBG
char 

/* Строка имени текущего подкаталога */
path[PATH_LEN], 

/* Строка имени начального места расположения */
old_path[PATH_LEN], 

/* Строка имени требуемого устройства 7
drive[DRIVE_LEN], 

/* Пустая строка */
blank[BLANK_LEN]; 

int 

/* Количество отсканированных каталогов 7
n_dir, 

/* Количество исследованных файлов 7
nJil, 

/* Количество больных и исцеленных файлов 7
n_ill; 



int 

/* Длина имени файла */
I, 

/* Временный индекс */ 

' 1 

^include "antilib.c" 

/* Рекурсивная процедура обхода дерева каталогов */
walk() 

{
int found_d, found_f; 

struct find_t buf; 

/* Поиск каталогов */
found_d=_dos_findfirst("*.*",_A_SUBDIR ,&buf); 

while (found_d =- F_FOUND) 

{ 

if ((buf.name[0] != ".") && (buf.attrib & _A_SUBDIR )) 

{
chdir(buf.name); 

walk(); 

chdir(".."); 

}
found_d=_dos_findnext( &buf ); 

/* К этому моменту не отсканированных нижележащих каталогов
больше не осталось - сканируем файлы */ 

n_dir++; 

getcwd( path, PATH_LEN ); 

/* Поиск файлов */
^иг^^оз.Лг^ЛгзЦ^.^^А.МОРМА!- ,&buf); 

while (foundJ == F_FOUND) 

{
1=strlen( buf.name ); 

if (((buf.name[l-3]=="C")&&
(buf.name[l-2]=="0")&& 



(buf.name[l-1]=="M"))ll
((buf.name[l-3]=="E")&&
(buf.name[l-2]=="X")&&
(buf.name[l-1]=="E"))) 

(
n_fil++; 

printf("%c%s",13,blank); 

printf("%c%s\\%s ",13,path,buf.name); 

/* Нашли новый файл - надо проверить, инфицирован ли он.
Если заражен, то лечим 7 

if (infected(buf.name)==BAD) cure(buf.name); 

}
found_f=_dos_findnext( &buf ); 

}
} 

main( int argc, char *argv[] ) 

{
puts("ANTISVC - демонстрационный антивирус-фаг"); 

if (argc < 2)
{ р1Л8("Введите имя диска в качестве параметра"); exit(2); } 

if(((toupper(argv[1][0]))>"Z")ll((toupper(argv[1][0]))<"A"))
{ puts("HeBepHO задано имя диска"); exit(3); } 

drive[0]=argv[1][0]; drive[1 ]=":"; drive[3]="\0'; 

for (i=0;i<BLANK_LEN;i++) blank[i]=" ";blank[BI_ANK_LEN-1]="\0"; 

n_dir=0; n_fil=0; 

getcwd(old_path, PATHJ-EN); 

drive[2]="\0"; system(drive); 

drive[2]=^\"; chdir(drive); 

/* Запускаем рекурсивный обход дерева каталогов
для выбранного диска 7
walk(); 

old_path[2]="0"; system(old_path); 

old_path[2]='\\"; chdir(old_path); 



printf("\nKaTanoroB : %с1\пфайлов : %Ь\пОбнаружено больных
и излечено: %d", n_dir, n_fil, n_ill); 

if (nJII) exit(1); else exit(O); 

Файл "ANTILIB.C", включаемый в предыдущий: 

Процедуры обнаружения и лечения 

/* Сигнатура */
char sign[7]={ (char) OxB4, 

(char) 0х83, 

(char) OxCD, 

(char) 0х21, 

(char) Ox5E, 

(char) 0х56, 

"\0"); 

int infected( char *fn ) 

I
int f; 

int r,q; 

char buf[7]; /* Буфер под сигнатуру */ 

/* Открываем файл */
r=_dos_open( fn, 0_RDONLY, &f ); 

if (r) { printf(" - ошибка открытия!"); return GOOD; } 

/* Читаем 6 байт */
lseek( f, -1724, SEEK_END ); 

r=_dos_read( f, buf, 6, &q ); buf[6]="\0"; 

if ((r)ll(q!=6)) {printf(" - ошибка чтения!"); _dos_close(f); return GOOD; 

/* Закрываем файл */
_dos_close(f); 

/* Сравниваем байты с сигнатурой 7
if (strcmp( buf, sign)==0) 



( printf(" - был болен и..."); n_ill++; return BAD; } /* Болен !!! */ 

/* Годен к в/службе. П/пк мед. службы Орлов :-) */
return GOOD; 

cure( char *fn ) 

i
int f; 

int mz; 

int r,q; 

char buf[24]; /* Буфер под байты */ 

/* Открываем файл */
r=_dos_open( fn, 0_RDWR, &f ); 

if (r) { printf(" - ошибка открытия!"); return; } 

/* Читаем первые два байта для определения типа программы */
r=_dos_read( f, &mz, 2, &q ); 

if ((r)ll(q!=2)) {printf(" - ошибка чтения!"); _dos_close(f); return; } 

/* Читаем сохраненные вирусом 24 байта старого начала */
lseek( f, -80, SEEK_END ); 

r=_dos_read( f, buf, 24, &q ); 

if ((r)ll(q!=24)) (printf(" - ошибка чтения!"); _dos_close(f); return; } 

/* Определяем тип программы 7
if ((mz==Ox4D5A)ll(mz==Ox5A4D))
{ /* Это ехе 7 

/* Пишем правильные PartPag и PageCnt 7
lseek( f, 2, SEEK_SET ); 

r=_dos_write( f, &buf[2], 4, &q ); 

if ((r)ll(q!=4)) {printf(" - ошибка записи!"); _dos_close(f); return; } 

/* Пишем правильные ReloSS и ExeSP 7
lseek( f, 14, SEEK_SET ); 

r=_dos_write( f, &buf[14], 4, &q ); 

if ((r)ll(q!=4)) {printf(" - ошибка записи!"); _dos_close(f); return; } 



/* Пишем правильные ReloCS и ExelP */
lseek( f, 20, SEEK_SET ); 

r=_dos_write( f, &buf[20], 4, &q ); 

if ((r)ll(q!=4)) {printf(" - ошибка записи!"); _dos_close(f); return; } 

) 

else
( /* Это corn */ 

/* Восстанавливаем сохраненные З первые байта программы */
lseek( f, О, SEEK.SET); 

r=_dos_write( f, &buf[0], 3, &q ); 

if ((r)ll(q!=3)) {printf(" - ошибка записи!"); _dos_close(f); return; } 

/* Усекаем файл (переходим на начало вируса
и записываем 0 байт) */
lseek( f, -1740, SEEK_END); 

r=_dos_write( f, buf, 0, &q); 

/* Закрываем файл 7
_dos_close(f); 

printf("Tenepb исцелен !\п"); 

return; 

}