ZF

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

                                     Плохо жить на свете пионеру Пете
                                     Бъет его по роже пионер Сережа.

                                                   из детских анектодов


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

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

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

      +--+        +-------------+  +---+         +------------+
+---+ | С++ +---+<+События связн| ++ Д ++ +---+<-+эвр. маска 1|
|эмуЖ=µ о|+>+Пре| +-------------+ || е |+>+Пре|  +------------+    +---+
|ля | | б|  |обр| +-------------+ || й |  |обр|  +------------+    |Эвр|
|торЖ=µ ы+->+азо+<+События несв | ++ с +->+азо+<-+эвр. маска 2| +->+чис|
|   | | т|  |ват| +-------------+ || т |  |ват|  +------------+ |  |ло |
+---+ | и|+>+ель| +-------------+ || в |+>+ель|  +------------+ |  +---+
      | я++ +-+-+<+....         | ++ия ++ +-+-+<-+....        | |
      +--+    |   +-------------+ |+---+    |    +------------+ |
              +-------------------+         +-------------------+

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

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

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

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

     for(i=0;i<CountMaskEvrnrs;i++) {
       if (MaskEvents[i][0]==0) {
         for(j=2;j<MaskEvents[i][1];j++)
           if(Events[MaskEvents[i][j]]==0)
             goto nextMask;
       };
       else
         for(e=0,j=2;j<MaskEvents[i][1];j++) {
           if(Events[MaskEvents[i][j]]==0 || 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 nextMask1;
       NumberHeurist = i+1;
       break;
     nextMask1:
     }
    CountMaskHeurist - число эвристических масок
    MaskHeurist - двумерный массив с эвристическими масками
    NumberHeurist - эвристическое число

    Данная схема может использоваться всеми  желающими  с  обязательной
ссылкой на автора данной идеи.

  Валентин Колесников, AVP Team e-mail: valik@avp.ru.


(C) NF, 1998-2004