Метаморфизм (часть II, техническая) — Архив WASM.RU

Все статьи

Метаморфизм (часть II, техническая) — Архив WASM.RU

Приветствую вас снова, дорогие читатели. Я написал статью 'Metamorphism Essay' некоторое время назад и она вышла в Xine#4. Я не обещал написать продолжение, но у меня возникли некоторые идеи насчет метаморфизма (и других подобных вещей), так что мне захотелось написать новую статью на эту тему. Если Вам не понравилась первая часть рассказа о метаморфизме, у Вас нет причин читать эту. Так как это вторая часть, то я предполагаю, что первую Вы уже прочитали :). Кстати, спасибо Qozah/29A за поддержку и новые идеи.

[ Введение во вторую часть рассказа о метаморфизме ]

Первая часть была моим первым вкладом как мембера iKX. Это хорошо, и у меня уже есть некоторые наработки, так что я могу научить Вас многим интересным вещам. Метаморфизм – это техника не для всех этих чайников, ламеров и прочих новичков и даже не для людей со средними навыками. Это действительно элитная техника (хотя я и не люблю это слово, за то, что оно дискриминирует людей и показывает всю их ламерность...). В этом документе я сделаю более глубокое описание некоторых методов, которые могут быть полезными под Win32, но не под DOS (я вообще забыл все, что связано DOS).

[ Своппинг блоков ]

Нет, не пинайте меня. Это НЕ метаморфизм. Зато это может стать хорошим довеском к Вашему метавирусу. Просто посмотрите на вирус Bad Boy и Вы увидите как он перемещает блоки кода внутри себя. Пускай эти блоки достаточно длинны, чтобы AV нашел сканстроку для Вашего вируса, но представьте себе удлиннение и сжатие кода, своппинг регистров и пр... Это просто невероятно и недостижимо!

Давайте посмотрим на небольшую иллюстрацию того, какой должна быть структура вируса с четырьмя переставляемыми блоками:

Как Вы можете видеть, у нас есть два блока, которые не меняют своего положения (но внутри один из них все-таки делает это). Что ж, я думаю нужно объяснить некоторые термины, которые я использовал:

- Заголовок (Header): это то место, где мы храним глобальные данные (то есть те которые используются всеми блоками, например, базовый адрес ядра, API'шников и пр.), смещения всех блоков, которые будут изменяться с каждым вызовом BSE (block swapping engine – собственно, движок своппинга блоков) и, конечно же, длина каждого из блоков. - Загрузочная область (Exec): место в коде, куда мы загружаем нужные нам блоки в правильном порядке и передаем им управление - Блок (Block): блоки – это куски кода, которые могут выполняться в любом порядке, за некоторым исключением. Например, блок антиотладки, блок заражения и т. п. - BSE: этот термин я использую для определения блока в котором содержится сам своппинговый движок. Задачей этого движка является перестановка нужных блоков, а также исправление значений соответствующих переменных в заголовке.

Хорошей идеей будет вместо последовательного исполнения блоков запускать их как потоки (или фиберы, но я бы все же рекомендовал использовать потоки), так чтобы их выполнение происходило одновременно и без задержек.

[ Проблемы метода перестановки блоков ]

Я знаю, что нет ничего невозможного (Наполеон однажды сказал приблизительно следующее: "impossible is the adjective of the suckers"). В процессе реализации метода перестановки блоков возникают некоторые проблемы, обусловленные самими принципами. Первое – изменение всех смещений. Решение было найдено просто – достаточно вычислить дельта-смещение в самом начале кода. Но Вам будет непросто использовать локальные переменные в коде Ваших блоков. Вследствие этого Вам придется помещать все данные в заголовок. Другая проблема, которую я обнаружил, связана с последовательностью выполнения блоков. Здесь может быть два возможных решения:

  • - не использовать зависимых блоков :)
  • - использовать структуру типа

BYTE BlockAttributes, WORD nBlockSize; DWORD lpBlockOffset;

Конечно, Вам придется играть с битовыми полями в атрибутах блока и все зависит от Вас. В одном байте Вы можете определить все возможные зависимости блока. Используйте Ваше воображение :)

