ZF

                       Анализ вируса W97M.Lexar
                   by Ричард Марко (Eset, Slovakia)

                      Virus Bulletin, August 2003
                          (фрагменты статьи)

    ************************ Перевод by DrMAD *************************

    Дни, когда   макровирусы  доминировали   в   вирусных  хит-парадах,
несомненно, прошли.  Эти  времена  начинались  в  1995  году  с  вируса
WM.Concept.A. В  конце  1999  года  макровирусы порождали до 90%  всех
вирусных инцидентов. Некоторое время спустя их слава начала угасать и в
соответствии со  статистикой  Вирусного Бюллетеня упала до 0.68%  к маю
2003 года.

    25 июня 2003 года я получил документ Word,  который,  как  показала
эвристика,  кажется был инфицирован новым макровирусом.  Быстрый анализ
показал,  что  эвристика  не  соврала.  Тексты,  отображаемые  вирусным
троянским  фрагментом,  намекали  на  то,  что лучше всего было бы этот
вирус обозвать Relax,  но к этому  моменту  уже  хорошо  были  известны
вирусы из совсем другого семейства W97M.Relax. Поэтому мы назвали новый
вирус W97M.Lexar.

    = Размножение =

    Исходник W97M.Lexar.A состоит из  83  строк.  Механизм  размножения
стандартен и весьма примитивен...

    [...]

    ...Затем вирус пытается открыть файл, содержащий активный документ,
в двоичном режиме.  Если  это  получается,  он  устанавливает  байт  по
смещению 35Dh  в  1.  Мы  детально  рассмотрим  это  необычное действие
позже...

    [...]

    = Странный байт =

    Проблем не возникало.  Все было относительно просто  и  примитивно,
исключая одну фишку: странное изменение байта в 1.

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

    Давайте начнем с  краткого  описания  формата  дкумента  Word.  Эти
документы  в  основном хранятся в составных файлах OLE2,  которые могут
быть представлены как множество отдельных  файлов,  заключенных  внутри
одного физического файла. Этот физический файл имеет сложную структуру,
содержащую 2-х-уровневую FAT-таблицу,  каталоги,  организованные в виде
деревьев и т.п.  Это означает, что мы имеем дело со многими хранилищами
(каталогами) и потоками (файлами),  каждый из которых также имеет  свой
сосбственный внутренний формат.

    Каждый составной  файл  OLE2 - это последовательность секторов,  по
умолчанию  имеющих  длину  200h  байтов.  Первый  сектор  (с   файловым
смещением 0) начинается с заголовка.  Он содержит важную информацию про
устройство файла,  такую как размер сектора, указатель на первый сектор
корневого  каталога  и  т.п.  Размещение  остальных секторов зависит от
содержимого FAT-таблиц и оно изменяется от файла к файлу. Ну и фигли же
вирус  пишет в смещение 35Dh (это смещение лежит во втором секторе), не
проверяя, куда попадает и какие повреждения может этим нанести?

    Ответ заключается в способе, которым Word сохраняет свои документы.
Наши тесты показали,  что в подавляющем большинстве случаев со смещения
200h начинается  поток  WordDocument.  И  это  означает,  что  файловое
смещение 35Dh соответствует смещению 15Dh в потоке WordDocument.

    = Поток WordDocument =

    Поломав немножко голову,  давайте познакомимся  поближе  с  потоком
WordDocument. Это   фундаментальный   поток   для  Word-документов.  Он
начинается со структуры  с  названием  FIB  (File  Information  Block).
Неподалеку от  смещения 15Dh мы обнаружили пару интересных полей fcCmds
и lcbCmds.

    А теперь посмотрим в документацию от Microsoft.

   ------------------------------------------------
   0x015A fcCmds long     Offset in table stream of
                          The macro commands.
                          These commands are
                          private and undocumented.

   0x015E lcbCmds ulong   Undocument size of
                          undocument structure not
                          documented above.
   --------------------------------------------------

    Я так понял, что кто-то из Microsoft просто прикалывается. Понятно,
что  изменение байта со смещением 15Dh изменяет самый старший байт поля
fcCmds.  Так как таблица потока часто занимает несколько килобайтов, то
fсСmds будет указывать куда-то за пределы потока.

    Поскольку область _macro commands_ официально недокументирована, то
пришлось немножко  похакать  ее,  и  это  показало,  что  она  содержит
множество различных записей.  Например,  там  лежат  имена  макросов  в
VBA-проекте, информация по пользовательским настройкам и многое другое.
Область всегда стартует с байта 0FFh и кончается байтом 40h.

    Документы, которые     не    содержат    никаких    макросов    или
пользовательских настроек,  имеет lcbCmds=2 и  fcCmds,  указывающее  на
пару 0FFh 40.  Когда наш макродвижок удаляет макросы из инфицированного
документа, он чистит всю область _macro commands_.

    Поскольку W97M.Lexar.A устанавливает fcCmds за  конец  таблицы,  то
