Самый полиморфный вирус
14 июня 2010
Рубрика: Лаборатория Касперского. Тэги:
Автор: .

«Лаборатория Касперского» публикует статью «Обзор Virus.Win32.Virut.ce», который открывает серию публикаций «Сложные вредоносные программы». Автор материала — старший вирусный аналитик «Лаборатории Касперского» Вячеслав Закоржевский.

Введение

Данная статья посвящена полиморфному заражающему вирусу Virus.Win32.Virut, а конкретно — модификации “ce”.

Почему же выбор пал именно на Virut.ce?

Virut.ce — один из наиболее популярных заражающих зловредов, которые проникают на компьютеры пользователей. Вирус заражает исполняемые файлы в системе, применяя самые современные методы, так что его сложно обнаружить, задетектировать и вылечить файлы. В настоящее время для массового распространения вредоносных файлов наиболее активно применяется server–side полиморфизм. Заражение файлов не так популярно, как это было, например, лет пять назад, ввиду того, что уровень эмуляции файлов достиг очень высокого уровня. Надо отдать должное разработчикам Virut.ce: они не побоялись трудностей, с которыми им пришлось столкнуться, применяя заражение исполняемых файлов.

Технологии, реализованные в Virut.ce, очень хорошо отражают наиболее современные методы, используемые при написании зловредов. В нём активно используется антиэмуляция и антиотладка. А именно — применяется подсчёт дельт, полученных с помощью серии инструкций rdtsc, API–функции GetTickCount, а также используется многократный вызов “Fake” API – функций.

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

В этой статье рассмотрены техники заражения файлов. Также не будет обойдена вниманием обфускация, которая имеет место при каждом заражении исполняемого файла. Дополнительно будет показана эволюция различных компонент вируса, начиная от его появления и заканчивая настоящим временем. Вся статистика, которая использована в статье, получена с помощью технологии KSN — Kaspersky Security Network.

Краткий обзор статистики и распространения

Самая первая модификация вируса Virut — “a” — появилась ещё в середине 2006 года. Далее шло постепенное развитие вредоносной программы, которое вылилось в появление модификации “q” в сентябре 2007 года.

Эта модификация была очень популярна в своё время, однако, сейчас встречается редко. Полноценная “поддержка” Virut.q была прекращена разработчиками во второй половине 2008 года. А в первую неделю февраля 2009 года было зарегистрировано появление модификации “ce”. Промежуток времени между окончанием работы над модификацией “q” и выпуском “ce”, по-видимому, был использован для разработки новых методик заражения, алгоритмов шифрования и методов антиэмуляции.

Далее в статье под словами “Virut”, “Вирус” и т.д. будет подразумеваться именно Virus.Win32.Virut.ce.

В настоящее время модификация Virut.ce находится на втором месте среди всех Virus.Win32.*.*, детектируемых на компьютерах пользователей.

kasper_14_06_2010

TOP20 детектируемых вирусов Январь 2009 — Май 2010

На графике, приведенном ниже, хорошо видно, что с течением времени активность распространения Virut.ce растет.

kasper_14_06_2010_1

Динамика заражения компьютеров вирусом Virut.ce май 2009 — май 2010

Распространяется вирус через заражённые файлы, как исполняемые, так и html, либо через небольшие программы, предназначенные для взлома лицензионного ПО. К таким программам, как правило, относятся генераторы ключей (keygen) и утилиты прямого изменения файлов (crack). А если конкретнее, то через RAR — SFX архивы с говорящими названиями вроде “codename_panzers_cold_war_key.exe”, “advanced_archive_password_recovery_4.53_key.exe”. Когда пользователь запускает архив, в нём, помимо искомой программы, находится ещё и экземпляр Virut, либо в виде исходного экземпляра вируса, распространяемого разработчиками, либо в виде заражённого файла.

Функционал вируса

