ZF

                  ОБНАРУЖЕНИЕ И РАСПОЗНАВАНИЕ ВИРУСОВ
                               by DrMAD

    Введение
    1.  Сигнатуры
    1.1. Важное предварительное замечание
    1.2. Обобщенные сигнатуры
    1.3. Простые сигнатуры
    1.4. Прерывистые сигнатуры ("маски")
    1.5. Сигнатуры для "обычных" полиморфиков
    1.6. Сигнатуры для "фуллморфных" вирусов
    2.  Контрольные коды
    2.1. Контрольная сумма
    2.2. Циклические избыточные коды
    2.3. Другие контольные коды
    2.4. "Правильное" использование сигнатур и контрольных кодов
    3.  Эвристические методы
    3.1. Логические методы
    3.2. Методы распознавания образов
    Заключение

                               ВВЕДЕНИЕ

    Надеюсь, эта статья будет полезна тем,  кто хочет представить себе,
как  антивирусы  находят  и  распознают  заразу.  Для  понимания текста
необходимо знание математики в объеме 3-го  класса  общеобразовательной
школы. J

                             1. СИГНАТУРЫ

    Это -  классический  способ,  позволяющий обнаруживать и однозначно
распознавать большинство _известных_ вирусов.
    В строгом   смысле   слова,   сигнатура   это  -  уникальный  набор
характеристик, однозначно характеризующих некий объект (в данном случае
- вирус). В переводе это слово означает "подпись".
    Понятно, что  этот  набор  характеристик  заведомо  МЕНЬШЕ  полного
количества характеристик,  присущих объекту.  Например,  мы при встрече
распознаем своего друга  (подругу)  по  довольно  ограниченному  набору
параметров, таких как форма лица, цвет глаз и т.п., нагло игнорируя при
этом наличие какой-нибудь там родинки на каких-нибудь  ягодицах. Иногда
(например, при встрече с близнецами) это может привести к обознатушкам.
    С этой точки зрения  сигнатура  -  это  вариант  хеш-функции,  т.е.
НЕОДНОЗНАЧНОГО  отображения  большого  множества  объектов на маленькое
множество комбинаций их признаков.

    1.1. ВАЖНОЕ ПРЕДВАРИТЕЛЬНОЕ ЗАМЕЧАНИЕ

    Мы обычно доверяем  документу,  если  под  ним  присутствует  некая
закорючка,  но  эта закорючка - еще не вся сигнатура.  Представим себе,
что в точности такая же закорючка отпечатана в конце листа  на лазерном
принтере.  Или  высечена зубилом на камне.  Будем ли мы доверять такому
документу?  Конечно, нет. Мы будем доверять только той подписи, которая
представляет  собой  набор чернильных пятен на листе бумаги,  причем на
этой бумаге должно быть воможно различить  уникальные  для  конкретного
человека вмятины и бороздки, проделанные пером или шариком ручки.
    Точно так  же  дело  обстоит  и  с   вирусами.   Например,   байты,
характерные для ЗАГРУЗОЧНОГО вируса,  и найденные внутри EXE-программы,
НЕ  ОЗНАЧАЮТ  зараженности  этой  программы.  Т.е.  в  полное   понятие
"сигнатуры"   входят   еще   такие  косвенные  характерстики,  как  тип
проверяемого объекта,  местоположение этого объекта и некоторые  другие
параметры.  Просто  обычно  на  практике они "выносятся за скобки",  но
полностью игнорировать их ни в  коем  случае  нельзя.  Иначе  получится
такая  же ерунда,  что когда-то произошло при попытке одного антивируса
(MSAV) искать загрузочные (!!!) вирусы в программном теле (!!!) другого
антивируса (AIDSTEST).
    Наборы "косвенных"  признаков (тип файла,  размер,  время создания,
взаимное  расположение  различных  частей  программы  и  т.п.)   иногда
называют "слабыми сигнатурами".

    1.2. ОБОБЩЕННЫЕ СИГНАТУРЫ

    В современных антивирусах под сигнатурой понимается множество троек

                         {<ЧТО, ГДЕ, КОГДА>}.

    "Что" - это значение байта, или слова, или любого другого фрагмента
кода;
    "Где" - это местоположение этого фрагмента внутри программы;
    "Когда" -  это  номер  шага  работы  программы,  на  котором данный
