Анализ вируса 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, больше не работает... [...] |