движок  отказывается  работать.  Теперь  осталось рассмотреть последнюю
часть загадки,  почему же Word молчит как рыба об лед, хотя в документе
явно лежит подозрительный макрос?

    = Защита от макровирусов =

    Вплоть до Office  95  MIcrosoft  использовала  язык  WordBasic  для
написания  Wordовских  макросов.  Макросы  жили  вместе  с документом в
обющем потоке WordDocument.  Начиная с  Office  97  Microsoft  заменила
WordBasic  на более мощный язык VBA.  Теперь макросы хранятся в потоках
каталога Macros.  Все очень просто:  если нет макросов,  то нет  такого
каталога.

    Мы теперь посмотрим,  как же работает _macro  virus  protection_  в
Word 97  SR-1.  Функция  закопана  где-то  глубоко в winword.exe, длина
которого 5 Мб,  но немножко потрахавшись,  можно найти ее.  Назовем  ее
ProcessMacroCommands. Ее упрощенный алгоритм выглядит так:

 ------------------------------------------------
    BOOL ProcessMacroCommands(STREAM_HANDLE
    TableStream, LONG fcCmds, ULONG lcbCmds ...)
    {

      BYTE RecordID;
      BOOL UserWarned=FALSE;

      if (lcbCmds == 1) return FALSE;
      ...
      Seek(TableStream, fcCmds);
      ...
      ReadByte(TableStream, &RecordID);
      lcbCmds--;
      if (RecordID != 0xff) return TRUE;
      ReadByte(TableStream, &RecordID);
      lcbCmds--;
      if (RecordID != 0x40)
      {
         PossibleMacros;
         if (!WarnUserAboutMacros()) return FALSE;
         UserWarned=TRUE;
      }

      if (!UserWarned && TestMacrosStorage())
      goto PossibleMacros;
      ...

    }
   --------------------------------------------------

    По умолчанию макросы разрешены.  Если функция возвращает FALSE,  то
Word не открывает  документ.  Функция  ReadByte  читает  один  байт  из
указанной  позиции указанного потока.  Позиция в потоке устанавливается
функцией Seek.  Если позиция  указана  за  концом  потока,  то  функция
ReadByte прочитывает 0.

    Функция WarnUserAboutMacros   отображает  хорошо  известный  диалог
(если установлен  соответствующий  флажок  в  Word-е)  и  ждет  желания
пользователя - разрешить  или  запретить  макросы,  и делает именно так
(устанавлиявая свои внутренние флажки) или даже возвращает  FALSE, если
пользователь решает вообще не открывать документ.  Окончательно функция
TestMacrosStorage пытается открыть поток Macros и возвращает TRUE, если
удалось.

    Как можно  видеть,  если  fcCmds  указывает  за  конец  потока,  то
сравнение с 0FFh обломится и функция вернет TRUE (т.е.  Word  продолжит
загрузку документа)   без   отображения  предупреждений.  Все,  загадка
разгадана. Другой  способ  достижения  того  же  эффекта   может   быть
достигнут установкой  fcCmds в кокую-нибудь позицию потока,  которая не
содержит 0FFh в первом байте,  или заменой первого байта области _macro
commands_.

    = Решение =

    Есть хорошие новости и есть плохие новости.  Плохие новости в  том,
что эта  уязвимость  есть  также  в  Word  2000  и  Word XP,  даже если
установлен Security Level=HIGH.  Версии Word for Macintosh тоже  должны
быть уязвимы,  но  мы не проверяли.  Хорошие новости заключаются в том,
что Microsoft знает об этой проблеме с 21 июня 2001 года, и она описана
в Microsoft Security Bulletin MS01-034.  Патчи для разных версий Word-а
находятся там же.

    Если Вам интересно (мне, например, да) видеть, как же работает этот
патч, вот исправленная версия ProcessMacroCommands:

    ----------------------------------------------------

    BOOL ProcessMacroCommands(STREAM_HANDLE
    TableStream LONG fcCmds ULONG lcbCmds _)
    {
      BYTE RecordID;
      BOOL UserWarned=FALSE;
      if (lcbCmds == 1) return FALSE;
      ...
      Seek(TableStream fcCmds);
      ...
      if (TestMacrosStorage())
      {
         If (!WarnUserAboutMacros())
         return FALSE;
         UserWarned=TRUE;
      }
      ReadByte(TableStream &RecordID);
      lcbCmds--;
      If (RecordID != 0xff) return TRUE;
     ...
    }
    -------------------------------------------------

    Как показано выше,  проверка наличия потока Macros теперь вставлена
перед обработкой  области  _macro  commands_.  Поскольку   этот   поток
присутствует в  зависимости  от  присутствия макросов,  то защита более
надежна и трюк, использованный в W97.Lexar.A, больше не работает...


    [...]



(C) NF, 1998-2004