фрагмент находится в данном месте.
    Сигнатура должны  быть  уникальной  и характерной для вируса,  т.е.
такой,  чтобы сравнив ее с фрагментами программы, можно было однозначно
сказать: это конкретный вирус или нет.
    Рассмотрим частные случаи сигнатур.

    1.3. ПРОСТЫЕ СИГНАТУРЫ

    Для большинства   вирусов   вид   сигнатуры   очень   прост:    это
последовательность  расположенных  друг  за  другом байтов плюс адрес в
файле для  начала  этой  последовательности.  (Еще,  разумеется,  нужна
длина,  если  для  разных  вирусов используются разновеликие сигнатуры)
Например,  для  вируса  Win95.CIH  можно  построить  такую   сигнатуру,
начинающуюся с 0-го байта: 55 8D 44 24 F8 33 DB 64.
    Какой длины  должна  быть сигнатура?  Вообще-то,  чем длинней,  тем
лучше,  в идеале - в нее должны входить вся неизменяемая часть  вируса.
Но  предположив среднюю длину типичного вируса 1Кб и количество записей
в антивирусной базе 50000,  получим 50 Мб только для хранения сигнатур.
Накладно-с...  Поэтому  нужен  разумный  компромисс.  Предположим,  что
"нормальная"  длина  сигнатуры  -  44  байта.  Естественно,  это  число
"нормально" только для вирусов,  чье тело было длинней 44 байтов, а для
прочих  вирусов  приходилось  использовать  более  короткие  сигнатуры;
отсюда один из главных недостатков сигнатур - переменность их длины.
    Но тогда встает проблема - в каком месте вируса выбирать сигнатуру?
Например, рассмотренная выше сигнатура одинакова для вирусов Win95.CIH.
A,  B и С.  Значит, нужно выбирать непрерывную сигнатуру в таком месте,
где  эти  версии  различаются  (а  различаются  они  где-то  в середине
вирусного тела,  всего в нескольких командах,  обрабатывающих заражение
самораскручивающихся   ZIP-ов).   Это   можно  сделать  самостоятельно,
тщательно изучив коды вирусов,  но когда этих вирусов десятки,  сотни и
тысячи, такой поход неприемлим.

    1.4. "ПРЕРЫВИСТЫЕ" СИГНАТУРЫ ("МАСКИ")

    Избежать указанного  выше  недостатка  можно,  введя  "прерывистые"
сигнатуры, состоящие из отдельных кусочков. В этом случае сигнатуры для
вирусов семейства Win95.CIH будут состоять из двух частей:  1) из общей
для всех вирусов семейства;  2)  и  из  уникальной  для  каждой  версии
вируса.
    Также можно использовать разновидность  "прерывистых"  сигнатур  не
только на уровне байтов,  но и на уровне отдельных частей байтов,  т.е.
битовых полей.  Это удобно для  распознавания  "олигоморфных"  вирусов,
т.е.    вирусов   с   частичной   полиморфностью.   Вот   пример   двух
"олигоморфных" расшифровщиков:

    ; Первый вариант
    00: B90010   mov    cx, 1000 ; Длина зашифрованной части
    03: BE1201   mov    si, 0112 ; Начало зашифрованной части
    06: 3E       ds:
    07: 81343412 xor    [si], 1234 ; Шифрация случайным ключом
    0B: 83C602   add    si, 02
    0E: 83E901   sub    cx, 1
    11: 75F4     jne    00000006

    ; Второй вариант
    00: B80010   mov    ax,1000 ; Длина зашифрованной части
    03: BB1201   mov    bx,0112 ; Начало зашифрованной части
    06: 26       es:
    07: 81072143 add    [bx]4321 ; Шифрация случайным ключом
    0B: 83C302   add    bx, 02
    0E: 2D0100   sub    ax, 1
    11: 75F4     jne    00000006

    В сигнатуру  для  распознавания этого вируса можно внести следующие
пары (позиция,значение):  (1,00),  (2,10h),  (4,12h),  (5, 1), (7,81h),
(0Bh, 83h), (11h,75h), и т.п.
    А можно  для  надежности  использовать даже части отдельных байтов.