Еще одна проблема, свойственная этому методу – детектируемость. Это решается с помощью других техник, к примеру полиморфизма :)

[ Резюме ]

Это простая техника (конечно, не такая простая как заражение com-файлов методом перезаписи, но гораздо проще, чем техники, описанные ниже), но у нее есть свои преимущества... Я думаю будет неплохо, если Вы добавите ее в свой вирус. Я пока не видел подобных вирусов под Win32... Мммм... у меня возникла идея... X-D

[ Своппинг регистров ]

Сейчас пойдут приветствия... Привет Vecna, наш бог! Искренне, по моему мнению, Vecna, наряду с Dark Avenger, Quantum и Neurobasher, лучший кодер всех времен. Вы, наверное, думаете, зачем все эти приветствия Vecna. Просто он написал первый Win32-вирус с техникой своппинга регистров.

Своппинг регистров также относится к категории простого метаморфизма, и позже я объясню почему. Суть этого метода состоит в замене используемых регистров во всем теле вируса. Таким образом, большинство опкодов изменится в любом случае. Есть два способа реализации своппинга регистров: использование эмулятора и использование таблиц. Win9x.RegSwap by Vecna использует последнюю технику. Если Вы хотите увидеть пример первой техники, посмотрите движки A/ZCME by ZOMBiE. Как я слышал, Lord ASD написал MPE (Monster Polymorphic Engine) для своих вирусов Win32.Apparition. В них использовался метаморфизм первого типа. В данном случае я хотел бы уделить внимание подходу, которым воспользовался Vecna (таблицы), поскольку штучки с эмуляторами будут обсуждаться в другой главе.

Давайте представим себе базовый опкод, такой как MOV reg32,imm32. В двоичной форме это будет выглядеть как B8+reg32 imm32. Уделим немного внимания к части B8+reg32:

10 111 xxx ^^^reg32

Таким образом, мы можем легко изменить регистр в опкоде проведя операцию OR с базовым значением (B8) и нужным нам регистром. Вот как выглядели элементы таблицы, которую использовал Vecna в RegSwap (каждый элемент имеет размерность одно слово):

+ 00..06 Индекс регистра + 07..08 Позиция регистра в инструкции (xx 000 xxx или xx xxx 000) + 09..16 Расстояние до предыдущей инструкции с участием регистра

Использование таблиц приводит к тому, что в теле вируса нужно хранить большие массивы таких структур...

[ Проблемы метода перестановки регистров ]

Это хорошая техника, но у нее есть свои недостатки:

  • - она слаба
  • -- структура вируса сохраняется, так что AV сможет поймать его используя регулярные выражения (wildcards)
  • -- таблицы фиксированы, поэтому являются хорошей сканстрокой для AV :(

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

Это был хороший опыт для Vecna и всех нас, ведь мы его ученики :)

[ Резюме ]

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

[ Проект Itxoiten ]

Я имею смелость называть себя изобретателем этой техники, (никто не возразил, так что у меня есть право думать так), так что я дал ей имя Itxoiten. Я довольно подробно описал свой проект в первой части, но было бы неплохо написать несколько строк об этом, чтобы освежить Вашу память. Моя техника основана на принципе транслятора. Сначала мы создаем ITX-заголовок, затем передаем его специальной функции, анализирующей наш заголовок и конвертирующей его в вирус. ITX-заголовок несколько напоминает язык программирования. Давайте представим себе как IHP (ITX header processor - обработчик ITX-заголовка) транслирует инструкцию MOV reg32,imm32 с нашего языка в опкоды:

И это только начало. ITH может генерировать простой MOV самыми разными способами... Например,

xor eax,eax add eax,12345678h или sub eax,eax sub eax,-12345678h

и т. п. Таким образом, мы достигаем одинакового результата, но с абсолютно разными опкодами (большими или даже меньшими по размеру). Представьте себе степень модификации кода... WOW! ;)