Пришло время рассмотреть самое основное — функционал вируса. Как известно, подавляющее большинство зловредов создаются исключительно ради извлечения выгоды. Так вот — Virut не стал исключением. По сути — это Backdoor, который вначале пытается внедриться в адресное пространство процесса “explorer.exe” (“services.exe”, “iexplore.exe”), а затем подключиться по IRC-протоколу к адресам irc.zief.pl, proxim.ircgalaxy.pl, с которых он ожидает команды сервера. Всё довольно стандартно, как и попытка завершения различных процессов, список которых виден на представленном ниже скриншоте. В этом списке присутствуют и процессы антивирусных программ — “nod32”, “rising”, “f-secure” и т.д.

kasper_14_06_2010_2

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

Довольно интересным является заражение всех *.htm и *.html — файлов. В них дописывается следующая строка: <iframe src = http://jl.*****.pl/rc/ style = “display:none”></iframe>. По этой ссылке будет происходить скачивание наиболее актуальной версии Virut с помощью эксплуатации уязвимости в PDF–файле. От версии к версии (в пределах модификации “ce”) эта строка значительно меняется — например, буква “u” заменяется на “u”, что является её эквивалентом. Для браузера запись значения не имеет, а вот статичные сигнатуры становятся бессильными.

Общий вид заражения и техника заражения

В вирусе Virut.ce для заражения применяется технология EPO или перезапись точки входа. Совместно с ней используются один или два полиморфных декриптора.

Техника EPO — Entry Point Obscuring, сокрытие точки входа, —заключается в затруднении обнаружения перехода на тело вируса. Обычно это реализуется с помощью замены либо произвольной инструкции, либо параметра инструкции перехода. Ниже приведён пример подмены инструкции и направления перехода.

kasper_14_06_2010_3

Пример заражения файла с помощью техники EPO

Под перезаписью точки входа подразумевается изменение PE-заголовка файла, а именно перезапись поля AddressOfEntryPoint структуры IMAGE_NT_HEADERS32. Следовательно, исполнение файла начнётся сразу с вирусной составляющей.

Как упоминалось выше, вирус при заражении добавляет только один или два декриптора. Назовём их «Init» и «Main». Если дешифровщик Main располагается в каждом файле, над которым “поработал” Virut.ce, то Init встречается не всегда. Рассмотрим более подробно назначение и общий вид этого декриптора.

Основное назначение декриптора Init — расшифровать первый “слой” основного тела вируса, чтобы затем передать туда контроль, но даже после этой расшифровки бОльшая часть тела вируса всё равно остаётся зашифрованной. Init декриптор представляет собой небольшой код, размером от 0x100 до 0x900 байт, большинство инструкций которого являются бесполезными и используются для того, чтобы сбить статичные антивирусные сигнатуры. Декриптор располагается в конце секции кода, если там присутствует достаточное количество нулей. Логика его работы следующая:

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

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

Таким образом, получится четыре возможных варианта заражения:

1. Init Decryptor + EPO:

kasper_14_06_2010_4

2. Init Decryptor + изменения EP:

kasper_14_06_2010_5

3. Только EPO:

kasper_14_06_2010_6

4. Только перезапись точки входа:

kasper_14_06_2010_7

Четыре представленные схемы полностью отражают все возможные варианты заражения и изменения структуры файла.

Первичная дешифровка тела Virut.ce

Прежде чем переходить к функционалу основного тела вируса, рассмотрим Init декриптор в реальном заражённом файле.

kasper_14_06_2010_8

Фрагмент из файла, заражённого Virus.Win32.Virut.ce,
в котором присутствует Init декриптор

kasper_14_06_2010_9

Дизассемблированный код Init декриптора

Выше располагаются два скриншота. Первый — фрагмент заражённого файла calc.exe. На нём дополнительно отмечены границы секции кода и выделен Init дешифровщик. На втором скриншоте —дизассемблированный код Init декриптора. На иллюстрации красными овалами обведены четыре логических элемента, которые упоминались выше. В данном примере регистр ecx заполняется с помощью последовательных инструкций push — pop, а расшифровка выполняется с помощью adc. Однако так было не всегда. За год Virut.ce сильно эволюционировал, соответственно, в нём эволюционировал и Init декриптор. Если занесение в регистр размера тела менялось только один раз, — а именно mov reg, dword изменилось на push dword; pop reg, то сама дешифровка менялась не один раз (в хронологическом порядке):

