Полиморфный генератор — своим руками

       

Ступень2: расшифровщик из кирпичиков


Идея: расшифровщик вируса имеет постоянный алгоритм, но состоит из произвольно выбираемой последовательности команд. Звучит страшновато, но реализуется тривиально. Возьмем в качестве наглядно-агитационного пособия расшифровщик, изображенный на листинге 4. А теперь попробуем подобрать синонимы для каждой из слагающих его машинных команд (заботится об оптимизации необязательно). Получится примерно так:

MOV ESI,offset body_begin à LEA ESI,body_begin;MOV ESI,offset body_begin-1/INC ESI;

MOV EDI, ESI à PUSH ESI/POP EDI; XOR EDI,EDI/ADD EDI,ESI;

LODSB à MOV AL,[ESI]/INC ESI; SUB AL,AL/SUB AL,[ESI]/NOT AL/INC ESI/ADD AL,1

XOR AL,66h à XOR AL, 6/XOR AL, 60h

Листинг 6 инструкции и их синонимы

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

       LEA ESI, body_begin

       PUSH ESI

       POP EDI

       MOV ECX, offset body_end - body_begin + 2

       DEC ECX

       DEC ECX

my_begin:

       MOV AL,[ESI]

       INC ESI

       XOR AL, 6

       XOR AL, 66

       MOV [EDI], AL

       SUB EDI,-1

       ADD ECX,-1

       JNZ my_begin

Листинг 7 случайно сгенерированный расшифровщик

Поскольку, "синонимы" команд подготавливаются вручную еще на этапе ассемблирования, автоматически определять их длины совсем необязательно! Реализация получается простая как два пальца. Единственную проблему представляют метки. Как видно, и абсолютное, и относительное смещение my_begin изменилось. Мы не можем, не имеет права на этапе ассемблирования подставлять в команду JNZ смещение my_begin, поскольку оно будет указывать в космос. Что делать? Вот одно из решений проблемы. Вместо метки подставляем команду сохранения текущего EIP в один из свободных регистров общего назначения, а затем прыгаем на него:

my_begin:

       CALL

$+5      ; прыгаем на следующую команду, занося EIP


в стек

       POP EBX              ; выталкиваем EIP из стека

       PUSH EBX      ; ( как вариант, можно дать INC EBX)

       ...

       JNZ

$+4              ; выход из расшифровщика

       JMP EBX              ; переход на my_begin с динамич

Листинг 8 автоматическое определение смещений меток

На первый взгляд, каждое последующее поколение вируса выглядит полностью непохожим на предыдущее и по сигнатурам он уже не детектируется. Ведь если подобрать побольше команд-синонимов, количество возможных комбинаций может составить не один миллион. Тресни моя антивирусная база! Тем не менее, в каждой позиции расшифровщика встречается строго определенная комбинаций команд, поэтому специальный алгоритм отождествления сможет надежно ее распознать. Естественно, для этого антивирусникам придется потрудиться и запастись хорошей травой. Был как-то у одной такой компании мешок отменной травы, так за месяц скурили! Ну это ладно.

Не стоит забывать и про эмулятор. Расшифровав основной код вируса, разработчики запросто отождествят его по сигнатуре. Поэтому, антиотладочные приемы должны быть! Здесь за уникальность можно уже не опасаться (команды-синонимы делают свое), оттянувшись на полную катушку со всем набором SSE и прочих векторных команд, до которых антивирусным эмуляторам еще ползти и ползти…


Содержание раздела