Это только часть секции кода ITX-заголовка, и, конечно же, будут секция данных и таблицы импорта (посредством CRC32 API'шников). Я уже работаю над этим, но ничего не обещаю.

[ Проблемы техники Itxoiten ]

Как Вы уже могли догадаться, с этой техникой также есть проблемы. Первая сложность следует из самой идеи ITX-заголовка: заголовок должен быть гораздо больше размера вируса, который он может сгенерировать, а также то, что он статичнен :( Единственным возможным решением представляется внедрение небольшого полиморфного декриптора в ITX-заголовок. Черт, в дополнение к метаморфному движку делать полиморфный кажется (а так оно и есть на самом деле) не очень хорошей идеей, мммм... скорее плохой идеей. Другая проблема – смещения в сгенерированном коде. Я много размышлял над этим, но не нашел никакого простого и эффективного решения. Если у Вас есть какие-либо идеи насчет этого, я был бы рад, если бы Вы написали мне.

[ Резюме ]

Да, это мощная метаморфик-техника, но связанные с ней проблемы делают ее на данный момент времени (и до тех пор, пока я не найду решение) бесполезной. Черт, очень неприятно, что мне приходится критиковать свою собственную технику, но все-таки генерировать идеи проще, чем код для их реализации. Такие выводы я сделал после попыток сделать свой проект реальностью... Но, учитывая все проблемы, на данный момент у меня нет уверенности, что я закончу его в ближайшем будущем. Кто знаем, может быть, однажды, решение придет мне в голову, и я закончу то, что начал. Ох.

[ Внутренний дизассемблер ]

Это несомненно самый надежный способ сделать метаморфный движок, хотя создание эмулятора кода представляется мне не таким уж и легким, по крайней мере в среде Win32. Мы можем с успехом использовать int 1, но только под Win9x, так как в WinNT нельзя просто так перейти в Ring-0 или сделать что-либо подобное. Хотя, нет. Ведь можно сделать эмулятор, который будет выполнять код в специальной защищенной зоне, где мы будем сохранять результаты операций, значения регистров, ячеек памяти и т. п. Это хорошее решение, но сложность заключается в том, что для этого нам нужно знать размер каждой без исключения инструкции. Мы можем это сделать, не так просто, но можем. Этот принцип используется в туннелинговых движках Wintermute, таких как Zohra и Ithaqua. И все-таки под Win32 всегда возникают новые проблемы. Самая большая и неизбежная проблема – вызов API. Мы НЕ МОЖЕМ и НЕ ДОЛЖНЫ эмулировать код внутри API. Это бесполезно и опасно. Одной из причин этого является, то что мы не знаем сколько байт в стеке нужно передать конкретному API и на данный момент нет какого-либо решения этой проблемы. Но мы все еще можем эмулировать свой собственный код и выяснять нужное количество байт из нашего кода. Да, это сложно, но это возможно, потому что мы знаем, что должен делать вирусный код.

Давайте предположим, что мы уже сделали эмулятор (самое сложное!). Теперь наш путь станет легче. Мы можем своппить регистры и даже переставлять инструкции местами в некоторых частях вируса. Также мы можем генерировать различные варианты одной и той же инструкции.

Этот метод намного более эффективен, чем все остальные. Я думаю, что нам нужно идти по этому пути, вместо того чтобы тратить время на бесполезные техники, использование которых не усложняет обнаружение вируса. Представьте себе все возможные альтернативы операции mov reg,imm. Почти бесконечность!

Итак, давайте подумаем: что будет, если каждый раз мы будем заменять простую операцию блоком, который выполняет те же действия? В результате множественных пермутаций вируса, его тело станет длиннее, и будет занимать много места на диске, а зараженные программы будут выполняться заметно дольше из-за появления целой кучи бессмысленных команд. Таким образом, перед нами встает еще одна проблема: кроме расширения кода (expanding), мы должны позаботиться и о его сжатии (shrinking), так чтобы убрать лишние опкоды и сохранить дисковое пространство. Я думаю, Вы уже поняли, что сжимать код гораздо труднее, чем расширять. Также не нужно забывать, что в одних местах нужно расширять, а в других сжимать код... ммм... закон компенсации!

Вот как с моей точки зрения должен работать движок: случайным образом расширять или сжимать.

[ Проблемы ]

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

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

Со сжатием все обстоит несколько сложнее. Я думаю, что возможным решением является хранение в теле вируса шаблонов всех возможных путей расширения инструкций. Таким образом, при просмотре кода, мы (и не только мы – прим. пер.) сможем видеть "базовый" код данного блока. Я надеюсь, что Вы поняли это.

[ Резюме ]

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

[ Стоит ли овчинка выделки? ]

Ммм... сложный вопрос. Очевидно, да. Но если Вы читали статью 'Polymorphism and Grammars' by Qozah (вышла в 29A#4 – ОЧЕНЬ советую Вам прочитать это!), то поймете, что обнаружить можно любой вирус. Мы просто пытаемся сделать жизнь AV'еров тяжелее, ведь им придется работать гораздо больше, чтобы найти наш вирус и сделать против него лекарство. В любом случае, мы тратим кучу времени на метаморфные вирусы, а AV обнаруживают их гораздо быстрее.

Итак, можно сделать вывод, что иетаморфизм – техника только для элитных вирмейкеров - тех гуру ассемблера, которые постоянно удивляют нас. Наверное единственная причина, по которой я хочу создать метаморфный вирус, это показать, что кодер, сделавший это был кем-то 'особенным', не человеком из толпы вирусописателей, которые только начали делать простые вирусы с препроцессорной резидентностью (о, черт, я причислил себя к толпе...) под Win32.

Создание метаморфный вирусов – занятие для настоящих ассемблерщиков, способных сделать с помощью своих ассемблеров практически все что угодно. Так что держитесь подальше, если Вам кажется тяжелым написать хотя бы полиморфный вирус. Это не для Вас.

Вернемся к нашему вопросу. Есть две точки зрения:

  • - Метаморфизм – это хорошо, если Вы хотите испытать свои умственные способности, и Вы достаточно сообразительны, чтобы понять это. AV'еры будут удивлены Вашими кодерскими навыками и сможете выделиться из толпы других кодеров. -
  • Метаморфизм не подходит Вам, если Вы пытаетесь сделать абсолютно невидимый вирус. Обнаружить можно любой вирус и рано или поздно это произойдет, так что лучше Вам заняться чем-нибудь другим.

Вам все понятно? Надеюсь на это.

[ Заключение ]

Я надеюсь, Вы заметили, насколько серьезно я поработал, перед тем как написать эту статью. Вы ошибаетесь (если Вы знаете меня лично, то поймете почему ;), но я старался быть объективным, чтобы рассмотреть под всеми углами различные техники метаморфизма. Если Вы что-то не поняли, дайте мне знать, и я попытаюсь развеять Ваши сомнения.

Я ни в коем случае не пытался показать себя элитным кодером, с помощью этой статьи, так как знаю, что я им не являюсь. Мне пришлось пройти длинный путь, чтобы стать одним из избранных. Самое главное, всегда оставаться скромным и не заставлять людей ждать от тебя чего-то такого. В конце концов, когда Вы сделаете что-нибудь стоящее, то сможете всех удивить. Это моя философия как VX'ера, можете ей следовать если хотите.

Я закончил писать этот документ 9 сентября 1999 года (9-9-99), слушая по радио, бред о том, что 2000-ый год – это вирус, что все компьютеры заражены этим вирусом и прочую чепуху. Больше всего ненавижу, когда невежественные люди говорят о вещах, в которых совершенно не разбираются. Невежество всегда было оружием в руках тоталитаристов. Уничтожьте невежество и мир изменится к лучшему. Черт, я опять заговорил о политике! :) Не могу держать себя в руках...

Что ж, надеюсь, что эта небольшая статья помогла Вам в Ваших попытках накодить метаморфный вирус. Становитесь элитой (придется и себе написать что-нибудь для такой цели)!

- You can't smell your own shit under your knees - (Marilyn Manson)

2002-2013 (c) wasm.ru