Разумеется,  для этого  надо  знать  структуру  отдельных  процессорных
команд. Например, вторая команда вируса вида

    MOV РЕГИСТР, ЧИСЛО

    на самом деле имеет битовый формат

    1011 0RRR NNNNNNNNNNNNNNNN,

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

    if ( (Byte & 0xF8) == 0xB0 )...

    1.5. СИГНАТУРЫ ДЛЯ "ОБЫЧНЫХ" ПОЛИМОРФИКОВ

    Полиморфики -   это  вирусы,  для  которых  невозможно  найти  даже
сигнатуру-"маску". Тем не менее, использовать механизм сигнатур для них
возможно.  Дело в том,  что в процессе работы вирус расшифровывает свою
тушку,  и после этого уже она содержится в памяти в неизменяемом  виде.
То-есть,  к сигнатуре надо добавить компонент "КОГДА" - на каком шаге в
памяти оказывается расшифрованная тушка.
    Например, для     рассмотренных    выше    случайных    8-командных
расшифровщиков 1000-байтовой тушки  раздевание  этой  тушки  закончится
через 8*1000=8000 шагов.
    Даже если  вирус  использует  прием "бегущей" волны (расшифровывает
код впереди исполняемого фрагмента  и  зашифровывает  уже  выполненнные
фрагменты),   то   можно   использовать   "прерывистую"   сигнатуру   с
прерывистостью не только в пространстве, но и во времени.
    Шаги можно считать по разному.  Можно выполнять вирус  в  пошаговом
режиме.
    Вкратце, для DOS-а это делается примерно так:
    - освобождается побольше памяти при помощи Int21h/ah=4Ah;
    - в эту память грузится трассируемая программа при помощи Int21/ah=
4B01h,  (другой вариант - создать PSP при помощи Int21/ah=26h и грузить
программу самостоятельно, настраивая fixup-ы ручками);
    - ставится   собственный   обработчик   Int1,   он  будет  получать
управление после каждой выполненной в программе команды;
    - выставляется  в  регистре  флагов  бит  T  (например,  так:  push
303h/popf);
    - ну  и  в  обработчике  Int1  выполняются  все  желаемые  действия
(минимально - просто считаются шаги, ну а на самом деле там очень много
чего должно делаться,  например, анализироваться исполняемый код, чтобы
не плюхнуться в антиотладочную лужу).
    Возможно нечто подобное и в Windows:
    - трассируемая программа запускается  при  помощи  CreateProcess  с
параметром DEBUG_ONLY_THIS_PROCESS;
    - при помощи  GetContext  берется  ее  контекст  и  в  поле  флагов
выставляется бит Т;
    - организуется цикл ожидания и  обработки  событий  в  трассируемой
программе, примерно вот такой:

    while (WaitForDebugEvent(...)==TRUE) // Дождаться события
     {
      ...
      ContinueDebugEvent(...); // Продолжить трассировку
     }

    - в  этом цикле ловятся события:  сначала одно CREAT_PROCESS_DEBUG_
EVENT=0 , а потом много EXCEPTION_DEBUG_EVENT=1;
    - поймав  событие,  инкрементируется  количество шагов и при помощи
ReadFromMemory читается код выполненной команды.
    А можно  и  полностью  эмулировать  всю работу программы,  выполняя
команды   "понарошку".   (Для   _любительского_    вируса    аппаратный
трассировщик даже предпочтительней эмулирующего.  Ибо можно жизнь убить
только на отладку эмулятора,  и так и не увидеть в итоге  специфических
фенечек, возникающих при _распознавании_ вирусов).
    Все это относится и к  полиморфным  макровирусам,  хотя  аппаратная
пошаговая трассировка для них невозможна, остается только эмуляция.
    Впрочем, эта интересная и сложная  тема  -  для  отдельной  большой
статьи.

    1.6. СИГНАТУРЫ ДЛЯ ФУЛЛМОРФНЫХ ВИРУСОВ

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

    ; Первый вариант
        jmp m1
    m3: add sp, 2
        int 21h
        jmp m4
    m2: mov dx, offset Mess
        call m3
    m1: nop
        mov ah,9
        jmp m2
    m4: ...


    ; Второй вариант
        call m1
    m2: cli
        mov dx, offset Mess
        sti
        jmp m3
    m3: int 21h
        jmp m4
    m1: add sp, 2
        mov ah, 9
        jmp m2
    m4: ...

    Нетрудно видеть,  что  сигнатура  все-таки   есть.   Она   образует
