;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
; ГЕНЕРАТОР МУСОРНЫХ ИНСТРУКЦИЙ 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		;
;------------------------------------------------------------------------------;
</src>
<p>Для работы данного движка необходима новая версия - ГЕНЕРАТОР СЛУЧАЙНОГО ЧИСЛА.</p>
<src lang="asm">
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%;
; ГЕНЕРАТОР СЛУЧАЙНОГО ЧИСЛА 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				; Возврат из подпрограммы