1. ADD/SUB [mem], dword;
2. ROL/ROR [mem], byte;
3. ADC/SBB [mem], byte;
4. ADD/SUB [mem], byte;
5. ADD/SUB [mem], word;
6. ADC/SBB [mem], word;
7. ADC/SBB [mem], dword;

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

Восстановление оригинального кода

Итак, весь код основного тела можно поделить на три группы по его назначению: восстановление оригинальной функции/точки входа, дешифровка статичного тела, выполнение вредоносной нагрузки.

Прежде чем переходить к рассмотрению каждого элемента, посмотрим на структуру тела и на соответствующий фрагмент файла.

kasper_14_06_2010_10

Структура основного тела Virut.ce

Как видно из рисунка, всё основное тело, которое дописано в конец последней секции кода, делится на два типа — зашифрованное статичное тело и исполняемый код. Исполняемая часть содержит код, который исполняет антиэмуляцию, восстанавливает оригинальную точку входа и/или функцию, дешифрует статичное тело. Она “размазана” по основному телу и может располагаться как целиком вверху/внизу, так и может быть разбита на две составляющие. Что интересно, исполняемая часть ещё и сильно обфусцирована. Для антивирусных компаний это является одной из трудностей при детектировании, так как статичные элементы в исходном файле отсутствуют, а статичное тело, очевидно, всегда зашифровано с разными ключами и/или алгоритмами, но об этом далее.

kasper_14_06_2010_11

Фрагмент файла, содержащий основное тело Virus.Win32.Virut.ce

Выше представлен скриншот фрагмента файла, заражённого Virus.Win32.Virut.ce. Красным овалом обведена исполняемая часть основного тела вируса, её также можно найти визуально по значительной бОльшей концентрации нулевых байтов. В этом примере вирус не использовал Init Decryptor при заражении, иначе все области выглядели бы примерно одинаково и были зашифрованы.

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

1. CALL с небольшой дельтой перехода;
2. сохранить оригинальное содержимое регистров;
3. заполнить регистр EBX адресом, указывающим на kernel32.dll;
4. вычислить указатель на адрес инструкции, следующей за CALL из п.1;
5. арифметическая/логическая операция над адресом, полученным в п.4.

Необходимо заметить, что вирус применяет технику EPO, только если находит вызов API–функции из kernel32.dll. При этом поиск ведётся по вызовам как через опкод 0x15FF, так и через 0xE8, с последующим JMP (0x25FF). Если такая функция найдена, то она заменяется на инструкцию JMP (0xE9), которая указывает на п.1 предыдущей схемы. В регистр EBX кладётся адрес заменённой функции из kernel32.dll, а если была просто изменена точка входа, то в регистр помещается значение по [ESP + 24] — адрес возврата приложения в kernel32.dll. В дальнейшем содержимое этого регистра будет использоваться для получения адресов экспортируемых функций из библиотеки. В случае применения EPO техники, значение по [ESP + 20] будет содержать адрес инструкции, следующей за вызовом пропатченой API–функции, а иначе — оригинальной точки входа.

Если исключить обфускацию, то в машинных кодах, в самом простом случае, восстановление точки входа и/или функции будет происходить следующим образом (считаем, что была заменена функция GetModuleHandleA):

CALL $ + 5
PUSHAD
MOV EBX, [GetModuleHandleA]
XOR [ESP + 20h], Key

Этот код полностью соответствует логике работы всего блока. Теперь проследим за изменением всех этапов во времени. Единственный пункт, который не будет подробно рассматриваться, — второй (сохранение оригинального содержимого регистров), так как этот элемент всегда реализуется с помощью инструкции PUSHAD.

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