"хребет" вируса.  Определяется  она так:  команды (с учетом переходов!)
поочередно  выполняются  (или  эмулируются),  мусор  типа   nop/cli/sti
пропускается, а на "шампур" нанизываются только значимые команды

        mov ah,9
        mov dx, offset Mess
        int 21h

    которые и  образуют  в конечном итоге сигнатуру.  Вот если бы такие
вирусы позаимствовали у обычных полиморфиков прием эквивалентной замены
значимых  команд,  например,  mov  ah,9  на  push 9/pop ax...  Но таких
вирусов пока,  насколько я в курсе,  еще не существует. (Есть отдельные
попытки,  в результате их рождаются, например, вирусы семейства VCG, но
и эти козявки оставляют внутри себя  в  зашифрованном  виде  постоянные
таблицы замен, и поэтому тоже не являются настоящими фуллморфиками).
    Еще один  вариант  "фулморфиков"  -  это  всяческие   там   "random
push"-технологии,  т.е.  попытки  представить  вирус  в  виде огромного
количества PUSH-ей и/или MOV-ов,  которые потихоньку формируют где-то в
памяти истинный  образ  вируса.  Если  пройти  всю  цепочку формирующих
команд в эмуляторе,  то рано или поздно образуется статичная сигнатура.
Больше антивирусу ничего уже и не нужно.

    2. КОНТРОЛЬНЫЕ КОДЫ

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

    2.1. КОНТРОЛЬНАЯ СУММА

    Простейший вид  контрольного  кода  -  сумма всех байтов (или слов)
фрагмента данных (вирусного кода).  Например,  если первые байты вируса
Win95.CIH равны 55 8D 44 24 F8 33 DB 64, то их сумма составляет 3B4h, и
это число можно было бы использовать для  поиска  программ,  зараженных
этим вирусом.
    Но это было бы очень неудачным решением проблемы. Во-первых, крайне
просто подобрать  какую-нибудь  другую последовательность из 8 байтов с
такой же суммой.  Во-вторых,  если переставить местами любые два байта,
то значение суммы не изменится.
    Есть варианты, несильно усложняющие алгоритм расчета, но улучшающие
качество контрольного суммирования,  например,  для _текстовых_  данных
неплохо работают контрольные суммы вида:

    sum := sum*A + s[i]

      или, что чаще:

    sum := (sum*A + S[i]) mod N, где N - разрядность.

    Крис Касперски в "Технике и  философии  хакерских  атак"  заклеймил
этот   алгоритм   позором,  но  в  в  книжке  Кернигана  и  Ричи  "Язык
программирования с++" отмечается,  что этот алгоритм  можно  с  успехом
использовать при A=31 _для_коротких_текстовых_ данных (отдельных слов и
приложений в тексте, для данных в базах формата .DBF и пр).
    Поэтому контрольные суммы подобного рода  используются  только  для
очень простых  и  неответственных проверок,  например,  для определения
целостности кода BIOS. Для поиска вирусов их использовать нельзя.

    2.2. ЦИКЛИЧЕСКИЕ ИЗБЫТОЧНЫЕ КОДЫ

    CRC - это циклический  избыточный  код.  В  5-м  выпуске  "Земского
Фершала" на эту тему есть очень хорошая статья by Sassa, поэтому идею и
подробности использования данного метода ищите там.
    Кратко упомянем,  что  смысл  CRC  -  в  делении длинного двоичного
многочлена,  полученого  из  исходных  данных,  на  другой   (тщательно
выбранный!) двоичный многочлен,  и в фиксировании остатка. Этот остаток
- и есть искомый контрольный код.
    Многочлены-делители нельзя  брать  от  балды.  Имеются  СТАНДАРТНЫЕ
многочлены-делители,  это CRC-16 (A001h или 8005h) и CRC-32  (0DB88320h
или 04C11DB7h).   Доказано,   что   именно   они   обладают   наилучшей
распознаваемостью уникальности.
    Вероятно, в      антивирусах       используются       НЕСТАНДАРТНЫЕ
многочлены-делители,  выбранные,  тем  не  менее,  не  от  балды,  а  в
соответствии с определенными правилами.  Поэтому они обладают  примерно
такими  же  свойствами,  как и стандартные,  но в отличие от них,  ясен
перец, засекречены.

    2.3. ДРУГИЕ КОНТРОЛЬНЫЕ КОДЫ

    В качестве контрольных кодов может быть использована  любая  другая
