;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%; ; ГЕНЕРАТОР МУСОРНЫХ ИНСТРУКЦИЙ V. 0.4 (x) 2004 СЛОН http://slon.wronger.com ; ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%; ; Использование: mov edi,БУФЕР ДЛЯ КОДА ; ; mov ecx,ДЛИНА КОДА ; ; mov ebx,НЕ ИСПОЛЬЗУЕМЫЕ РЕГИСТРЫ(_all) ; ; call garbage ; ;------------------------------------------------------------------------------; ; Результат: сгенерированный код в edi ; ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%; ; ВЕРСИЯ 0.3 Генерация инструкций по заданным статистическим ; ; характерстикиам(они получены в результате анализа ; ; большого количества файлов формата "PE") ; ;------------------------------------------------------------------------------; ; ВЕРСИЯ 0.2 Добавлены новые инструкции x86, так же добавлены ; ; инструкции сопроцессора (x87) ; ;------------------------------------------------------------------------------; ; ВЕРСИЯ 0.1 Реализация многих инструкций x86 процессора, ; ; случайная комбинация инструкций ; ;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%; ;----[Главная подпрограмма генератора мусора]----------------------------------; garbage: ; Подпрограмма генерации ; мусорных инструкций push edx ; Сохраняем в стэке push ecx ; edx, ecx, esi, ebp, ecx, eax push esi ; push ebp ; push ebx ; push eax ; call delta_offset ; delta_offset: pop ebp ; Получаем дельта смещение sub ebp,offset delta_offset ; call r_init ; Инициалицируем ГСЧ __st__: test ecx,ecx ; Если все инструкции jz landing ; сгенерированы, то на выход mov eax,21 ; Выбираем случайным образом call brandom32 ; вариант генерации мусорных ; инструкций shl eax,1 ; Умножаем eax на 2 call __freq__ ; Выбираем блок инструкций по ; статистической вероятности test eax,eax ; Если не выбрали, то пытаемся jz __st__ ; снова lea esi,[ebp+mega_table] ; В esi смещение на таблицу ; относительных смещений add esi,eax ; к esi добавляем eax xor eax,eax ; Обнуляем eax lodsw ; В ax загружаем ; относительное смещение от ; метки __st__ lea esi,[ebp+__st__] ; В esi кладём смещение ; метки __st__ add eax,esi ; Добавляем смещение ; подпрограммы call eax ; Вызываем её jmp __st__ ; Переход на __st__ ;----[Завершение работы генератора мусора]-------------------------------------; landing: inc [ebp+__generation] ; Увеличиваем счётчик поколений cmp [ebp+__generation],10 ; Если это не 10 поколение, то jne __ne__ ; идём на выход mov [ebp+__generation],0 ; Сбрасываем счётчик поколений call gen_mutation ; Вызываем изменение 1 случ. ; мат. ожидания mov [ebp+__cross1],ecx ; Выбираем 1 опр. фактор ; эволюции call gen_mutation ; Вызываем изменение 2 случ. ; мат. ожидания mov [ebp+__cross2],ecx ; Выбираем 2 опр. фактор ; эволюции __ne__: mov ecx,[ebp+__cross1] ; Производим селекцию 1 опр. call gen_crossover ; фактора эволюции mov ecx,[ebp+__cross1] ; Производим селекцию 2 опр. call gen_crossover ; фактора эволюции pop eax ; pop ebx ; pop ebp ; pop esi ; Восстанавливаем регистры pop ecx ; pop edx ; ret ; Возврат из подпрограммы ;----[Подпрограмма выбора стат. вероятностей]----------------------------------; __freq__: push eax ; Сохраняем eax в стэке lea esi,[ebp+__freq_table] ; Загружаем указатель на таблицу add esi,eax ; с мат. ожиданиями lodsw ; Загружаем в ax мат.ожидание mov edx,eax ; Переносим её в edx mov eax,1001 ; Генеририуем случайное число call brandom32 ; в интервале 0..1000 cmp edx,eax ; Проверяем попали ли мы? jge __exit__ ; Если попали, то на выход mov 4 ptr [esp],0 ; Нет обнулим верхушку стэка __exit__: pop eax ; Восстанавливаем eax из стэка ret ; Возврат из подпрограммы ;----[Подпрограмма изменения мат. ожидания]------------------------------------; gen_mutation: mov eax,21 ; Выбираем случайным образом call brandom32 ; вариант генерации мусорных ; инструкций shl eax,1 ; Умножаем eax на 2 lea esi,[ebp+__freq_table] ; В esi смещение на таблицу ; мат. ожиданий опкодов add esi,eax ; к esi добавляем eax xor eax,eax ; Обнуляем eax lodsw ; В ax загружаем мат. ; ожидание call brandom32 ; Генерируем СЧ в диапазоне sub esi,2 ; 0..мат.ожидание-1 и уменьшаем ; esi на 2 sub 2 ptr [esi],ax ; Вычитаем из мат. ожидания ; Наше случаное число push eax ; Сохраняем в стэке СЧ mov eax,21 ; Выбираем случайным образом call brandom32 ; вариант генерации мусорных ; инструкций shl eax,1 ; Умножаем eax на 2 mov ecx,eax ; lea esi,[ebp+__freq_table] ; В esi смещение на таблицу ; мат. ожиданий опкодов add esi,eax ; к esi добавляем eax pop eax ; Восстанавливаем из стэка СЧ add 2 ptr [esi],ax ; И добавляем его к другому ; Мат. ожиданию ret ; Возврат из подпрограммы ;----[Подпрограмма селекции опр. фактора эволюции]-----------------------------; gen_crossover: mov eax,21 ; Выбираем случайным образом call brandom32 ; вариант генерации мусорных ; инструкций shl eax,1 ; Умножаем eax на 2 lea esi,[ebp+__freq_table] ; В esi смещение на таблицу ; мат. ожиданий опкодов add esi,eax ; к esi добавляем eax xor eax,eax ; Обнуляем eax lodsw ; В ax загружаем мат. ; ожидание call brandom32 ; Генерируем СЧ в диапазоне sub esi,2 ; 0..мат.ожидание-1 и уменьшаем ; esi на 2 sub 2 ptr [esi],ax ; Вычитаем из мат. ожидания ; Наше случаное число push eax ; Сохраняем в стэке СЧ lea esi,[ebp+__freq_table] ; В esi смещение на таблицу ; мат. ожиданий опкодов add esi,ecx ; к esi добавляем eax pop eax ; Восстанавливаем из стэка СЧ add 2 ptr [esi],ax ; И добавляем его к другому ; Мат. ожиданию ret ; Возврат из подпрограммы ;----[Генерация инструкций JXX SHORT - 0x70..0x7f]-----------------------------; __jxx_short: mov eax,50 ; Генерируем случайное число call brandom32 ; в диапазоне 0..49 push eax ; Сохраняем eax в стэке add eax,2 ; Добавляем длину перехода cmp eax,ecx ; Проверяем не больше ли длины ; Всех инструкций pop eax ; Восстанавливаем из стэка eax jle __gen1__ ; Если число превышает длину ret ; то выходим из подпрограммы __gen1__: ; push eax ; Кладём eax опять в стэк mov eax,10 ; Выбираем случайным образом call brandom32 ; число от 0..9 add al,70h ; Добавляем 70h stosb ; и кладём его в буфер pop eax ; Вынимаем из стэка eax и stosb ; кладём в буфер mov edx,eax ; Кладём число в edx push ecx ; Сохраняем ecx в стэке mov ecx,edx ; Генерируем рекурсивно call garbage ; мусор между переходом pop ecx ; Восстанавливаем ecx ; В итоге у нас получается ; случайно выбранный, ; условный переход: ; .............................. ; jae next ; mov eax,0 ; next: nop ; .............................. sub ecx,2 ; Уменьшаем счётчик на 2 sub ecx,edx ; И на длину перехода ret ; Возврат из подпрограммы ;----[Генерация инструкций NOT/NEG - 0xf7]-------------------------------------; __not_r32: cmp cl,2 ; Если длина генерируемой jge __g1__ ; инструкции меньше 2, то ret ; Возврат из подпрограммы __g1__: mov al,0f7h ; Помещаем в al - 0f7h stosb ; и кладём его в буфер mov dl,0d0h ; Помещаем в dl - 0d0h mov eax,2 ; Генерируем случайное число call brandom32 ; в диапазоне 0..1 shl eax,3 ; Умножаем его на 8 add dl,al ; Добавляем к dl - al call free_reg ; Вызываем подпрограмму ; получения свободных ; регистров add al,dl ; Добавляем к al - dl stosb ; и кладём его в буфер ; В итоге у нас получается ; случайно выбранная ; инструкция NOT/NEG: ; .............................. ; not eax ; .............................. sub ecx,2 ; Уменьшаем счётчик на 2 ret ; Возврат из подпрограммы ;----[Генерация инструкций JXX NEAR - 0x0f 0x80..0x0f 0x89]--------------------; __jxx_near: mov eax,50 ; Генерируем случайное число call brandom32 ; в диапазоне 0..49 push eax ; Сохраняем его в стэке add eax,6 ; Добавляем длину перехода cmp eax,ecx ; Проверяем не больше длины ; Всех инструкций pop eax ; Восстанавливаем eax из стэка jle __gen2__ ; Если число превышает длину ret ; то выходим из подпрограммы __gen2__: ; push eax ; Сохраняем в стэке eax mov al,0fh ; Помещаем в al - 0fh stosb ; и кладём его в буфер mov eax,10 ; Выбираем случайным образом call brandom32 ; число от 0..9 ; add al,80h ; Добавляем 80h stosb ; и кладём его в буфер pop eax ; Вынимаем из стэка eax stosd ; Помещаем его в буфер mov edx,eax ; Кладём в edx - eax push ecx ; Сохраняем ecx в стэке mov ecx,edx ; Генерируем рекурсивно call garbage ; мусор между переходом pop ecx ; Восстанавливаем ecx ; В итоге у нас получается ; случайно выбранный, ; условный, переход: ; .............................. ; je next ; push 0 ; next: push 64 ; .............................. sub ecx,6 ; Уменьшаем счётчик на 6 sub ecx,edx ; И на длину инструкций ; ret ; Возврат из подпрограммы ;----[Генерация инструкций сопроцессора - 0xdc]--------------------------------; __x87: cmp cl,2 ; Если длина генерируемой jge __g2__ ; инструкции меньше 2, то ret ; Возврат из подпрограммы __g2__: mov al,0dch ; Кладём в al - 0dch stosb ; И помещаем al в буфер mov eax,02fh ; Генерируем случайное число call brandom32 ; в интервале 0..2eh add al,0c0h ; Добавляем к числу 0c0h stosb ; и помещаем сумму в буфер ; В итоге у нас получается ; случайно выбранная ; инструкция сопроцессора: ; .............................. ; fadd st(0),st ; .............................. sub ecx,2 ; Уменьшаем счётчик на 2 ret ; Возврат из подпрограммы ;----[Генерация инструкций сравнения - 0x3a]-----------------------------------; __cmp_r32_r32: cmp cl,2 ; Если длина генерируемой jge __g3__ ; инструкции меньше 2, то ret ; Возврат из подпрограммы __g3__: mov dl,3ah ; Помещаем в dl - 03ah mov eax,3 ; Получаем случайное число call brandom32 ; в диапазоне 0..2 add al,dl ; Добавляем к al - dl stosb ; Затем помещаем al в буфер call rnd_reg ; Получаем случайный регистр shl eax,3 ; Умножаем eax на 8 add al,0c0h ; Добавляем к al - 0c0h mov dl,al ; помещаем в dl - al call rnd_reg ; Получаем случайный регистр add al,dl ; Добавляем к al - dl stosb ; И помещаем al в буфер ; В итоге у нас получается ; случайно выбранная ; инструкция CMP: ; .............................. ; cmp eax,esp ; .............................. sub ecx,2 ; Уменьшаем счётчик на 2 ret ; Возврат из подпрограммы ;----[Генерация инструкций XOR - 0x33]-----------------------------------------; __xor_r32_r32: cmp cl,2 ; Если длина генерируемой jge __g4__ ; инструкции меньше 2, то ret ; Возврат из подпрограммы __g4__: mov al,33h ; Помещаем в al - 33h stosb ; И затем кладём это в буфер call free_reg ; Вызываем подпрограмму ; получения свободных ; регистров shl eax,3 ; Умножаем eax на 8 add al,0c0h ; Добавляем к al - 0c0h mov dl,al ; помещаем в dl - al call rnd_reg ; Получаем случайный регистр add al,dl ; Добавляем к al - dl stosb ; И помещаем al в буфер ; В итоге у нас получается ; случайно выбранная ; инструкция XOR: ; .............................. ; xor eax,esp ; .............................. sub ecx,2 ; Уменьшаем счётчик на 2 ret ; Возврат из подпрограммы ;----[Генерация инструкций TEST - 0x84]----------------------------------------; __test_r32_r32: cmp cl,2 ; Если длина генерируемой jge __g5__ ; инструкции меньше 2, то ret ; Возврат из подпрограммы __g5__: mov dl,084h ; Помещаем в dl - 084h mov eax,2 ; Получаем случайное число call brandom32 ; в диапазоне 0..1 add al,dl ; Добавляем к al - dl stosb ; И затем кладём это в буфер call rnd_reg ; Вызываем подпрограмму ; получения случайного ; регистра add al,0c0h ; Добавляем к al - 0c0h mov dl,al ; помещаем в dl - al call rnd_reg ; Получаем случайный регистр add al,dl ; Добавляем к al - dl stosb ; И помещаем al в буфер ; В итоге у нас получается ; случайно выбранная ; инструкция TEST: ; .............................. ; test eax,esp ; .............................. sub ecx,2 ; Уменьшаем счётчик на 2 ret ; Возврат из подпрограммы ;----[Генерация инструкций MOV, XCHG - 0x87,0x89,0x8b]-------------------------; __mov_r32_r32: cmp cl,2 ; Если длина генерируемой jge __g6__ ; инструкции меньше 2, то ret ; Возврат из подпрограммы __g6__: mov eax,3 ; Генерируем СЧ в call brandom32 ; диапазоне 0..2 test eax,eax ; Проверяем, как опкод мы jnz __ng1__ ; будем генерировать ; Если не 0, то 0x8b mov eax,10 ; Генерируем СЧ в call brandom32 ; диапазоне 0..9 test eax,eax ; Проверяем какой опкод мы jnz __ng2__ ; будем генерировать ; Если не 0, то 0x89 mov al,87h ; Будем генерировать 0x87 jmp __ag1__ ; Идём дальше __ng2__: mov al,89h ; Будем генерировать 0x89 jmp __ag1__ ; Идём дальше __ng1__: mov al,8bh ; Помещаем в al - 8bh __ag1__: stosb ; Потом помещаем al в буфер call free_reg ; Вызываем подпрограмму ; получения свободных ; регистров shl eax,3 ; Умножаем eax на 8 add al,0c0h ; Добавляем к al - 0c0h mov dl,al ; помещаем в dl - al call free_reg ; Получаем случайный регистр add al,dl ; Добавляем к al - dl stosb ; И помещаем al в буфер ; В итоге у нас получается ; случайно выбранная ; инструкция MOV, XCHG: ; .............................. ; mov eax,esp ; .............................. sub ecx,2 ; Уменьшаем счётчик на 2 ret ; Возврат из подпрограммы ;----[Генерация инструкций PUSH/POP - 0x50..0x57;0x58..0x5f]-------------------; __push_r32: mov eax,10 ; Генерируем СЧ в call brandom32 ; диапазоне 0..9 mov edx,eax ; Кладём его в edx add al,2 ; Доавляем к al - 2 cmp eax,ecx ; Если длина генерируемой jle __g7__ ; инструкции меньше 2 ; и длины мусора ,то ret ; Возврат из подпрограммы __g7__: call free_reg ; Получаем случайный регистр add al,50h ; Добавляем к al - 50h stosb ; Кладём al в буфер push ecx ; Сораняем ecx в стэке mov ecx,edx ; Генерируем серию call garbage ; мусорных инструкций pop ecx ; Вынимаем ecx из стэка call free_reg ; Вызываем подпрограмму ; получения свободных ; регистров add al,58h ; Добавляем к al - 58h stosb ; И опять кладём al в буфер ; В итоге у нас получается ; случайно выбранная ; инструкции PUSH/POP: ; .............................. ; push eax ; mov eax,2 ; pop ecx ; .............................. sub ecx,edx ; Уменьшаем счётчик на edx sub ecx,2 ; Уменьшаем счётчик на - 2 ret ; Возврат из подпрограммы ;----[Генерация инструкций MOV - 0x0b8]----------------------------------------; __mov_r32_imm32: cmp cl,5 ; Если длина генерируемой jge __g8__ ; инструкции меньше 5, то ret ; Возврат из подпрограммы __g8__: ; call free_reg ; Вызываем подпрограмму ; получения свободных ; регистров add al,0b8h ; Добавляем к al - 0b8h stosb ; И кладём al в буфер xor eax,eax ; Обнуляем eax dec eax ; Теперь eax = 0ffffffffh call brandom32 ; Генерируем случайное stosd ; число ; В итоге у нас получается ; случайно выбранная ; инструкции MOV: ; .............................. ; mov eax,12345678 ; .............................. sub ecx,5 ; Уменьшаем счётчик на 5 ret ; Возврат из подпрограммы ;----[Генерация инструкций JMP SHORT - 0xeb]-----------------------------------; __jmp_short: cmp cl,2 ; Если длина генерируемой jg __g9__ ; инструкции меньше 2, то ret ; Воврат из подпрограммы __g9__: mov eax,50 ; Генерируем случайное число call brandom32 ; в диапазоне 0..49 push eax ; Сохраняем его в стэке add eax,2 ; Добавляем длину перехода cmp eax,ecx ; Проверяем не больше длины pop eax ; Восстанавливаем из стэка jle __gen3__ ; Если число превышает длину ret ; то выходим из подпрограммы __gen3__: ; push eax ; Сохраняем в стэке eax mov al,0ebh ; Кладём в al - 0ebh stosb ; И кладём al в буфер pop eax ; Восстанавливаем из стэка stosb ; Помещаем его в буфер mov edx,eax ; Кладём в edx - eax push ecx ; Сохраняем ecx в стэке mov ecx,edx ; Генерируем рекурсивно call garbage ; мусор между переходом pop ecx ; Восстанавливаем ecx ; В итоге у нас получается ; случайно выбранная ; инструкции JMP SHORT: ; .............................. ; jmp next ; mov ax,22 ; next: nop ; .............................. sub ecx,2 ; Уменьшаем счётчик на 2 sub ecx,edx ; И на длину инструкций ; ret ; Возврат из подпрограммы ;----[Генерация инструкций ADD - 0x81]-----------------------------------------; __add_r32_imm32: cmp cl,6 ; Если длина генерируемой jge g10__ ; инструкции меньше 6, то ret ; Возврат из подпрограммы g10__: mov al,81h ; Кладём в al - 81h stosb ; И помещаем al в буфер mov eax,4 ; Получаем случайное число call brandom32 ; в диапазоне от 0..9 add al,0ch ; Добавляем к нему - 0ch shl al,4 ; Умножаем al на 16 mov dl,al ; Кладём в dl - al mov eax,2 ; Получаем случайное число call brandom32 ; в диапазоне от 0..1 shl al,3 ; Умножаем al на 8 add dl,al ; Добавляем к dl - al call free_reg ; Вызываем подпрограмму ; получения свободных ; регистров add al,dl ; Добавляем к al - dl stosb ; И кладём al в буфер xor eax,eax ; Обнуляем eax dec eax ; Теперь eax = 0ffffffffh call brandom32 ; Генерируем случайное stosd ; число и кладём его в буфер ; В итоге у нас получается ; случайно выбранная ; инструкции ADD: ; .............................. ; add eax,12345678 ; .............................. sub ecx,6 ; Уменьшаем счётчик на 6 ret ; Возврат из подпрограммы ;----[Генерация инструкций LEA - 0x8d]-----------------------------------------; __lea_r32_imm32: cmp cl,6 ; Если длина генерируемой jge __g11__ ; инструкции меньше 6, то ret ; Возврат из подпрограммы __g11__: mov al,8dh ; Кладём в al - 8dh stosb ; И помещаем al в буфер call free_reg ; Вызываем подпрограмму ; получения свободных ; регистров shl eax,3 ; Умножаем eax на - 8 add al,5 ; Добавляем к al - 5 stosb ; И кладём al в буфер xor eax,eax ; Обнуляем eax dec eax ; Теперь eax = 0ffffffffh call brandom32 ; Генерируем случайное число stosd ; И кладём его в буфер ; В итоге у нас получается ; случайно выбранная ; инструкции LEA: ; .............................. ; lea eax,[12345678] ; .............................. sub ecx,6 ; Уменьшаем счётчик на 6 ret ; Возврат из подпрограммы ;----[Генерация инструкций CALL NEAR - 0xe8]-----------------------------------; __call_near: mov eax,50 ; Генерируем случайное число call brandom32 ; в диапазоне 0..49 mov edx,eax ; И кладём его в edx mov eax,50 ; Генерируем случайное число call brandom32 ; в диапазоне 0..49 push eax ; Сохраняем его в стэке add eax,11 ; Добавляем длину перехода add eax,edx ; Добавляем к eax - edx cmp eax,ecx ; Проверяем не больше длины pop eax ; Восстанавливаем из стэка jle __gen4__ ; Если число превышает длину, то ret ; Возврат из подпрограммы __gen4__: push edx ; Сохраняем в стэке edx push eax ; Сохраняем в стэке eax mov al,0e8h ; Кладём в al - 0e8h stosb ; И помещаем al в буфер mov eax,[esp] ; Восстанавливаем eax inc eax ; Увеличиваем eax на - 1 stosd ; Кладём eax в буфер xor eax,eax ; Обнуляем eax dec eax ; Теперь в eax - 0ffffffffh call brandom32 ; Генерируем СЧ и stosb ; Кладём его в буфер pop edx ; Вынимаем из стэка в edx push ecx ; Сохраняем ecx в стэке mov ecx,edx ; Генерируем рекурсивно call garbage ; мусор между переходом pop ecx ; Восстанавливаем ecx mov al,55h ; stosb ; Кладём в буфер 055h mov ax,0ec8bh ; stosw ; Кладём в буфер 0ec8bh push edx ; Кладём edx в стэк mov edx,[esp+4] ; Вынимаем из стэка в edx push ecx ; Сохраняем ecx в стэке mov ecx,edx ; Генерируем рекурсивно call garbage ; мусор между переходом pop ecx ; Восстанавливаем ecx mov al,5dh ; Кладём в буфер 05dh stosb ; call free_reg ; Вызываем подпрограмму ; получения свободных ; регистров add al,58h ; Добавляем к al - 58 stosb ; И опять кладём al в буфер ; В итоге у нас получается ; случайно выбранная ; инструкция CALL NEAR: ; .............................. ; mov eax,12345678h ; call next ; add edx,34567h ; next: ; push ebp ; mov ebp,esp ; xor eax,edx ; pop ebp ; pop edx ; .............................. sub ecx,11 ; Уменьшаем счётчик на 11 pop edx ; Вынимаем из стэка в edx sub ecx,edx ; Уменьшаем на длину инструкций pop edx ; Вынимаем из стэка в edx sub ecx,edx ; Уменьшаем на длину инструкций ; ret ; Возврат из подпрограммы ;----[Генерация инструкций SHL - 0xc1]-----------------------------------------; __shl_r32_imm8: cmp cl,3 ; Если длина генерируемой jge __g12__ ; инструкции меньше 3, то ret ; Возврат из подпрограммы __g12__: mov al,0c1h ; Кладём в al - 0c1h stosb ; И помещаем al в буфер mov eax,6 ; Генерируем случайное число call brandom32 ; в диапазоне 0..5 shl eax,3 ; Умножаем его на 8 add al,0c0h ; Добавляем к нему - 0c0h mov dl,al ; Помещаем в dl - al call free_reg ; Вызываем подпрограмму ; получения свободных ; регистров add al,dl ; Добавляем к al - dl stosb ; И помещаем al в буфер mov eax,256 ; Генерируем случайное число call brandom32 ; в диапазоне 0..255 stosb ; И кладём его в буфер ; В итоге у нас получается ; случайно выбранная ; инструкции SHL,ROL, ...: ; .............................. ; shl ebp,04 ; .............................. sub ecx,3 ; Уменьшаем счётчик на 3 ret ; Возврат из подпрограммы ;----[Генерация иструкций XADD - 0x0f 0x0a3 ...]-------------------------------; __xadd_r32_r32: cmp cl,3 ; Если длина генерируемой jge __g13__ ; инструкции меньше 6, то ret ; Возврат из подпрограммы __g13__: mov al,0fh ; Кладём в al - 0fh stosb ; И помещаем al в буфер lea esi,[ebp+__3_byte_opcode]; Кладём в esi указатель на ; таблицу частей 3-х байтных ; инструкций mov eax,14 ; Генерируем случайное число call brandom32 ; в диапазоне 0..13 add esi,eax ; Прибавляем к esi - eax movsb ; Перемещаем байт в буфер mov dl,0c0h ; Кладём в dl - 0с0h call free_reg ; Вызываем подпрограмму ; получения свободных ; регистров shl eax,3 ; Умножаем eax на 8 add dl,al ; Добавляем к dl - al call free_reg ; Вызываем подпрограмму ; получения свободных ; регистров add al,dl ; Добавляем к al - dl stosb ; И помещаем al в буфер ; В итоге у нас получается ; случайно выбранная ; инструкции XADD,IMUL, ...: ; .............................. ; xadd eax,eax ; .............................. sub ecx,3 ; Уменьшаем счётчик на 3 ret ; Возврат из подпрограммы ;----[Генерация инструкций MOV - 0x66 0xb8..0xbf]------------------------------; __mov_r16_imm16: cmp cl,4 ; Если длина генерируемой jge __g14__ ; инструкции меньше 4, то ret ; Возврат из подпрограммы __g14__: mov al,066h ; Кладём в al - 066h stosb ; И помещаем al в буфер mov dl,0b8h ; Помещаем в dl - 0b8h call free_reg ; Вызываем подпрограмму ; получения свободных ; регистров add al,dl ; Добавляем к al - dl stosb ; И помещаем al в буфер xor eax,eax ; Обнуляем eax dec eax ; Теперь в eax - 0ffffffffh call brandom32 ; Генерируем СЧ stosw ; И помещаем его в буфер ; В итоге у нас получается ; случайно выбранная ; инструкции MOV: ; .............................. ; mov ax,3452 ; .............................. sub ecx,4 ; Уменьшаем счётчик на 4 ret ; Возврат из подпрограммы ;----[Генерация инструкций CMOVA - 0x0f 0x40..0x4f]----------------------------; __cmova_r32_r32: cmp cl,3 ; Если длина генерируемой jge __g15__ ; инструкции меньше 6, то ret ; Возврат из подпрограммы __g15__: mov al,0fh ; Кладём в al - 0fh stosb ; И помещаем al в буфер mov eax,15 ; Генерируем случайное число call brandom32 ; в диапазоне 0..14 add al,40h ; Добавляем к al - 40h stosb ; И помещаем al в буфер call free_reg ; Берём случайный регистр shl eax,3 ; Умножаем его на 8 add al,0c0h ; Добавляем к нему - 0c0h mov dl,al ; Помещаем в dl - al call rnd_reg ; Вызываем подпрограмму ; получения свободных ; регистров add al,dl ; Добавляем к al - dl stosb ; И помещаем al в буфер ; В итоге у нас получается ; случайно выбранная ; инструкции CMOVA: ; .............................. ; cmova eax,edx ; .............................. sub ecx,3 ; Уменьшаем счётчик на 3 ret ; Возврат из подпрограммы ;----[Генерация инструкций PUSH/POP - 0x6a, 0x0ff 0x0f0..0x0f7;0x58..0x5f]-----; __push_r32_2: mov eax,10 ; Генерируем СЧ call brandom32 ; в диапазоне 0..9 mov edx,eax ; Кладём в edx - eax add al,3 ; Добавляем к al - 3 cmp eax,ecx ; Если длина генерируемых jle __g16__ ; инструкций меньше ,то ret ; Возврат из подпрограммы __g16__: mov eax,4 ; Генерируем СЧ call brandom32 ; в диапазоне 0..3 test eax,eax ; Если оно не равно 0, то jnz __ng3__ ; Переходим на метку __ng3__ mov al,6ah ; Кладём в al - 06ah stosb ; Помещаем al в буфер xor eax,eax ; Обнуляем eax dec eax ; Теперь в eax - 0ffffffffh call brandom32 ; Генерируем СЧ stosb ; Кладём в буфер jmp __gen5__ ; Идём на генерацию мусора __ng3__: push edx ; Сохраняем в стэке edx mov al,0ffh ; Кладём в al - 0ffh stosb ; И помещаем al в буфер mov dl,0f0h ; Кладём в dl - 0f0h call free_reg ; Получаем свободный регистр add al,dl ; Добавляем к al - dl stosb ; И помещаем al в буфер pop edx ; Вынимаем из стэка edx __gen5__: push ecx ; Сохраняем ecx в стэке mov ecx,edx ; Кладём в ecx - edx call garbage ; Генериуем серию мусора pop ecx ; Восстанавливаем ecx из стэка call free_reg ; Вызываем подпрограмму ; получения свободных ; регистров add al,58h ; Добавляем к al - 58h stosb ; И опять кладём al в буфер ; В итоге у нас получается ; случайно выбранная ; инструкции PUSH/POP: ; .............................. ; push eax ; mov eax,2345 ; pop ecx ; .............................. sub ecx,edx ; Уменьшаем счётчик на edx sub ecx,3 ; Уменьшаем счётчик на 3 ret ; Возврат из подпрограммы ;----[Генерация инструкций PUSH - 0x68,0x58..0x5f]-----------------------------; __push_imm32: mov eax,10 ; Генерируем СЧ в call brandom32 ; диапазоне 0..9 mov edx,eax ; Помещаем в edx - eax add al,6 ; Добавляем к al - 6 cmp eax,ecx ; Если длина генерируемых jle __g17__ ; инструкций меньше, то ret ; Возврат из подпрограммы __g17__: mov al,68h ; Кладём в al - 68h stosb ; Помещаем al в буфер xor eax,eax ; Обнуляем eax dec eax ; Теперь в eax - 0ffffffffh call brandom32 ; Генерируем СЧ stosd ; Кладём его в буфер push ecx ; Сохраняем ecx в стэке mov ecx,edx ; Кладём в ecx - edx call garbage ; Генерируем серию мусора pop ecx ; Восстанавливаем ecx из стэка call free_reg ; Вызываем подпрограмму ; получения свободных ; регистров add al,58h ; Добавляем к al - 58h stosb ; И опять кладём al в буфер ; В итоге у нас получается ; случайно выбранная ; инструкции PUSH/POP: ; .............................. ; push eax ; add eax,42346 ; pop ecx ; .............................. sub ecx,edx ; Уменьшаем счётчик на edx sub ecx,6 ; Уменьшаем счётчик на 6 ret ; Возврат из подпрограммы ;----[Генерация однобайтовых инструкций - 0x40..0x4f;0x0f2;0x0f3...]-----------; __one_byte: mov eax,3 ; Генерируем случайное число call brandom32 ; в диапазоне 0..2 cmp al,1 ; Если число = 1, то jne __not_inc_ ; генерируем инструкцию INC call free_reg ; Вызываем подпрограмму ; получения свободных ; регистров add al,40h ; Добавляем к al - 40h stosb ; Помещаем al в буфер ; В итоге у нас получается ; случайно выбранная ; инструкции INC: ; .............................. ; inc eax ; inc ebp ; .............................. jmp __q__ ; Идём на выход __not_inc_: cmp al,2 ; Если число = 2, то jne __not_dec_ ; Идём на выход call free_reg ; Вызываем подпрограмму ; получения свободных ; регистров add al,48h ; Добавляем к al - 48h stosb ; Помещаем al в буфер ; В итоге у нас получается ; случайно выбранная ; инструкции DEC: ; .............................. ; dec eax ; .............................. jmp __q__ ; Идём на выход __not_dec_: lea esi,[ebp+__1_byte_opcode]; Кладём в esi указатель на ; таблицу однобайтных ; инструкций mov eax,8 ; Генерируем случайное число call brandom32 ; в диапазоне 0..7 add esi,eax ; Прибавляем к esi - eax movsb ; Помещаем инструкцию ; из таблицы в буфер ; В итоге у нас получается ; случайно выбранная ; инструкция из таблицы: ; ............................. ; cld ; nop __q__: ; ............................. dec ecx ; Уменьшаем ecx на единицу ret ; Возврат из подпрограммы ;----[Подпрограмма получающая случайный свободный регистр]---------------------; free_reg: ; Подпрограмма получения ; свободного регистра push edx ecx ; Сохраняем в стэке edx, ecx another: ; call rnd_reg ; bt ebx, eax ; Определяем используемый jc another ; случайный регистр pop ecx edx ; Восстанавливаем ecx, edx ret ; Возврат из подпрограммы ;----[Подпрограмма получающая случайный регистр]-------------------------------; rnd_reg: ; Подпрограмма получения ; случайного регистра mov eax,8 ; Получаем случайное число call brandom32 ; в диапазоне 0..7 ret ; Возврат из подпрограммы ;----[Таблица смещений на подпрограммы]----------------------------------------; mega_table: dw __x87 -__st__ ; dw __mov_r32_r32 -__st__ ; dw __push_r32 -__st__ ; dw __push_r32_2 -__st__ ; dw __push_imm32 -__st__ ; dw __shl_r32_imm8 -__st__ ; dw __cmp_r32_r32 -__st__ ; dw __xor_r32_r32 -__st__ ; dw __one_byte -__st__ ; dw __mov_r32_imm32 -__st__ ; dw __jxx_short -__st__ ; Таблица относительных dw __jxx_near -__st__ ; смещений от метки dw __add_r32_imm32 -__st__ ; delta_offset dw __jmp_short -__st__ ; dw __lea_r32_imm32 -__st__ ; dw __test_r32_r32 -__st__ ; dw __not_r32 -__st__ ; dw __xadd_r32_r32 -__st__ ; dw __mov_r16_imm16 -__st__ ; dw __cmova_r32_r32 -__st__ ; dw __call_near -__st__ ; ;----[Таблица однобайтовых опкодов]--------------------------------------------; __1_byte_opcode: std ; cld ; Таблица однобайтовых nop ; инструкций clc ; stc ; cmc ; db 0f2h ; rep db 0f3h ; repnz ;----[Таблица трёхбайтовых опкодов]--------------------------------------------; __3_byte_opcode: db 0a3h,0abh,0adh,0b3h,0bbh,0bdh,0bfh ; Таблица трёхбайтовых db 0b6h,0b7h,0beh,0afh,0bch,0c1h,0bdh ; инструкций ;----[Таблица мат. ожиданий опкодов]-------------------------------------------; __freq_table: dw 10 ; x87(0xdc) dw 209 ; mov r32,r32(0x8b) dw 107 ; push r32/pop r32(0x50) dw 147 ; push r32(0xff,0x6a) dw 32 ; push imm32(0x68) dw 6 ; ror/shl r32,imm8(0xc1) dw 5 ; cmp r32,r32(0x3ah) dw 43 ; xor r32,r32(0x33) dw 8 ; rep/repnz(0xf3) dw 22 ; mov r32,imm32(0xb8) dw 82 ; je short(0x70..0x7fh) dw 18 ; je near(0x0f) dw 78 ; add/or r32,imm32(0x81..0x85) dw 30 ; jmp short(0xeb) dw 63 ; lea r32,imm32(0x8d) dw 1 ; test r32/r8,r32/r8(0x84,0x85) dw 1 ; not/neg(0xf7) dw 23 ; xadd/imul r32,r32(0x0f) dw 6 ; mov r16,imm16(0x66) dw 13 ; cmova r32,r32(0x0f) dw 95 ; call near(0xe8) ;----[Количество поколений]----------------------------------------------------; __generation dd 9 ;----[Наследственность]--------------------------------------------------------; __cross1 dd 0 __cross2 dd 0 ;----[Определения регистров]---------------------------------------------------; _eax equ 00000001h ; _ecx equ 00000002h ; _edx equ 00000004h ; _ebx equ 00000008h ; _esp equ 00000010h ; Определения регистров _ebp equ 00000020h ; спасибо Z0MBiE :) _esi equ 00000040h ; _edi equ 00000080h ; ;------------------------------------------------------------------------------;
Для работы данного движка необходима новая версия - ГЕНЕРАТОР СЛУЧАЙНОГО ЧИСЛА.