ПОЛИМОРФИЗМ: ЧТО ДАЛЬШЕ

Вирус -- независящая от пользователя программа, направленная на самораспространение.

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

Под способностью к самораспространению(направленностью на самораспространение) будем понимать присутствие(и использование) в вирусе специально написанных функций для распространения [копий] вируса.

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

Под полиморфизмом вируса понимается существование одного вируса в нескольких формах. Это свойство мы далее и рассмотрим.

Итак, изменение формы вируса возможно на тех уровнях информации, с позиции которых можно рассматривать(различать) любые компьютерные программы, а именно:

  1. На уровне байт, составляющих тело вируса.
  2. На уровне команд(опкодов), составляющих тело вируса.
  3. На уровне функциональных вызовов(действий) вируса.
  4. На уровне алгоритма вируса.

Уровень 1

Наиболее простой уровень полиморфизма, существует в двух проявлениях:

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

Детектирование таких вирусов может достигаться:

Уровень 2

"Пермутирующие", они же "метаморфные" вирусы.

Идея заключается в том, чтобы изменять команды/группы команд на функционально им эквивалентные(замена), и/или менять команды/группы команд местами(перестановка).

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

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

О реализации.

Здесь пока есть два основных подхода к технологии мутирования вируса:

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

Кстати, здесь существует интересная проблема о степени зашифрованности этого самого прообраза и соответственно возможности его детектирования.

Уровень 3

Назовем их функционально мутирующие вирусы.

Такой уровень на практике пока еще не был реализован.

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

Дело в том, что при эмуляции/трассировке вируса, его функциональные вызовы могут быть закодированы например так:

mov   ah, 4Eh      ; найти файл
int   21h          ; вызов: 21 4E
jc    ...
call  infect_file
...
infect_file:
...
mov   ah, 3Dh      ; открыть файл
int   21h          ; вызов: 21 3D
...
mov   ah, 40h      ; записать в файл
int   21h          ; вызов: 21 40
...

функциональна сигнатура: 21 4E 21 3D 21 40

Очевидно, что прерывания/процедуры api, которые вызываются вирусом, представляют неплохую информацию для его детектирования.

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

Уровень 4

Пожалуй самый сложный уровень, единственный за который не следует браться ;-)

Назовем их алгоритмически мутирующие вирусы.

Алгоритм работы программы (вместе с результатом ее работы), есть, наверное, самый высокий уровень информации о программе.

И как бы мы ни извращались на уровнях команд и функциональных вызовов, все равно файл с расширением .EXE и внутренним форматом PE будет найден, открыт, и в него произойдет запись. Либо нечто в этом роде.

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

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

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

Общие рекомендации

В глобальном смысле, я сегодня вижу такую ситуацию:

Вылечить можно отнюдь не все вирусы, достигается это технологиями Seek&Destroy(вставка ошибок в случайные места программы и обработка их вирусом), UEP (Unknown Entry Point) и прочими гадостями.

В частности, есть вот такая интересная техника заражения:

Выбирается точка в теле программы, в которую будет записан переход на вирус.
В случае нормального вируса, это просто точка входа (entrypoint) программы.
В случае хорошего вируса, это случайно выбранная точка программы. (UEP)
Если вирус еще более правильный, то переход произойдет на полиморфный расшифровщик.
А вот если вирус из этой самой точки _заберет_ с десяток инструкций, а потом либо размешает их в полиморфном декрипторе, либо сохранит в себе (с последующим восстановлением, понятно) -- то это совсем правильно.

А вот детектировать можно любой (или почти любой ;-) вирус, вопрос только КОГДА.

Здесь есть несколько параллельных временных стадий.

  1. Фаза распространения (вирус идет от пользователя к пользователю, и через некоторое время попадает в антивирусную контору)
  2. Фаза создания антивируса (контора пишет антивирус)
  3. Фаза лечения (антивирус идет из конторы к пользователю, и, в последный момент, вирус просекает что больше не судьба и накернивает "...ЭВМ, систему ЭВМ или их сеть...")

Длительность всех трех стадий некоторым образом связана с такими "качествами" вируса, как:

  1. маскировка (позднее поймают)
  2. сложность (дольше будут писать антивирус)
  3. защита (сводит антивирус на нет)

Здесь следует сказать пару слов о деструкции. Так вот деструкция, несомненно, нужна. ;-) Но в меру. Например всякая рандомная деструкция снижает маскировку, зато "умная" деструкция (типа пришел новый антивирус или юзер пишет письмо к аверам) усиляет защиту и усложняет лечение.

Также можно хранить вирус в нескольких файлах, но это может сильно затруднить распространение.

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

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

Можно при ситуации "антивир хочет нас вылечить" совершать убийство (ритуальное) пользователя вместе с компьютером.

В заключение...

...не надо ;-)