Количество: Количество пользователей
Инфицировано: Количество пользователей, которым был передан
вирус.
Время: Время (в минутах) от начала сеанса до момента
передачи инфекции.
Основную опасность Коэн видит в "разделении", т.е. в
том, что несколько пользователей имеют совместный доступ к
одним и тем же данным. Он сделал вывод:
Там, где есть путь от А к В и от В к С, там есть и
путь от А к С.
Отсюда следует логичный вывод, что распространение ви-
руса можно остановит при помощи изоляции. Различные подходы
к решению, основанные на модели целостности и на модели Бел
-ля Падула (Bell-La Padula), а также протоколирование пере-
мещения данных не дают удовлетворительных результатов. По
крайней мере, в тех случаях, когда необходим быстрый и ин-
тенсивный обмен данными.
Если нельзя предотвратить инфицирование, значит следу-
ет искать стратегии распознавания вирусов. Коэн пытался
обосновать невозможность целенаправленной стратегии поиска
на примере программы, которую можно назвать логическим ко-
лебательным контуром.Эта программа выглядит следующим обра-
зом:
program contradictory_virus:=
{ 12345678;
subroutine infect_executable:=
- 34 -
{ loop:file = get_random_executable_file;
if first_line_of_file = 12345678 then goto loop;
prepend virus to file;}
subroutine do_damage:=
{ whatever damage is to be done}
subroutine trigger_pulled:=
{ return true if some condition holds}
main program:=
{ if not D(contradictory_virus) then
{ infect_executable;
if trigger_pulled then do_damage;
goto next;}}
next:}
Причем "D" должна представлять собой подпрограмму, ко-
торая решает, является ее аргумент программой-вирусом,
т.е.: D(x) ИСТИННО, если х является вирусом. D( x) ЛОЖНО,
если х не является вирусом. Таким образом, при отрицатель-
ном результате инициируется заражение ( внесение инфекции),
при положительном результате - нет.
Так как резкие нападки автора на практику аргументации
Коэна вызвали появление некоторых критических статей с уп-
реками, такая аргументация должна быть научно обоснованной,
и по этому приведенная выше программа-вирус Коэна должна
быть рассмотрена более подробно. Так как речь идет о псев-
доязыке программирования, эту программу можно сразу описать
на общепринятом языке.
( Программы "do_damage" и "trigger_pulled" для после-
дующего рассмотрения не важны, они опускаются.)
программа вируса противоречивости:=
{ 12345678;
подпрограмма инфицирования:=
{ цикл:файл = поиск_какой-либо_программы;
- 35 -
если первая_строка_Ды = 12345678 то переход на цикл;
запись_вируса_перед_файлом;}
основная программа:=
{ если не D(противоречие) то
инфицировать;
если инициировано то повредить;
перейти на дальше;}
дальше:}
Эту логику можно использовать и для других целей. Так,
можно составить программу такого типа на тему истории о де-
ревенском брадобрее, который бреет только тех, кто не умеет
бриться сам.
(Между прочим: Бреется ли сам брадобрей, или, может ли
он бриться?)
программа брадобрей:=
подпрограмма бритье:=
{ цикл: файл = поиск_какого-либо_мужчины;
если мужчина = безбородый то переход на цикл;
бритье_мужчины;}
основная программа:=
{ если не D( брадобрей) то
бритье;
перейти на дальше
дальше:}
Причем "D" представляет собой подпрограмму, которая
решает, является ли ее аргумент брадобреем. Т.е.: D(х) ИС-
ТИННО, если х брадобрей. D( х) ЛОЖНО, если х не брадобрей.
Таким образом приведено доказательство того, что нельзя ре-
шить, является ли произвольный мужчина брадобреем или нет.
Об этом можно судить только в том случае, если этого
мужчину кто-то побрил.
Ошибка заключается в том, что свойство объекта, кото-
рое можно обнаружить только после выполнения действия, сна-
- 36 -
чала распознается, и на основании этого определяется вход-
ной критерий проверки этого объекта.
Логично: Работодатель не нанимает нового сотрудника,
если знает, что тот лентяй. Если бы существовал тест на
лень, то предтендент мог бы испробовать этот тест на себе и
работать до тех пор, пока тест не покажет положительный ре-
зультат.
Возникает противоречие. Не говоря уже о том, что нель-
зя написать подпрограмму, которая надежно распознает, явля-
ется ли некоторая программа вирусом - по крайней мере, за
приемлимое время -, приведенную выше распечаку можно еще
изменить, не меняя логики программы:
Старт:
Проверить, является ли А вирусом.
ЕслиА является вирусом, взять у А свойство вируса.
Если А не является вирусом, дать А свойство вируса.
Еще раз то же самое для любителей Бейсика:
10 if a=3 then a=5
20 if a=5 then a=3
30 goto 10
Являются ли такого типа программы содержательными,
каждый читатель может судить сам.
В следующей программе из работы Коэна речь идет об
"эволюционирующем вирусе", т.е. о вирусе с изменяющейся
формой проявления:
program evolutionary_virus:=
{12345678;
subroutine infect_executable:=
{loop: file = get_random_executable_file;
if first_line_of_file = 12345678 then goto loop;
prepend virus to file;}
subroutine do_damage:=
{whatever damage is to be done}
subroutine trigger_pulled:=
- 37 -
{return true if some condition holds}
subroutine print_random_statement:=
{print random_variable_name,=,random_variable_name;
loop: if random_bit = 0 then
{print random_operator,random_variable_name;
goto loop}
print semicolon;}
subroutine copy_virus_with_random_insertations:=
{loop: copy_evolutionary_virus to virus till
semicolon_found;
if random_bit = 1 then print_random_statement;
if not end_of_input_file goto loop;}
main program:=
{ copy_virus_with_random_insertations;
infect_executable;
if trigger_pulled then do_damage;
goto next;}
next:}
Таким образом, возникают вирусы, которые имеют одина-
ковые функции, но по-разному выглядят. Коэн не смог дока-
зать, что нельзя распознать вирус на основе процедур срав-
нения. Он использовал для этого программу - последнюю в
этой работе -, основанную на том же - бессмысленном - веде-
нии доказательства, что и показанный выше вирус противоре-
чивости:
program undecidable_evolutionary_virus:=
{12345678;
subroutine infect_executable:=
{loop:file = get_random_executable_file;
if first_line_of_file = 12345678 then goto loop;
prepend virus to file;}
- 38 -
subroutine do_damage:=
{whatever damage is to be done}
subroutine trigger_pulled:=
{ return true if some condition holds}
subroutine copy_with_undecidable_assertion to file till
line_starts_with_zzz;
if file=P1 then print "if D(P1,P2) then print 1;"
if file=P2 then "if D(P1,P2) then print 0;"
copy undecidable_evolutionary_virus to file till
end_of_input_file;}
main program:=
{if random_bit=0 then file=P1 otherwise file=P2;
{copy_with_undecidable_assertion;
zzz:
infect_executable;
if trigger_pulled then do_damage;
goto next;}
next:}
При этом D представляет собой процедуру сравнения, ко-
торая сравнивает два своих аргумента. Смысл этой программы
можно было бы представить следующим образом:
СТАРТ:
Проверить два предмета на совпадение; если они одина-
ковы, сделать их неодинаковыми.
Проверить два предмета на несовпадение; если они нео-
динаковы, сделать их одинаковыми.
Перейти на СТАРТ.
Несмотря на проблемы, возникающие при обнаружении ви-
русов, Коэн сделал вывод, что вирус можно идентифицировать,
если известен его идентификатор. В этом случае для обнару-
жения инфекции в подозрительных программах следует искать
лишь этот идентификатор. Коэн также совершенно верно опре-
делил, что путем введения в программу идентификатора вируса
- 39 -
можно сделать ее защищенной от действия этого вируса; в
этом случае вирус поведет себя так, как будто программа уже
инфицирована. Новое заражение в этом случае было бы невоз-
можным. Дополнительную информацию о возможностях защиты при
помощи идентификаторов вирусов Вы найдете в разделе 15.3.
Коэн поставил еще один интересный вопрос: какова веро-
ятность того, что программа-вирус возникнет случайно?
Коэн считает, что при благоприятных условиях ( длина
вируса 1000 битов, 50-процентное задание) 500!/1000**500.
Прав ли он и какова действительно потенциальная опас-
ность, Вы узнаете в разделе 13.3.
В конце Коэн приходит к выводу, что существующие сис-
темы не предоставляют достаточных возможностей для защиты
от вирусов. Предстоит еще очень много сделать...
Вывод: Работа Коэна не внесла той ясности, которая
ожидалась.Все же его работа полезна тем, что он помог осоз-
нать возникшую опасность, а также обратил внимание на тема-
тику и связанные с ней проблемы.
2.2 Другие исследования
ДДДДДДДДДДДДДДДДДДДДДДДД
В первую очередь здесь следует рассмотреть работу спе-
циалиста по информатике из Дортмундского университета Дж.
Крауса "Самовоспроизводящееся программное обеспечение". Эта
работа Крауса интересна не только тем, что здесь определено
самовоспроизведение программного обеспечения и приведены ас-
семблерные распечатки на реально существующем языке програм-
мирования - ВАссемблере фирмы Сименс, - но и указанны парал-
лели между органическими и компьютерными вирусами. При этом
не следует забывать, что эта работа появилась примерно за
четыре года до публикации Коэна. Так как получить экземпляр
этой работы весьма сложно, автор обратился к работе Крауса
1981 года с тем же названием.
О содержании
ДДДДДДДДДДДДД
Один из интереснейших пунктов этой работы до сих пор
нигде не обсуждался. Краус уже во введении начал с того,
о чем одни уже много лет мечтали, а другие думали с пани-
- 40 -
ческим страхом: о "жизни" на уровне вычислительной системы.
Краус поясняет взаимосвязь между жизнью и сложностью окру-
жающей среды и приходит к выводу:
"Если верно представление о том, что возникновение или
существование жизни является следствием сложности, то спе-
кулятивным является предположение даже о возможности жизни
на уровне ЭВМ".
Он признает воспроизводство и мутацию необходимыми для
возникновения жизни и приходит к выводу, что самовоспроиз-
водящиеся программы весьма плодотворны в этом смысле. Само-
модификация - т.е. мутация - определяется обычной частотой
ошибок в вычислительной системе. Он делает вывод:
"Так как электронные вычислительные системы не обеспе-
чивают 100-процентное отсутствие ошибок, всегда существует
возможность неверного вывода текста программы, т.е. мута-
ции. Таким образом, самовоспроизводящаяся программа не мо-
жет считаться носителем жизни на уровне ЭВМ".
Более подробно тема "Жизнь" на уровне ЭВМ будет обсуж-
даться в разделе 16.4.
Краус видит существенное различие между программами,
написанными на ассемблере, и на языках программирования вы-
сокого уровня:
"Ассемблерные программы могут адресовать и читать об-
ласть памяти, в которой они находятся. Поэтому они в состо-
янии копировать свои собственные коды в рабочей памяти, а
следовательно, самовоспроизводиться. Программы на языках