хорошая хеш-функция,  например,  SHA или MD5. Основной недостаток таких
функций - относительная сложность программирования. Другой недостаток -
избыточность  результата,  который составляет в разных вариантах от 256
до 512 бит.  На 100000-200000 вирусов это явно круто.  Ориентируясь  на
разумное  количество потенциальных коллизий,  вполне хватило бы и 32-48
битов. Тем более, что авторы антивирусов постоянно ноют, что их продукт
постоянно  распухает  как  в памяти,  так и на диске,  и пора соблюдать
диету.
    Используются ли эти хеши в антивирусах,  мне достоверно неизвестно.
Наверное, все-таки да. В рекламных целях. J

    2.4. "ПРАВИЛЬНОЕ" ИСПОЛЬЗОВАНИЕ СИГНАТУР И КОНТРОЛЬНЫХ КОДОВ

    Вообще-то, любые   контрольные   коды   -  это  ни  что  иное,  как
хеш-функции.  Когда-то очень давно,  лет 50 назад, хеширование было как
раз  и  придумано  для  _ускорения_  поиска  в частично отсортированных
массивах  данных.  (Это  так  называемый  "ассоциативный"   поиск).   В
соответствии с этим подходом, антивирусы должны были бы работать так:
    - хранить в базах данных наборы длинных сигнатур;
    - также  хранить  в  базах данных наборы коротких контрольных кодов
(хешей),  причем   одному   хешу   (ключу)   в   общем   случае   может
соответствовать несколько разных вирусов со своими сигнатурами;
    - при  распознавании  вируса  перевоначально надо быстро сравнивать
хеши из базы данных и хеши проверяемых файлов;
    - если ни один хеш не совпал, то файл считается здоровым;
    - если один из хешей совпал, то дальше поиск осуществляется при уже
помощи побайтового сравнения длинных сигнатур,  соответствующих данному
хешу.
    Но авторы   некоторых   антивирусов   (например,   КАВ)   в   своих
аналитических  обзорах  отмечают,  что  используют в своих базах данных
короткие контрольные коды  исключительно  для  _уменьшения_размера_баз.
Поэтому,  как  можно  предположить,  "правильная"  методика  в  них  не
применяется (т.к., наоборот, увеличивает базы).

    3. ЭВРИСТИЧЕСКИЕ МЕТОДЫ

    Есть греческое  слово  heurisco,  оно  означает  "узнавать  новое",
"открывать".  Поэтому  "эвристическими" называются методы,  имитирующие
процесс    человеческого    мышления.    Глядя    на    исходник    или
дизассемблированный листинг программы,  человек обычно может определить
-  вирус  это  или  нет,  основываясь  на  наличии  и  взаимоотношениях
различных  ее характерных фрагментов:  процедур файлового ввода-вывода,
процедур копирования  из  макросов  одного  документа  в  другой и т.п.
    Разумеется, необходимым  условием этого процесса является ПОНИМАНИЕ
СМЫСЛА того,  что именно выполняет тот  или  иной  фрагмент,  т.е.  так
называемой "семантики".
    Для того,  чтобы  научить  антивирус  распознавать   заразу,   надо
снабдить  его  чисто  человеческим  качеством  -  умением анализировать
семантику.  Даже для человека это не всегда такая уж простая задача,  а
уж для программы... К счастью, от антивируса не требуется разбираться в
семантике КАЖДОГО фрагмента программы,  ему надо "знать"  только  смысл
НЕКОТОРЫХ, наиболее характерных, узловых фрагментов. Это:
    - для загрузочных  программ  -  вызовы  Int  13h  с  учетом  набора
значений регистров;
    - для DOS-овских программ - вызовы Int 21h;
    - для Windows-программ - вызовы сервисов Win32 API и сервисов VMM с
учетом содержимого стека и регистров;
    - для макросов MS Office  -  обращения  к  стандартным  функциям  и
методам типа MacroCopy, OrganizerCopy или Import/Export;
    - ну  и  т.п.,  включая различные замаскированные способы всех этих
вызовов и обращений.
    Эти "подозрительные" фрагменты можно просто искать внутри программы
