![]() |
![]() |
![]() |
Сейчас в моде куча различных видов морфинга - полиморфинг, метаморфинг и тп. Особняком идет пермутация. Из бывшего СНГ я слышал всего о паре человек, которые этим занимались (занимаются).(если кто-то еще этим занимается, пишите на [email protected] или кидайте в борду TopDevic'а = http://topdev.cjb.net) И так.. - Reminder. Недоделанный пермутатор - Zombie, с его несколькими версиями пермутаторов и метаморфиков. - 2b, с его Way To Full Morphing (гы... чем-то созвучно с Way To Hell :) - Эгм...Я... Написал я metamorphic engine, послал Янушу, а он сказал что это не статья и опубликовать не сможет. Вобщем там и смотреть не на что, зато с User Interfac'ом. :) Что представляет из себя фулморфинг должно быть понятно.. При написании чего-нибудь подобного, всегда возникают 3 бооольшие проблемы (1 из них не очень большая,но...) 1. Расчет прыжков 2. Определение данных 3. Определение комманд, которые эти данные используют И так.. 1. Расчет прыжков довольно прост. Смотри примеры Reminder'a. 2. А вот это уже лажа. Есть несколько способов избавления от проблемы. - Хранить все данные в отдельной области, которая шифруется и специальным образом обрабатывается пермутатором. Это все хорошо, но немного напряжно. - Данные разместить в коммандах. Например сделать цепочку Push'ов которые в стеке восстановят все нужные данные. Пермутатор возьмет данные из стека и создаст новую цепочку Push'ей которые содержат данные. Довольно не плохо, но вот размер катастрофически возрастает. - Мой метод (немного позаимствованный у дизассемблера (типа IDA, Sourcer,etc)). Описание смотри ниже. 3. Опять таки, если все делается через стек, то такой проблемы не возникает совсем. Иначе приходится содержать дизассемблер, определять тип инструкции и тп. И так, мой метод... Работает в 2 прохода. Первый проход. Идем по коду (псевдо-эмулируя), прыгая по Jump'ам и рекурсивно обрабатываем Call'ы. При этом создаем карту кода/данных. Где эмуляция прошла - код, где остались пятна - данные. Естественно, на каждую комманду, даже по биту - жирно, поэтому я сделал все в виде блоков. Блок характеризуется смещением и длиной. Блоки можно обьединять, если они пересекаются и тп. Сильная экономия памяти. Заодно ведем таблицу Jmp'ов, комманд, которые работают с данными, и тп. Второй проход. Собственно пермутация. На входе - смещение на пермутируемый код. Идем по буферу. Напрямую (без обрабатывания Call'ов и тп). Если данное смещение принадлежит коду - берем размер комманды, возможно пермутируем ее и добавляем мусор. Если не принадлежит коду - просто переписываем байт. За одно проверяем, указывает на это смещение что-то (Jmp,данные и тп). Если да, то заменяем в таблицах нужное смещение. По окончании всех проходов, пропатчиваем Call'ы,Jmp'ы,смещения на данные. Таким образом происходит пермутация кода без затрагивания данных. Проблемы 1 и 2 решены. Остается последняя проблема. Я использую простейший дизассемблер, который опеределяет обращается ли данная комманда к данным или нет. Естественно, могут быть глюки, но тут уж все на голову программера ложится. Вот все это я и реализовал в Deviator's Morphing Engine. Дополнения. Вспоминаем инструкции типа Jxx (Jz,Jnz,etc). Они дают прыжок максимум на +-127 байт. После добавления мусора, комманда может не "попасть" туда, куда нужно. На текущий момент Jmp Short (0EBh) и все Jxx заменяются на их длинные эквиваленты при пермутации. Аналогично делается с Loop'ами Фичи - Вроде первый почти полноценный пермутатор - эээээ...а какие еще фичи у пермутатора быть могут ? Текущие недостатки. - Исходный буффер не должен пересекатся с выходным буфером. (недостаток движка) - Внешние данные не обрабатываются. Короче, пермутация должна происходить всего кода. (скоро исправлю) - Плохой алгоритм пермутации комманд и добавления мусора - Возможны некоторые глюки. :) Прилагающийся вирус - пермутант. Я так подумал - мусор должен быть не отсеиваемым, иначе никакого смысла в мусоре нет. И тут встречается проблема - при пермутации отпермутированной копии, мусор также пермутируется. В результате размер катастрофически увеличивается. Deviator//HAZARD. |
||
![]() |
![]() |
![]() |