Самый первый этап — вызов инструкции CALL — практически не изменялся. Вначале это был просто CALL $ + 5, чуть позже — CALL $ + 6(7,8), затем CALL $ + 0xFFFFFFFx, т.е. вызов «назад». Хотя может показаться, что этот этап совсем неважен, и можно было бы обойтись без него, это не так. После исполнения этой инструкции в стек кладётся адрес следующей инструкции. Этот адрес используется как для восстановления точки входа/оригинальной функции, так и для адресации ключей расшифровки и начала статичного тела. Этот адрес мы упомянем еще раз, при рассмотрении Main декриптора.

Этап под номером 3 меняется чаще, по сравнению с только что рассмотренным элементом. Возможные варианты исполнения:
MOV EBX, [ApiFunc]/MOV EBX, [ESP + 24h];
PUSH [ApiFunc]/[ESP + 24h]; POP EBX;
SUB ESP, xxh; PUSH [ESP + 24h + xx]; POP EBX;
LEA EBX, [ESP + xxh]; MOV EBX, [EBX + 24h — xx];
ADD ESP, 28h; XCHG [ESP – 4], EBX;

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

Рассмотрим последний этап — восстановление непосредственно адреса оригинальной точки входа или адреса пропатченого CALL`а. Его изменение происходит практически непрерывно — в среднем, каждые 2 — 3 недели.

После вызова инструкции PUSHAD указатель на стек — регистр ESP уменьшится на 0x20, следовательно, в [ESP + 20h] будет находить значение, заполненное последней инструкцией CALL. К этому значению применяется арифметическая/логическая операция и получается необходимое нам значение.

Ниже приведена часть возможных вариантов последовательности инструкций, которые выполняют действия, описанные выше:
XOR/AND/OR/ADD/SUB [ESP + 20h], const;
MOV [ESP + 20h], const;
LEA EBP, [ESP + x]; MOV/OR/ADD/SUB/XOR EBP, const; XCHG [EBX + 20h – x], EBP;
MOV EBX, ESP; PUSH const; POP [EBX + 20h];
PUSH const; POP [ESP + 20h].

Здесь опять же были приведены не все возможные варианты, но общая тенденция явно прослеживается — добавление разнообразных промежуточных операций.

На скриншоте ниже приведен фрагмент зараженного файла, содержащий все описанные выше операции (отмечены красным овалом).

kasper_14_06_2010_12

Скриншот заражённого Virus.Win32.Virut.ce файла,
содержащий код восстановления оригинальной точки входа

Обфускация была исключена из примерного кода для упрощения понимания, однако, её активно используют во всех участках файла, дописанных вирусом (Init декриптор, вся исполняемая часть основного тела). Именно обфускация полностью ограничивает использование статичных сигнатур, так как код после её применения становится полностью изменённым (по содержимому, но не по функционалу). Примеры инструкций, которые используются в качестве «мусора», т.е. не несущих какой — либо функциональной нагрузки:

Пара — XCHG reg1, reg2; XCHG reg2, reg1;
Пара — SUB reg1, reg2; ADD reg1, reg2;
MOV reg, reg; OR reg, reg; AND reg, reg; XCHG reg, reg; LEA reg, [REG];
CLD, CLC, STC, CMC и т.п.

Под “reg1” и “reg2” подразумеваются разные регистры, а под “reg” — одинаковые, в пределах одного выражения

Арифметические/логические операции, где правый операнд произволен — ADC reg, const; SBB reg, const; XOR reg, const; и т.п.

На скриншотах ниже элементы обфускации отмечены красным овалом:

kasper_14_06_2010_13

Скришноты, содержащие код основного тела вируса.
Овалами отмечены элементы обфускации

На левом скриншоте очень хорошо видно, что бесполезные инструкции занимают 70-80% всего кода.

Выше были приведены не все возможные варианты обфускации, а наиболее часто используемые. От версии к версии добавляются новые варианты.

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

Дешифровка основного тела

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

Что интересно, если рассматривать Main декриптор из дизассемблера, то код будет выглядеть бессмысленно, так как происходит вызов инструкции RETN, которая передаёт управление в совершенно произвольное место. Дело в том, что перед тем, как начать исполнение основной дешифровки, инструкция RETN (0C3h) изменяется на CALL (0E8h). Выполняется это с помощью инструкции вида

ADD/SUB/XOR [EBP + xx], bytereg,

где EBP указывает на адрес инструкции, следующей за CALL, а bytereg — один из байтовых регистров.

Следовательно, можно считать, что цикл дешифровки будет начинаться после исправления RETN на CALL. Далее следует цикл дешифровки, который обфусцирован, как и всё остальное тело. Мало того, что используемых алгоритмов довольно много, так они ещё и не элементарны, в отличие от тех, что используются в Init декрипторе. Как правило, используется от двух до шести логических/арифметических операций в связке. Во всех алгоритмах регистр EDX содержит ключ расшифровки, а EAX — виртуальный адрес начала статичного тела. Регистры заполняются с помощью инструкций вида:

MOVZX/MOV dx/edx, [ebp + const]
LEA eax, [ebp + const]

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

Отразить всё многообразие используемых алгоритмов довольно сложно, поэтому приведено лишь несколько самых интересных из них:

ROL DX, 4
XOR [EAX], DL
IMUL EDX, EDX, 13h

ADD [EAX], DL
ROL DX, 5
IMUL EDX, 13h

XOR [EAX], DH
ADD [EAX], DL
XCHG DH, DL
IMUL EDX, 1Fh

XOR [EAX], DH
XCHG DH, DL
ADD [EAX], DH
IMUL EDX, 1Fh

XOR [EAX], DL
ADD [EAX], DH
IMUL EDX, 2Bh
XCHG DH, DL

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

kasper_14_06_2010_14

Дизассемблированный фрагмент Main декриптора

Выше представлен скриншот, содержащий фрагмент дизассемблированного кода Main декриптора. Красным овалом отмечены “полезные” инструкции, о которых до этого шла речь. Здесь также присутствуют бесполезные операции, которые являются продуктом обфускации.

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

kasper_14_06_2010_15

Расшифрованное статичное тело вируса

На скриншоте показано расшифрованное статичное тело вируса. Красными овалами отмечены строки, соответствующие определённому вредоносному функционалу. К примеру, “JOIN” и “NICK” — IRC-команды, “irc.zief.pl proxim.ircgalaxy.pl” — удалённые IRC–сервера, к которым пытается подключиться Virut, “SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile\AuthorizedApplications\List” — ключ реестра, по которому находится список доверенных программ для встроенного файрволла Windows.

Заключение

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

Разумеется, в статье представлена не вся информация о Virut.ce, — но такой задачи и не стояло. Можно было бы подробно изучить общение вируса с IRC–сервером или все тонкости заражения файлов, но мы уделили внимание только самым основным механизмам работы Virut. Подробное рассмотрение реализации антиэмуляции было исключено, дабы опубликованной информацией не воспользовались злоумышленники.

Определить дальнейшие перспективы развития вируса довольно сложно. Хотя в апреле — мае 2010 года и не было обнаружено новых версий Virut.ce, но это не означает, что его разработка остановилась. Вполне возможно, что вирусописателями была взята пауза для внесения в вирус изменений, которые усложнят детектирование Virut антивирусными компаниями.

В настоящее время все продукты «Лаборатории Касперского» успешно детектируют и лечат Virus.Win32.Virut.ce. Если будет найдена новая модификация вируса, её детектирование будет добавлено в наши базы в кратчайшие сроки.

Мы надеемся, что данная статья будет полезна вирусным аналитикам, а также людям, которые занимаются разбором вредоносных программ. В настоящее время антиэмуляция или антиотладка встречаются в большинстве зловредов, распространяемых с использованием server–side полиморфизма. Понимание технологий, реализованных в Virut.ce, поможет разобраться в этих зловредах и в полиморфных вирусах, использующих аналогичные трюки.

Orphus system
Подписывайтесь на канал infoCOM.UZ в Telegram, чтобы первыми узнавать об ИКТ новостях Узбекистана
В Telegram
В WhatsApp
В Одноклассники
ВКонтакте