по сигнатурам или контрольным кодам. И такие антивирусы были (например,
Lie Detector by SEH).  Но такой наивный подход довольно бестолков.  Кто
сказал,  что  найденный  линейным  поиском   внутри   файла   программы
подозрительный  фрагмент  когда-нибудь получит управление?  Кто сказал,
что регистры будут загружаться только командами MOV R,NNNN и  причем  в
определенном порядке?
    Вот почему  современные  антивирусы   для   поиска   подозрительных
фрагментов  трассируют прогамму либо при помощи Int 1,  либо при помощи
эмуляции ("понарошечного" выполнения) команд. При достижении, например,
Int  21h (или просто при переходе в сегмент DOS-а) достаточно проверить
содержимое регистров,  и семантика  этого  фрагмента  сразу  же  станет
ясной!
    Ну а дальше приходит время специальных методов, которые анализируют
взаимодействие этих фрагментов, и позволяют принять решение - вирус или
нет.

    3.1. ЛОГИЧЕСКИЕ МЕТОДЫ

    Проще всего принять решение,  составив  и  проверив  на  истинность
сложное логическое условие ("предикат"), типа:

    ЕСЛИ
     ("CALL XXX/POP R") and
     ("ОТКРЫТ_ФАЙЛ_НА_ЗАПИСЬ") and
     (("РАСШИРЕНИЕ_ФАЙЛА=COM") or ("РАСШИРЕНИЕ_ФАЙЛА=EXE"))...,
    ТО...

    Видимо, этот  прием  до   сих   пор   применяется   в   большинстве
антивирусов.  Чтобы  не  ошибаться,  надо  учитывать,  в  каком порядке
встретились подозрительные  фрагменты,  не  противоречат  ли  они  друг
другу,  и  т.п.  Но  тогда "хороший" предикат должен состоять из многих
сотен различных элементарных условий. Часто вирусологи ленятся подробно
описывать все тонкие нюансы,  и тогда рождаются Ninnyish.Generik-и. J
    Главный недостаток (и оно же - главное достоинство!)  таких методов
- вынужденность однозначного ответа:  "да/нет", "вирус/невирус". А ведь
иногда мир нельзя разделить на  "черное/белое":  встречаются  вирусы  с
ошибками  (intended),  троянцы,  просто  случайно (или не случайно J )
похожие на вирус программы, и пр.

    3.2. МЕТОДЫ РАСПОЗНАВАНИЯ ОБРАЗОВ

    Это большая  группа математических методов,  основанная на создании
обобщенного вирусного  "образа"  и  на  сравнении  всех  подозрительных
программ  с  этим образом.  Насколько я в курсе,  на настоящий момент в
коммерческих антивирусах эти методы используются ПОКА редко,  чаще -  в
исследовательских или демонстрационных а/в-програмах.  Но зато без этих
методов никуда не денешься при распознавании, например, спама по набору
встречающихся в e-mail-овых письмах слов и буквосочетаний.
    Честно говоря, хотя это очень интересная тема, мне лениво сейчас ее
подробно обсуждать. А если совсем кратенько, то...
    Чаще всего используются методы, требующие предварительной настройки
(обучения)   распознающего   алгоритма   на  многочисленных  "типичных"
примерах.
    Во-первых, это методы,  основанные  на  формуле  Байеса  из  теории
вероятностей.  Во-вторых,  это методы линейной классификации (например,
дискриминантный классификатор  Фишера).  Наконец,  это  страшно  модные
сейчас методы на основе нейронных сетей.
    Все эти методы в общем и целом решают одну и  ту  же  задачу.  Если
представить  множество  рассматриваемых  объектов  (в  данном  случае -
программ)  в  виде  набора  числовых  характеристик  и/или   логических
условий,   то   эти   характеристики/условия  можно  рассматривать  как
координаты точек,  соответствующих  объектам,  в  каком-то  многомерном
пространстве.   Методы   распознавания   образов   помогают   построить
поверхности  (в  линейном  случае  -  гиперплоскости,  в  нелинейном  -
какие-то "загогулины") меньшей размерности,  разбивающие все эти обекты
на классы (в данном случае - на "вирус"/"не вирус").

    ^
    I  V    / N
    I    V /
    I  V  / N
    I    /
    I   /  N
    I  / N
    +----------->

    Все это тоже тема большой и совсем другой статьи.

    ЗАКЛЮЧЕНИЕ

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


(C) NF, 1998-2004