;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
;                                                                                                  ;
;                                                                                                  ;
;     ########     ############    ##############    ###########   ##############  ############    ;
;   ############   #############   ##############   #############  ##############  #############   ;
;  ##############  ##############  ##############  ##############  ##############  ##############  ;
;  ######          #####    #####  #####           #####    #####      #####       #####    #####  ;
;  ######          #####    #####  #####           #####               #####       #####    #####  ;
;   ########       ##############  ###########     #####               #####       ##############  ;
;     ########     #############   ###########     #####               #####       #############   ;
;       ########   ############    ###########     #####               #####       ############    ;
;          ######  #####           #####           #####               #####       #####    ####   ;
;          ######  #####           #####           #####    #####      #####       #####    #####  ;
;  ##############  #####           ##############  ##############      #####       #####    #####  ;
;   ############   #####           ##############   #############      #####       #####    #####  ;
;     ########     #####           ##############    ###########       #####       #####    #####  ;
;                                                                                                  ;
;                                                                                                  ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;                         
;                                                                                                  ;
;									SwaP rEg ... moToR                                             ;
;                            ( transformation, Conditional jump, etc)                              ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;                 
;                                                                                                  ;
;                                     		:)                                                     ;        
;                                                                                                  ;                                                                                                                                                                                                                                                                                                
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
;функция SPECTR                                                                                  ;
;                                                                                                ;
;Простой морфер                                                                                  ;
;================================================================================================;
;(1) перестановка регистров в инструкциях                                                        ;
;(2) замена коротких переходов на длинные                                                        ;
;(3) замена:                                                                                     ;
;	 	adc/add/etc   AL/AX/EAX,imm8/16/32  на   adc/etc   REG,imm8/16/32;                       ;
;	 	test 	      AL/AX/EAX,imm8/16/32  на   test	   REG,imm8/16/32;                       ;
;	 	xchg	         AX/EAX,REG	    	на   xchg	   REG,REG                               ;
                                                                                                 ;
;================================================================================================;
;Вход (в стеке):                                                                                 ;
;[esp+00] - адрес движка дизассемблера                                                           ;
;[esp+04] - адрес генератора случайных чисел (ГСЧ)                                               ;
;[esp+08] - размер кода, который надо отмутировать                                               ;
;[esp+12] - адрес кода, который надо отмутировать                                                ;
;[esp+16] - адрес буфера, куда запишем отмутированный код                                        ;
;[esp+20] - адрес буфера для дизассемблера (в этом буфере будет храниться инфа об                ;
;	    	очередной разобранной инструкции). Также, потом, здесь будет храниться адрес         ;
;			массива BufReg(а в нем храняться заменяющие регистры).                               ;
;[esp+24] - адрес таблички исключений (о ней читай чуть ниже).                                   ;
;                                                                                                ;
;Выход:                                                                                          ;
;edi	  - адрес, куда мы записали отмутированный код                                           ;
;eax	  - размер этого кода                                                                    ;
;+ 		  	работающий код, если все отлично было сделано:)!                                     ;
;================================================================================================;
;                                                                                                ;
;Заметки:                                                                                        ;
;------------------------------------------------------------------------------------------------;
;(х) Отмечу, что все это можно было сделать КУДА ЛУЧШЕ (многие вещи я и                          ;
;    сам уже после заметил). Но все же я оставил все, как есть. Так что, втыкай!                 ;
;================================================================================================;
;(x) Данный движок не привязан ни к каким другим движкам - таким образом, он может               ;
;    компилиться отдельно. И поэтому он принимает столько параметров в стеке.                    ;
;    Но все же есть несколько требований к входным параметрам на тот случай, если                ;
;    ты захочешь, например, юзать свой дизасм или ГСЧ:                                           ;
;	(1) движок дизасма должен использовать те же флаги (P_MODRM=001h, etc),                      ;
;	    что и данный движок. Если это невозможно, то тогда просто в данном                       ;
;	    движке меняем флаги на те, которые используются в дизасме. Вот и все.                    ;
;	(2) адрес буфера для дизассемблера ака структура, в которой будет                            ;
;	    храниться инфа о разобранной инструкции - должна быть следующего вида:                   ;
;                                                                                                ;
;	INSTR1	struct                                                                               ;
;	(+ 00) len_com		db 00h 	      ;	- длина команды;                                         ;
;	(+ 01) flags		dd 00h 	      ;	- выставленные флаги                                     ;
;	(+ 05) seg			db 00h 	      ;	- сегмент (если есть);                                   ;
;	(+ 06) repx			db 00h 	      ;	- префикс (0F2h/0F3h) (если есть);                       ;
;	(+ 07) len_offset	db 00h 	      ;	- размер смещения;                                       ;
;	(+ 08) len_operand	db 00h 	      ;	- размер операнда;                                       ;
;	(+ 09) opcode 		db 00h 	      ;	- опкод (если опкод=0Fh, тогда                           ;
;					      			  ;	  сюда сохраняется 2-ой опкод, и                         ;
;					      			  ;	  устанавливается флаг B_OPCODE2);                       ;
;	(+ 10) modrm		db 00h 	      ;	- байт MODRM (также, если есть)                          ;
;	(+ 11) sib			db 00h 	      ;	- байт SIB                                               ;
;	(+ 12) offset		db 8 dup (00h);	- смещение инструкции                                    ;
;	(+ 20) operand		db 8 dup (00h);	- операнд  инструкции                                    ;
;	INSTR1	ends                                                                                 ;
;                                                                                                ;
;	    Если структуру невозможно сделать такого вида, тогда нах.                                ;
;	    Или же в данном движке придется до**я исправлять. Но возможно:) Вот такая вот            ;
;		независимость:)                                                                          ;
;================================================================================================;
;(x) Для правильной работы данного движка, не применять в своем коде команд,                     ;
;    которые                                                                                     ;
;    используют регистры неявно (то есть не кодируют их, а подразумевают их своим                ;
;    опкодом). Например, movsb/lodsd/imul/etc.                                                   ;
;================================================================================================;
;(x) Также, надо позаботиться (но это уже работа дизассемблера) о разделении кода                ;
;    и данных.                                                                                   ;
;================================================================================================;
;                                                                                                ;
;================================================================================================;
;(x) Данный движок рассчитан на обработку 200 переходов/вызовов. Количество можно                ;
;	 уменьшить/увеличить.                                                                        ;
;	 Но не переборщить, так как все хранится в стэке. Один переход требует 12 байт в стэке.      ;
;================================================================================================;
;(x) Теперь расскажу о Табличке Исключений (ТИ). Она должна иметь следующий вид:                 ;
;                                                                                                ;
;	dd	XXXXXXXXh ;address                                                                       ;
;	dd	XXXXXXXXh ;size                                                                          ;
;	dd	XXXXXXXXh ;address                                                                       ;
;	dd	XXXXXXXXh ;size                                                                          ;
;	...                                                                                          ;
;	dw	0FFFFh                                                                                   ;
;                                                                                                ;
;	 В 1-ом дворде должен лежать адрес, во 2-ом - размер. И так далее.                           ;
;	 Признак конца таблички = 0xFFFF.                                                            ;
;	 То есть суть ТИ в следующем:                                                                ;
;	 в нее кладутся адреса и размеры тех мест кода, которые изменять морфингу НЕ НАДО!           ;
;	 То есть, например, в ТИ лежит адрес 0x00401000 (1-ый дворд) и размер 0x1000 (2-ой дворд).   ;
;	 Это означает, что когда движок будет обрабатывать заданный код, то он пропутит, а точнее    ;
;	 скопирует БЕЗ ИЗМЕНЕНИЙ код по адресу с 0x00401000 в размере 0x1000 байт.                   ;
;	 И еще:                                                                                      ;
;	 адреса следует размещать в ТИ в порядке возрастания;                                        ;
;	 если ТИ не нужна, то вместо адреса ТИ следует в параметре передавать 0;                     ;
;	 В своем вирьке я вместо адресов использовал смещения относительно точки входа. То есть,     ;
;	 например, возьмем адрес 0x00401005. Точка входа в прогу = 0x00401000. Так вот,              ;
;	 0x00401005 - 0x00401000 = 0x05 - и вот такие числа я помещал в ТИ. Ну это уже дело ваше:)!  ;
;================================================================================================;
;(x) КАК ОБРАБАТЫВАТЬ КОД, В КОТОРОМ ВЫЗЫВАЮТСЯ АПИШКИ?                                          ;
;	 Ха, да как угодно. Вот один из вариков:                                                     ;
;	 Допустим, есть вот такой вызов:                                                             ;
;                                                                                                ;
;		push 0                                                                                   ;
;		call FakinTrahin ;в качестве результата эта функция возвращает какое-то значение в EAX!  ;
;                                                                                                ;
;	 Начнем. Сначала оборачиваем такой код так:                                                  ;
;                                                                                                ;
;		push 0 ;здесь что угодно                                                                 ;
;		pushad ;save all regs                                                                    ;
;		push 0                                                                                   ;
;		call FakinTrahin                                                                         ;
;_iskl1_:                                                                                        ;
;		mov [esp+20h],eax                                                                        ;
;Sizeiskl1	equ	$ - _iskl1_                                                                      ;
;		popad                                                                                    ;
;		pop eax                                                                                  ;
;                                                                                                ;
;	 Ну а после кладем в ТИ адрес _iskl1_ и размер Sizeiskl1. ВоТ и ВсЁ!                         ;
;================================================================================================;
;(х) Теперь расскажу о каждой из фич:                                                            ;
;;-----------------------------------------------------------------------------------------------;
;	(+) перестановка регистров в инструкциях:                                                    ;
;                                                                                                ;
;		СУТЬ В СЛЕДУЮЩЕМ: МЫ ДИЗАССЕМБЛИРУЕМ ЗАДАННЫЙ КОД, ОПРЕДЕЛЯЕМ - ЕСТЬ ЛИ В КОМАНДЕ        ;
;		РЕГИСТР(Ы), И ЕСЛИ ЕСТЬ, ТО ПЕРЕСТАВЛЯЕМ ИХ МЕЖДУ СОБОЙ ПО ОПРЕДЕЛЕННЫМ ПРАВИЛАМ.        ;
;		ПОЯСНЕНИЕ: ЕСЛИ БЫТЬ ТОЧНЕЕ, ТО МЫ СНАЧАЛА ДИЗАСМИМ КОМАНДУ, ЗАТЕМ КОПИРУЕМ ЕЕ В         ;
;		КАКОЙ-НИТЬ БУФЕР, ЗАТЕМ ОПРЕДЕЛЯЕМ - ЕСТЬ ЛИ РЕГИСТРЫ, И УЖЕ В НОВОМ БУФЕРЕ              ;
;		МЕНЯЕМ РЕГИСТРЫ.                                                                         ;
;                                                                                                ;
;		сразу отмечу, что переставляются между собой только: eax (al,ah),                        ;
;		ecx (cl,ch),edx (dl,dh),ebx (bl,bh). Остальные же: esp,ebp,esi,                          ;
;		edi - нет. Так было сделано для обработки определенного кода                             ;
;		aka влом:)! Так что, кому надо - добавляйте все сами!                                    ;
;		Надо помнить, что нельзя переставлять любой регистр в любой (esp,                        ;
;		ebp). + помнить, что надо определенным образом обрабатывать апишки                       ;
;		(так как многие из них возвращают значение в eax). И т.д..                               ;
;		Также, для использования данной фичи надо быть внимательным к                            ;
;		к некоторым инструкциям, которые используют определенные регистры                        ;
;		неявно (movsb, div/mul, etc). Как вариант - не применять их в                            ;
;		своем коде. Или же другой варик - об этом читай ниже.                                    ;
;		Ну а теперь, как это реализуется в данном движке:                                        ;
;		+ в самом начале мы рандомно выбираем, на какой регистр, допустим,                       ;
;		будем менять eax, на какой - ecx, и т.д.. Замечу, что нельзя,                            ;
;		например, оба регистра eax и ecx превратить в edx. То есть,                              ;
;		регистры должны переставляться только один к одному.                                     ;
;		+ далее, мы дизассемблируем в некотором коде ([esp+12]) очередную                        ;
;		инструкцию (заполняется некоторая структура, содержащая инфу об этой                     ;
;		инструкции), затем записываем эту продизасменную команду в новый                         ;
;		буфер ([esp+16]). После этого, смотрим, содержит ли эта команда                          ;
;		параметры-регистры. Если да, то переставляем (заменяем на ранее                          ;
;		рандомно соответствующие) регистры - уже в новом буфере.                                 ;
;		Например, регистру eax соответствует edx, а ecx - ebx. Тогда:                            ;
;                                                                                                ;
;		..................................................................                       ;
;		..................................................................                       ;
;       ... 						...                                ...                       ;
;		...БЫЛО: mov	eax,ecx		...СТАЛО: mov	edx,ebx            ...                       ;
;		...БЫЛО: mov	ah,ch		...СТАЛО: mov	dh,bh              ...                       ;
;		..................................................................                       ;
;		..................................................................                       ;
;                                                                                                ;
;		Короче, вот такие помидоры. Об этом хорошо написал некий mika0x65                        ;
;		("MetaMorphing?"). Прочти. ВСЕ ОСТАЛЬНОЕ СМОТРИ В ИСХОДНИКЕ:)!                           ;
;------------------------------------------------------------------------------------------------;
;	(+) замена коротких переходов на длинные:                                                    ;
;                                                                                                ;
;		СУТЬ В СЛЕДУЮЩЕМ: ИЩУТСЯ ВСЕ ПЕРЕХОДЫ В ЗАДАННОМ КОДЕ, КЛАДУТСЯ ИХ АДРЕСА И              ;
;		ОПЕРАНДЫ В СТЭК. ЗАТЕМ ПО НОВОЙ ИЩУТСЯ ПЕРЕХОДЫ. КАК ТОЛЬКО НАЙДЕН ПЕРЕХОД,              ;
;		МЫ СМОТРИМ, ПОПАДАЕТ ЛИ ЕГО АДРЕС В ДИАПАЗОН КАКОГО-НИТЬ ПЕРЕХОДА, ЧЬИ АДРЕСА В СТЭКЕ.   ;
;		ЕСЛИ ДА, ТО УВЕЛИЧИВАЕМ ОПЕРАНДЫ ПЕРЕХОДОВ, КОТОРЫЕ НАХОДЯТСЯ В СТЭКЕ. И ТАК ДАЛЕЕ.      ;
;		А УЖЕ ПОСЛЕ ВСЕХ КОРРЕКТИРОВОК МЫ ВСЕ ЗАМЕНЯЕМ. И ВСЕ СУПЕР!                             ;
;		ПОЯСНЕНИЕ: ДИАПАЗОН - ПРОМЕЖУТОК МЕЖДУ АДРЕСОМ ПЕРЕХОДА И ЕГО ПРЫЖКОМ.                   ;
;		АКТИВНОЕ УЧАСТИЕ ПРИНИМАЕТ ДИЗАСМ.                                                       ;
;                                                                                                ;
;		Я реализовал это так (в 3 этапа):                                                        ;
;		(заметка: двиг реализовывает все 3 фичи как раз тоже в 3 этапа)                          ;
;*******	+ 1 этап:                                                                            ;
;		дизасмим очередную команду. Если команда - переход с                                     ;
;		операндом (то есть call/jmp (0xe8/0xe9) imm32, jxx(short/near)                           ;
;		imm8/imm32), то тогда смотрим, куда он прыгает: вверх или                                ;
;		вниз, а также смотрим, какой это переход: short or near?                                 ;
;		Если это near (opcode: 0xe8,0xe9, 0x0f 0x8*), то нам все равно,                          ;
;		куда он прыгает, и мы кладем в стек его операнд (параметр) без                           ;
;		изменений. Если же оказался short, то тогда нам надо преобразовать                       ;
;		его операнд так, как для near переходов. Если этот short jmp                             ;
;		прыгает вниз, то помещаем в стек его операнд без изменений. А если                       ;
;		же прыгает вверх: (пример)                                                               ;
;                                                                                                ;
;		..................................................................                       ;
;		..................................................................                       ;
;                                                                                                ;
;		0x00401000   	      		_metka_:... 		<---                                     ;
;                                     		...   	     	|                                    ;
;                                     		...   	     	|                                    ;
;                                     		...   	     	|                                    ;
;		0x00401015 0xEB 0xE9  				jmp   _metka_---                                     ;
;		0x00401017                                                                               ;
;		..................................................................                       ;
;		..................................................................                       ;
;                                                                                                ;
;		В данном примере операнд=0x000000E9. Теперь преобразуем так, как                         ;
;		для near переходов:                                                                      ;
;		1) 0x000000E9 превратим в 0xFFFFFFE9;                                                    ;
;		2) Так как это короткий безусловный переход (2 байта), то в                              ;
;		   будущем он превратится в безусловный длинный (5 байт).                                ;
;		Таким образом: 5-2=3, 0xFFFFFFE9-3=0xFFFFFFE6 - а когда будем                            ;
;		записывать этот операнд двордом, то он запишется как 0xE6FFFFFF                          ;
;		(младший байт по младшему адресу). И в итоге у нас вот что                               ;
;		получится:                                                                               ;
;		..................................................................                       ;
;		..................................................................                       ;
;                                                                                                ;
;		0x00401000			      	  _metka_:... 		 <---                                    ;
;                                             ...            |                                   ;
;                                             ...            |                                   ;
;                                             ...            |                                   ;
;		0x00401015 0xE9 0xE6 0xFF 0xFF 0xFF   jmp   _metka_---                                   ;
;		0x0040101A                                                                               ;
;		..................................................................                       ;
;		..................................................................                       ;
;                                                                                                ;
;		После помещения в стек операнда перехода, помещаем также в стек и                        ;
;		адрес этого перехода. К адресу мы будем обращаться на 2 этапе, а                         ;
;		операнд (в стеке) будет постоянно корректироваться.                                      ;
;		В данном движке все это делается чуть по другому.                                        ;
;*******	+ 2 этап:                                                                            ;
;		по новой в том же буфере дизасмим команду за командой. Если                              ;
;		эта команда - переход (обозначим его как N), то тогда начинаем                           ;
;		брать из стека ранее сохраненные адреса переходов (обозначим их                          ;
;		как M). Продизасмим адрес перехода M для получения длины этой                            ;
;		команды, а также для получения операнда (параметра) этого                                ;
;		перехода.                                                                                ;
;		Затем узнаем адрес, куда прыгает переход M. Пример:                                      ;
;                                                                                                ;
;		..................................................................                       ;
;		..................................................................                       ;
;       ...                                                            ...                       ;
;		... Если переход M короткий (2 byte), и он прыгает вверх:      ...	                     ;
;		..................................................................                       ;
;		..................................................................                       ;
;       ...                                                            ...                       ;
;		... 0x00401000		   	   _metka_:... <---                    ...                       ;
;		...			   			   ...            |                    ...                       ;
;		...			   			   ...            |                    ...                       ;
;		...			   			   ...            |                    ...                       ;
;		... 0x00401015 0xEB 0xE9   jmp   _metka_---                    ...                       ;
;		... 0x00401017                                                 ...                       ;
;		..................................................................                       ;
;		..................................................................                       ;
;		...                                                            ...                       ;
;       ... Считаем адрес, куда он прыгает (должен быть равен          ...                       ;
;		... 0x00401000):                                               ...                       ;
;       ... operand=0x000000E9.                                        ...                       ;
;		... превращаем 			 0x000000E9 в 0xFFFFFFE9.                                        ;
;		... add	operand,2		;=0xFFFFFFEB                           ...                       ;
;		... 0x00401015+operand=0x00401000==0x00401000.                 ...                       ;
;		... Вот так (почти) и считаем все остальные переходы, которые  ...                       ;
;		... прыгают вверх (только прибавляем не 2, а столько, сколько  ...                       ;
;		... весит этот переход:)!                                      ...                       ;
;		..................................................................                       ;
;		..................................................................                       ;
;                                                                                                ;
;                                                                                                ;
;		..................................................................                       ;
;		..................................................................                       ;
;       ...                                                            ...                       ;
;		... Если переход M короткий (2 byte),и он прыгает вниз:        ...                       ;
;		..................................................................                       ;
;		..................................................................                       ;
;       ...                                                            ...                       ;
;		... 0x00401000 0xEB 0x13   jmp   _metka_---                    ...                       ;
;       ... 0x00401002		   	   ...            |                    ...                       ;
;       ...			   			   ...            |                    ...                       ;
;       ...			   			   ...            |                    ...                       ;
;       ... 0x00401015		   	   _metka_:... <---                    ...                       ;
;       ..................................................................                       ;
;       ..................................................................                       ;
;       ...                                                            ...                       ;
;       ... Считаем адрес, куда он прыгает (должен быть равен          ...                       ;
;		... (0x00401015):                                              ...                       ;
;		... operand=0x00000013                                         ...                       ;
;       ... add operand,2	;=0x00000015                           ...                           ;
;       ... 0x00401000+operand=0x00401015==0x00401015.                 ...                       ;
;       ... Вот так (почти) и считаются все остальные переходы,которые ...                       ;
;		... прыгают вниз (только прибавляем не 2, а столько, сколько   ...                       ;
;		... весит этот переход:)!                                      ...                       ;
;       ..................................................................                       ;
;       ..................................................................                       ;
;                                                                                                ;
;		После всего этого, смотрим, попадает ли переход N в диапазон                             ;
;		перехода M (то есть, находится ли переход N между адресом                                ;
;		перехода M и адресом, куда M прыгает). Если да, попадает, и                              ;
;		если переход N - короткий (0xEB - 2 байта), то увеличим в стеке                          ;
;		операнд, соответствующий переходу M на 3 байта (так как переход                          ;
;		N станет 0xE9 - 5 байт). А в новом буфере ([esp+16]) записываем                          ;
;		переход N как длинный:                                                                   ;
;		0xE9 0x00 0x00 0x00 0x00 - и в стеке сохраним этот адрес - по                            ;
;		которому только что записали "превращенный" в длинный переход N.                         ;
;		Потом, когда все операнды, что в стеке, будут скорректированы,                           ;
;		мы вместо этих нулей запишем соответствующие операнды.                                   ;
;		Если же N - длинный или не попал в диапазон, то операнды в стеке                         ;
;		не меняем, а в новом буфере запишем оригинал N и сохраним адрес,                         ;
;		по которому только что записали N, в стеке.                                              ;
;                                                                                                ;
;		Заметка: на этом же этапе (2 этап) происходит перестановка                               ;
;		регистров и фича №3 (замена adc/add/etc); все интрукции                                  ;
;		(мутированные и нет) записываются в новый буфер ([esp+16]).                              ;
;                                                                                                ;
;******		+3 этап: достаем из стека адреса переходов N в новом буфере,                         ;
;		соответствующие им скорректированные операнды, и остальную фигню                         ;
;		(чтобы сбалансировать стек). И по этим адресам записываем операнды                       ;
;		(вместо тех нулей:)! Вот и все! Все переходы готовы!                                     ;
;------------------------------------------------------------------------------------------------;
;	(+) замена                                                                                   ;
;		adc/add/etc   AL/AX/EAX,imm8/16/32  на   adc/etc   REG,imm8/16/32;                       ;
;		test 	      AL/AX/EAX,imm8/16/32  на   test	   REG,imm8/16/32;                       ;
;		xchg	         AX/EAX,REG	    на   xchg	   REG,REG                                   ;
;		Это лишь малый пример того, на что может быть годен данный движок.                       ;
;		Суть проста: если находим соответствующую команду, то все                                ;
;		аналогично, как с переходами, только меняем найденную такую                              ;
;		команду на аналог: adc/add/etc REG,imm16/imm32. Остальное - все то                       ;
;		же самое. Кстати, таким же образом можно и написать замены для                           ;
;		movs/lods[b,w,d], etc.                                                                   ;
;================================================================================================;
;		                                                                                         ;
;КОРОЧЕ, ЕСЛИ ИЗ ВСЕГО ВЫШЕНАПИСАННОГО БРЕДняКА ЧТО-ТО (ВсЁ:)! НЕПОНЯТНО, КоРоЧЕ -               ;
;ПО-ЛЮБОМУ СМОТРИ В ИСХОДНИК!                                                                    ;
;                                                                                                ;
;================================================================================================;
;(х) Движок предназначен Для 32-битного исполняемого кода. Насчет другого - как                  ;
;    хочешь.                                                                                     ;
;================================================================================================;						   
;(х) Кто хочет, пусть нафиг сам и добавляет остальные команды и всякие там                       ;
;    проверки.                                                                                   ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
                                                                                                 ;
                                                                                                 ;
                                                                                                 ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
;										ФИЧИ:                                                    ;                        
;(+) базонезависимость								                                             ;
;(+) перестановка регистров в инструкциях                                                        ;
;(+) замена коротких переходов на длинные                                                        ;
;(+) замена команд вида COMAND AL/AX/EAX,...   на команды вида COMAND REG,...                    ;
;(+) возможность добавления фич (напр., ply-мутация, более сильный метаморфизм, etc).            ;
;(+) не использует WinApi                                                                        ;             
; 							                                                                     ;                                                           
;(-) если использовать в вирусах, вирек должен быть специфичным (читай подробности выше).        ;
;                                                                                                ;
;(x) Прошел проверку на Windows XP SP2, на остальных не тестил. Но на 2000,NT + других SP        ;
;	 должен работать.						                                                     ;                                                                                                 
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
                                                                                                 ;
                                                                                                 ;
                                                                                                 ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
;									ИСПОЛЬЗОВАНИЕ:                                               ;
;                                                                                                ;
;------------------------------------------------------------------------------------------------;
;                                                     x                                          ;
;1) Подключение:                                      x                                          ;
;	 c использованием дизасма LiTo и ГСЧ RANG32:	  x			без использования:               ;
;		include		rang32.asm						  x				include		spectr.asm		 ;				
;		include		_lito_.asm                        x                                          ;
;		include		spectr.asm                        x                                          ;
;------------------------------------------------------------------------------------------------;                                                                   
;                                                                                                ;
;2) Вызов:	                                                                                     ;
;		push	XXXXXXXXh		;адрес Таблички Исключений (ТИ) либо 0                           ;
;		push	XXXXXXXXh		;адрес буфера под дизасм                                         ;
;		push	XXXXXXXXh		;буфер, в котором будет храниться уже отмутированный код         ;     
;		push	XXXXXXXXh		;код (адрес), который надо отмутировать                          ;
;		push	XXXXXXXXh		;размер этого кода, который надо проморфить                      ;
;		push	XXXXXXXXh		;адрес Генератора Случайных Чисел (ГСЧ)                          ;
;		push	XXXXXXXXh		;адрес дизассемблера                                             ;
;		call	SPECTR                                                                           ;
;                                                                                                ;                                                                                 
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
                                                                                                 ;
NumJMP		equ	270                                     ;количество переходов/вызовов            ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
;функция SPECTR                                                                                  ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;

										;m1x
									;pr0mix@mail.ru	

SPECTR:
	push	ebp											;им лучше пользоваться:)
	mov		ebp,esp
	pushad                                          	;сохраняем реги

	mov		edx,TMPAddr                        			;edx - указатель на структуру для нашего дизасма
	                                                	;(в ней будет храниться разобранная инструкция + некоторая дополнительная инфа)
	mov		esi,AddrSrcCode                         	;esi - адрес кода, который надо отмутировать                          	
	mov		ebx,esi                                 	;ebx - указывает на конец кода для морфинга
	add		ebx,SizeSrcCode

	call	_addrBufReg_	
;------------------------------------------------------------------------------------------------
_isklspectr0_:
BufReg		db 00,01,02,03,04,05,06,07					;буфер для сгенерированных регистров
Sizeiskspectr0		equ		$ - _isklspectr0_
SizeBufReg			equ 	$-BufReg
;------------------------------------------------------------------------------------------------
		
_addrBufReg_:
	pop		TMPAddr										;сохраняем адрес BufReg в этой локальной переменной	
	push	fnRand                                      ;кладем в стэк адрес ГСЧ
	call	reg_mut                                 	;вызываем функцию генерации регистров	
	xor		ecx,ecx;!									;ecx - счетчик переходов(jmp short/near) & call'ов (т.е. их количество)
;------------------------------------------------------------------------------------------------


;================================================================================================
;||============================================================================================||
;||                                  ##########                                                ||
;||				                     ##########                                                ||
;||                                     ####                                                   ||
;||                                     ####                                                   ||
;||                                     ####                                                   ||
;||                                     ####                                                   ||
;||                                  ##########                                                ||
;||                                  ##########                                                ||
;||============================================================================================||
;================================================================================================
_FIRSTSTAGE_:                                           ;I этап
	mov		eax,esi	
	call	obr_iskl_1                                  ;вызываем функцию обработки исключений (таблички адресов исключений:)! 
	cmp		eax,esi                                     ;если текущий адрес попал в табличку адресов исключений, то увеличим esi и перепрыгиваем
	jne		_isklok01_
;------------------------------------------------------------------------------------------------
	mov		edi,edx										;edi - указатель на буфер (под инструкцию)  			

	call	zero_mem 									;обнуляем буфер

	push	eax
_isklspectr1_:                                          ;это типа такая заглушка:)! Этот адрес (_isklspectr1_) и размер можно указать в ТИ.
	push	eax                                         ;А что получится, смотри в отладчике, ну или так:)!
	call	fnDizasm32 									;и дизассемблируем инструкцию
	mov		dword ptr [esp+04h],eax	
	pop		eax                                         ;
Sizeiskspectr1	equ		$ - _isklspectr1_
	pop		eax
;------------------------------------------------------------------------------------------------		
	test	dword ptr [edx+1],P_RELX					;это jump(call)? ;optimization: test byte ptr [edx+2],08h; в остальных случаях аналогично:)!
	je		_srav_                                  	;если нет, то перепрыгиваем
	push	ebx                                     	;иначе 
	mov		ebx,dword ptr [edx+20]						;в ebx - операнд(значение) перехода
														;по нему и будем считать адрес этого прыжка

	cmp		al,2										;это jump short? (2 byte - opcode: 0x7*,0xeb)
	jne		@F                                      	;или jump near? (5(6) byte, etc)
	test	bl,80h                                  	;также проверяем, куда он "прыгает": вверх?
	jne		_jxxshortup_                       			;нет? тогда идем дальше
	cmp		byte ptr [edx+9],0ebh                   	;это jmp short? 
	jne		$+3
	inc		ebx
	sub		ebx,4                                       ;сначала отнимаем, т.к. во 2 этапе будем прибавлять ( это типа корректируем:)!
	jmp		@F	
;------------------------------------------------------------------------------------------------

_jxxshortup_:
	movsx	ebx,bl                                  	;иначе нужно значение(параметр) этого прыжка превратить в такую отрицательную,                           
														;как для 6-байтного прыжка
@@:
	xchg	ebx,[esp]                               	;сохраняем в стеке параметр прыжка (уже сделанный под 5(6)-байтовый переход)
	push	esi                                     	;и адрес этого прыжка
	inc		ecx                                     	;увеличиваем счетчик
_srav_:
	add		esi,eax                                 	;и переходим к следующей инструкции
	cmp		ecx,NumJMP                                  ;не привысили ли мы максимальное количество прыжков?
	jge		_maxjmp_

_isklok01_:
	cmp		esi,ebx                                 	;все ли команды пройдены?                            	
	jb		_FIRSTSTAGE_                                ;если нет, то переход к разбору следующей
;================================================================================================

_maxjmp_:
	mov		ebx,esi                                     ;корректируем конечный адрес
	mov		esi,AddrSrcCode								;в esi - адрес кода для морфинга
	mov		edi,AddrDisCode                         	;в edi - адрес буфера, где будет храниться уже отмутированный код
	sub		esp,NumJMP*4								;также в стеке выделяем еще место для хранения адресов переходов в новом буфере
														;(на него указывает esp:) (если заранее известно, что в коде, который надо проморфить, 
														;будет больше NumJMP переходов, тогда значение NumJMP*4 надо изменить на ххх*4, где 
														;ххх - кол-во переходов)
	push	esp                                     	;сохраняем адрес на это место
	push	ecx           								;сохраняем счетчик (количество переходов)
	push	0                                       	;а здесь - число (кратное 4), которое будем прибавлять к адресу (на него указывает esp), 
														;где хранятся адреса переходов в новом буфере
;------------------------------------------------------------------------------------------------



;================================================================================================
;||============================================================================================||
;||                             ##########  ##########                                         ||       
;||				                ##########  ##########                                         ||   
;||                                ####        ####                                            ||
;||                                ####        ####                                            ||
;||                                ####        ####                                            ||
;||                                ####        ####                                            ||
;||                             ##########  ##########                                         ||   
;||                             ##########  ##########                                         ||   
;||============================================================================================||
;================================================================================================
_SECONDSTAGE_:                                          ;II этап
	mov		eax,edi	
	call	obr_iskl_2                                        ;вызываем фукцию обработки адресов исключений (которые в табличке:)!
	cmp		eax,edi                                     ;если текущий адрес попал в табличку адресов исключений, то увеличим esi, затем запишем в буфер, 
														;начиная с этого адреса, определенное кол-во байт (что также дано в табличке) и перепрыгиваем дальше
	jne		_isklok02_
;ж-----------------------------------------------------------------------------------------------	
	push	edi               							;save edi
	mov		edi,edx

	call	zero_mem                                	;обнуляем буфер под разбираемую инструкцию

	push	eax
_isklspectr2_:                                          ;еще одна заглушка:)!
	push	eax	
	call	fnDizasm32                              	;и дизасмим ее
	mov		dword ptr [esp+04h],eax
	pop		eax
Sizeiskspectr2	equ		$ - _isklspectr2_
	pop		eax
	pop		edi
;------------------------------------------------------------------------------------------------	
	push	eax                 						;сохраняем в стеке длину разобранной команды
	mov		eax,dword ptr [edx+1]                   	;в eax - характеристики (флаги) только что разобранной команды

;xxxxxxxxxxxxxxxxxxxxxBEG call/jxx (short/near) imm8/imm32xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

	test	ax,P_RELX									;вообще, это переход?
	je		_nxtflag0_                              	;если нет, то перескакиваем дальше

	mov		eax,dword ptr [esp+12];   +4];16]            ;в еах - адрес места, куда будем сохранять новые адреса переходов в новом буфере (во блин, я закрутил коменты:)!
														;(эти адреса принадлежат буферу, в котором будет хранться уже отмутированный код)
	add		eax,dword ptr [esp+4];+4]              		;увеличиваем адрес для доступа к следующему свободному месту под следующий новый адрес перехода
	add		dword ptr [esp+4],4;+1?!                	;корректируем это значение
	mov		dword ptr [eax],edi                     	;и сохраняем новый адрес (он нам нужен для изменения параметров переходов)

	xor		ecx,ecx                                 	;в есх будем хранить, сколько новых байтов мы запишем (например, если был 2-байтовый jmp, 
														;то мы его сделаем в 5-байтовый jmp. 5-2=3 байта следует добавить в операнды тех переходов, 
														;в чьи диапазоны попал текущий переход)

	mov		al,byte ptr [edx+9]                     	;в al - опкод текущего перехода
	cmp		al,0ebh
	jne		_noshortjmp_
	add		ecx,3
;------------------------------------------------------------------------------------------------
_noshortjmp_:
	mov		ah,al
	and		ah,11111100b
	cmp		ah,0E8h                                 	;выясняем, это call(0xe8), jmp(0xe9) или jmp(0xeb)?
	je		_jmpimm32_
	test	al,80h    									;или это jmp (0x8*)?	
	je		_jxximm8_	                        		;если нет, то тогда это короткий (short) jump
	sub		ecx,4	
	sub		al,10h                                  	;если же да, 
;------------------------------------------------------------------------------------------------
_jxximm8_:
	add		ecx,4
	mov		byte ptr [edi],0fh
	inc		edi
	add		al,10h
	mov		byte ptr [edi],al                       	;специально - для удобства морфинга (stosb)
	inc		edi
	jmp		@F
;------------------------------------------------------------------------------------------------
_jmpimm32_:
	and		al,01h                           			;тут все аналогично:)!
	add		al,0E8h

	mov		byte ptr [edi],al
	inc		edi
@@:
	and		dword ptr [edi],0
	add		edi,4
	jmp		_2_2stage_      							;если все отлично, то переходим дальше
;xxxxxxxxxxxxxxxxxxxxxEND call/jxx (short/near) imm8/imm32xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


;xxxxxxxxxxxxxxxxxxxxxBEG SBB/SUB/ADC/ADD/etc AX/EAX, imm16/imm32xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
_nxtflag0_:                                             ;а вот тут проверяем, это 2-х байтный опекод?
	test	ax,P_OPCODE2
	jne		_SWAPREG_

	mov		al,byte ptr [edx+9]                     	;если же это add/adc/sub/sbb AX/EAX,imm16/imm32 (эти инструкции имеют меньше байт)
	push	00111000b
	pop		ecx	
;------------------------------------------------------------------------------------------------
	push	ecx
	mov		ecx,eax
	and		cl,11111000b
	cmp		cl,90h                                      ;это xchg eax,reg?
	pop		ecx
	jne		@F
_xchgEAX_:
	test	dword ptr [edx+1],P_PFX66
	je		_nop66_
	mov		byte ptr [edi],66h                          ;0x66
	inc		edi

_nop66_:	
	movzx	eax,byte ptr [edx+9]
	and		al,7
	call	get_res_reg
	xchg	eax,ecx
	xor		eax,eax
	call	get_res_reg
	shl		eax,3
	add		al,cl
	add		al,0c0h
	mov		byte ptr [edi],87h                          ;если же это был XCHG EAX,REG, то заменяем его на => XCHG REG1,REG2
	inc		edi
	mov		byte ptr [edi],al
	inc		edi
	xor		ecx,ecx
	inc		ecx
	jmp		_2_2stage_
;------------------------------------------------------------------------------------------------
@@:	
	cmp		al,0A8h                                     ;это TEST AL,imm8?
	je		_testAL_
;------------------------------------------------------------------------------------------------
	cmp		al,0A9h                                     ;TEST AX/EAX,imm16/32?
	je		_testEAX_
;------------------------------------------------------------------------------------------------		
	and		al,11000111b                            	;(маска для их выявления)
	cmp		al,05h                                  	;то, переделаем их, как для всех остальных регистров (смотри код!)
	jne		@F
	mov		al,33h
	jmp		_addAXEAX_
;------------------------------------------------------------------------------------------------
@@:
	cmp		al,04h
	mov		al,32h
	jne		_SWAPREG_
	jmp		_addAL_
;------------------------------------------------------------------------------------------------
_testAL_:
	xor		ecx,ecx
_addAL_:
	add		al,4eh
	call	swap_eax_reg                           		;optimization!!!!!!!
	mov		byte ptr [edi],al
	inc		edi
	jmp		_incecx_
;------------------------------------------------------------------------------------------------
_testEAX_:
	xor		ecx,ecx
_addAXEAX_:
	add		al,4eh
	test	dword ptr [edx+1],P_PFX66                   ;есть ли префикс 0x66?
	je		@F
	mov		byte ptr [edi],66h
	inc		edi
@@:
	call	swap_eax_reg
	test	dword ptr [edx+1],P_PFX66
	je		_no0x66_
	mov		word ptr [edi],ax
	inc		edi
	inc		edi
	jmp		@F

_no0x66_:
	mov		dword ptr [edi],eax
	add		edi,4
_incecx_:
@@:		
;------------------------------------------------------------------------------------------------
	xor		ecx,ecx
	inc		ecx
;xxxxxxxxxxxxxxxxxxxxxEND SBB/SUB/ADC/ADD/etc AX/EAX, imm16/imm32xxxxxxxxxxxxxxxxxxx


_2_2stage_:
	cmp		dword ptr [esp+4+4],0;    +4],0				;проверяем, есть ли вообще в исходном коде переходы?
	je		_absentjxxcalljmp_	                		;если нет, то перескакиваем
	xor		eax,eax                                 	;eax - индекс (для стека) для получения адресов и их операндов (параметров)
;------------------------------------------------------------------------------------------------

_cyclejxx_:                                             ;!
	push	ebx
	push	edi
	push	ecx
	push	esi
	lea		edi,[esp-80]	                        	;выделяем в стэке буфер под разбираемую команду 
	push	eax
	call	zero_mem                                	;обнуляем буфер под разбираемую команду 

	mov		eax,[esp]	
	mov		esi,dword ptr [esp+eax*8+24+NumJMP*4+12];   ;берем из стека адрес (в первоначальном буфере) очередного перехода

;------------------------------------------------------------------------------------------------
	push	eax
_isklspectr3_:                                          ;еще одна заглушка:)!
	push	eax
	
	call	fnDizasm32                   				;и дизасмим снова этот переход (для того, чтобы получить его исходный (неизмененный) параметр)

	mov		dword ptr [esp+4],eax;20h
	pop		eax
Sizeiskspectr3	equ		$ - _isklspectr3_
	pop		eax
;------------------------------------------------------------------------------------------------
	
	mov		ebx,dword ptr [edi+20]                      ;в ebx - операнд (параметр) перехода
	mov		edi,ecx
	mov		ecx,eax                                 	;в ecx - длина разобранной инструкции
	pop		eax                                         ;восстанавливаем регистры
	pop		esi
;------------------------------------------------------------------------------------------------		                                                
	cmp		cl,2                           				;переход, диапазон которого сейчас проверяется, короткий?
	je      _jmpshort_                              	;если да, то переходим к нужной метке 
	test	ebx,80000000h                           	;иначе смотрим, куда он прыгает - вверх?
	jne		_upjxxnear_                             	;если да, то переходим
	jmp		_downjxxnear_
_jmpshort_:
	test	bl,80h                                  	;тут проверяем в случае короткого перехода: он прыгает вверх?
	jne		_upjxxshort_
;------------------------------------------------------------------------------------------------		
_downjxxnear_:	                                        ;в случае прыжка вниз:
	cmp		esi,dword ptr [esp+eax*8+24+NumJMP*4+4]; 	;смотрим, попадает ли адрес текущего перехода (esi) в диапазон очередного перехода, что в стеке 
	                                                	;для этого, сначала сравниваем адрес текущего перехода с АДРЕСОМ перехода (что в стеке)
	jb		_nxtjxx_                            		;если меньше, то понятно, что текущий переход не в диапазоне - тогда идем дальше
	add		ebx,ecx;6!!!!!!!                        	;иначе, прибавляем длину к параметру

	add		ebx,dword ptr [esp+eax*8+24+NumJMP*4+4]; 	;и прибавляем адрес этого перехода - таким образом получаем адрес прыжка данного перехода
	cmp		esi,ebx                                 	;и снова сравниваем
	jae		_nxtjxx_                            		;если выше, то не попадает

	add		dword ptr [esp+eax*8+4+24+NumJMP*4+4],edi	;иначе, увеличиваем в стеке операнд перехода
														;(в чей диапазон попал текущий адрес перехода) на ранее посчитанное значение 
	jmp		_nxtjxx_	
	                                                	;переходим
;------------------------------------------------------------------------------------------------
_upjxxshort_:                                           ;в случае прыжка (short) вверх:
	movsx	ebx,bl                                      ;приводим операнд в удобный для нас вид
	                                                    ;и также, будем проверать, попадает ли адрес текущего перехода 
_upjxxnear_:                                            ;в чей-либо дипазон других переходов
	add		ebx,ecx						
	
	add		ebx,dword ptr [esp+eax*8+24+4+NumJMP*4]		;в ebx - адрес прыжка очередного перехода из стека
	cmp		esi,ebx                                 	;и сравниваем
	jb		_nxtjxx_
	cmp		esi,dword ptr [esp+eax*8+24+NumJMP*4+4]		;затем сравниваем с самим адресом перехода 
	ja		_nxtjxx_
	sub		dword ptr [esp+eax*8+4+24+NumJMP*4+4],edi	;если все отлично, то корректируем операнд, принадлежащий переходу, чей адрес в стеке
;------------------------------------------------------------------------------------------------	
_nxtjxx_:                                               ;восстанавливаем регистры
	pop		ecx
	pop		edi
	pop		ebx
	inc		eax                        					;увеличиваем счетчик на +1
	cmp		eax,dword ptr [esp+8]                  		;диапазоны всех ли переходов проверены?
	jne		_cyclejxx_                              	;нет? тогда, бежим дальше:)!

_absentjxxcalljmp_:
	pop		eax											;достаем из стека длину команды, ранее сохраненную

@@:
	movzx	eax,byte ptr [edx]                          ;в eax - длина текущего перехода
	add		esi,eax                                     ;переходим к следующей команде
	jmp		_srav2_
;================================================================================================	




;================================================================================================
;||============================================================================================||
;||                     *       ########       #########       *       ch <= dh                ||         
;||	eax => edx         *       ##########      ##########       *                              ||
;||                   *        ####            ###    ###        *                             ||
;||                  *          ######         ###    ###         *                            ||     
;||                  *            ######       #########          *  esi <= esi                ||                       
;||         ah => ch  *              ####      ##########        *                 edi <= edi  ||                        
;||                    *       ##########      ###    ###       *                              ||         
;||  ebp => ebp         *       ######## wap   ###    ###eg    *                               ||          
;||============================================================================================||
;================================================================================================
_SWAPREG_:                                              ;SWAP REG
	mov		eax,dword ptr [edx+1]                   	;в eax - характеристики (флаги) только что разобранной команды

	xor		ecx,ecx                                 	;в ecx - будет храниться длина всех префиксов

														;ПРИСУТСТВУЕТ ЛИ ПРЕФИКС:
;------------------------------------------------------------------------------------------------
	test	al,P_SEG									;сегмента?				
	je		@F
	inc		ecx
@@:
	test	al,P_PFX66									;0x66?
	je		@F
	inc		ecx
@@:
	test	al,P_PFX67      							;0x67?
	je		@F
	inc		ecx
@@:
	test	al,P_LOCK               					;0xF0?
	je		@F
	inc		ecx
@@:
	test	ax,P_REP             						;повторения? (0xf2/0xf3)
	je		@F
	inc		ecx
@@:
	test	ax,P_OPCODE2      							;опкод состоит из двух байт? (где первый байт == 0x0f)
	je		@F
	inc		ecx
;------------------------------------------------------------------------------------------------
@@:		
;_SWAPREG_:	                                        	;если же разобранная команда - не переход, то
	xchg	eax,ecx                   					;запишем ее в новый буфер
	mov		ecx,[esp]
_repmovsb_:
	push	ecx
	mov		cl,byte ptr [esi]
	mov		byte ptr [edi],cl
	inc		esi
	inc		edi
	pop		ecx
	dec		ecx
	jne		_repmovsb_
;------------------------------------------------------------------------------------------------
	;rep	movsb
	pop		ecx
	sub		ecx,eax
	neg		ecx                                     	;если команда содержала префикс(ы), то в ecx - длина команды без префиксов

	push	edi
	lea		edi,[edi+ecx]                           	;в edi - адрес команды без префиксов (или с пропущенными)
;------------------------------------------------------------------------------------------------	
	mov		al,byte ptr [edx+9]                     	;al - opcode
	test	dword ptr [edx+1],P_MODRM               	;содержит ли разобранная команда байт MODRM?
	jne		_modrmok_
;------------------------------------------------------------------------------------------------
	                                                	;если нет, то проверяем, содержит ли опкод команды регистр?
	cmp		al,40h                             			;
	jb		@F
	cmp		al,60h
	jb		_regok_
@@:
	cmp		al,0b0h
	jb		@F                                      	;!!!!!!!!!!!!!!!!!!!!!!!!!
	cmp		al,0c0h
	jb		_regok_
@@:
	cmp		al,0c8h
	jb		_gogogo_
	cmp		al,0D0h
	jae		_gogogo_
;------------------------------------------------------------------------------------------------
_regok_:                                                ;если содержит, то
	mov		cl,al
	and		al,7                                    	;извлекаем регистр
	and		byte ptr [edi],11111000b
	and		cl,11111000b
	cmp		cl,0b0h                                     ;
	jne		_reg1632_	                        		;
	cmp		al,4                                        ;если это команда, использующая 8-разрядный регистр (al,ah,cl,etc), 
														;то смотрим, какой это регистр: ah (04h),ch (05h),dh (06h),bh (07h)?
	jb		_reg1632_
	sub		al,4                                        ;если да,то вычитаем 4, получаем регистр заменяющий, и прибавляем 4. То есть (пример):
														;например мы разбираем команду mov ah,byte ptr [esi]. Регистру eax (000h) соответствует edx (002h). Значит, 
														;мы должны получить mov dh,byte ptr [edi]. 
														;Мы делаем так: 04h (ah) - 4h = 00h (eax). Далее, получаем соответствие eax => edx, то есть (00h) => (02h).
														;Потом (02h) + 4h = (06h) == dh!
	call	get_res_reg
	add		al,4
	jmp		@F
;------------------------------------------------------------------------------------------------	                            	
_reg1632_:
	;and	al,7                                    	;извлекаем регистр
	;and	byte ptr [edi],11111000b
	call	get_res_reg                             	;получаем регистр, заменяющий его
@@:
	or		byte ptr [edi],al                       	;и записываем новый регистр
	jmp		_gogogo_                                	;переходим дальше
		
_modrmok_:                                              ;если команда имеет byte MODRM
	push	0
	test	dword ptr [edx+1],P_OPCODE2             	;opcode состоит из двух байт (первый=0x0f)?
	jne		_opc2ok_                                	;если да,то переходим дальше

;xxxBEG смотрим: это команда, чье поле reg в поле modrm - содрежит часть opcode?xxxxxxxxxxxxxxxxx

	mov		cl,al
	mov		ch,al
	and		cl,11000101b
	test	cl,cl
	je		_r8mod_
	mov		cl,ch
	and		cl,11111001b
	cmp		cl,80h
	je      _r8mod_
	cmp		ch,88h
	je		_r8mod_
	cmp		ch,8ah
	je		_r8mod_
	cmp		ch,0d0h
	jne		@F
_r8mod_:
	inc		dword ptr [esp]
	;jmp	_regopcok_
;------------------------------------------------------------------------------------------------	
@@:	
	cmp		al,80h
	jb		@F
	cmp		al,84h
	jb		_sibok_
@@:
	cmp		al,8Fh
	je		_sibok_
	cmp		al,0c0h
	je		_r8mod_2_
	cmp		al,0c1h
	je		_sibok_
	cmp		al,0c6h
	je		_r8mod_2_
	cmp		al,0c7h
	je		_sibok_
	cmp		al,0d0h
	jb		@F
	cmp		al,0d4h
	jb		_sibok_
@@:
	cmp		al,0d8h
	jb		@F
	cmp		al,0E0h
	jb		_sibok_	
@@:
	cmp		al,0f6h
	je		_r8mod_2_
	cmp		al,0f7h
	je		_sibok_
	cmp		al,0feh
	je		_r8mod_2_
	cmp		al,0ffh
	je		_sibok_
	jmp		_regopcok_
;------------------------------------------------------------------------------------------------
_r8mod_2_:
	inc		dword ptr [esp]
	jmp		_sibok_
;------------------------------------------------------------------------------------------------
_opc2ok_:           									;проверки для двухбайтного опкода
	cmp		al,00h
	je		_sibok_
	cmp		al,01h
	je		_sibok_
	cmp		al,90h
	jb		@F
	cmp		al,0A0h
	jb		_sibok_
@@:
	cmp		al,0BAh
	je		_sibok_
	cmp		al,0c7h
	je		_sibok_
;xxxEND смотрим: это команда, чье поле reg в поле modrm - содрежит часть opcode?xxxxxxxxxxxxxxxxx

_regopcok_:                         					;если же в поле reg (modrm) содержится регистр, то 
	movzx	eax,byte ptr [edi+1]                    	;то в eax - байт modrm
	shr		eax,3                    					;получаем регистр
	and		al,7
	and		byte ptr [edi+1],11000111b
	cmp		dword ptr [esp],1
	jne		_reg32_
	cmp		al,4
	jb		_reg32_
	sub		al,4
	call	get_res_reg                                 ;аналогично, смотри выше:)!
	add		al,4
	jmp		@F

_reg32_:

	call	get_res_reg                             	;получаем новый регистр, который заменит текущий регистр 
@@:
	shl		eax,3
	or		byte ptr [edi+1],al           				;и запишем его!

;------------------------------------------------------------------------------------------------	
_sibok_:
	pop		ecx
	test	dword ptr [edx+1],P_SIB                 	;содержит разбираемая команда байт SIB?
	je		_rmok_	                                	;если нет, то поле rm (modrm) содержит регистр, и переходим туда
	movzx	eax,byte ptr [edi+2]                    	;получаем SIB
	push	eax
	and		al,7                                    	;получаем 1-ый регистр
	and		byte ptr [edi+2],11000000b
	call	get_res_reg                             	;получаем новый регистр, который заменит старый регистр
	or		byte ptr [edi+2],al                     	;и поменяем их 
	pop		eax
	shr		eax,3                                   	;получаем 2-ой регистр
	and		al,7
	call	get_res_reg                             	;далее аналогично
	shl		eax,3
	or		byte ptr [edi+2],al
	jmp		_gogogo_                                	;переходим

;------------------------------------------------------------------------------------------------
_rmok_:
	movzx	eax,byte ptr [edi+1]                    	;если поле rm в байте modrm содержит регистр, то 
	and		al,7                                    	;получаем этот регистр
	and		byte ptr [edi+1],11111000b              	;убираем по маске этот регистр в коде
	test	ecx,ecx
	je		_reg32rm_
	mov		cl,byte ptr [edi+1]
	and		cl,0C0h
	cmp		cl,0C0h
	jne		_reg32rm_
	cmp		al,4
	jb		_reg32rm_
	sub		al,4
	call	get_res_reg
	add		al,4
	jmp		@F

;------------------------------------------------------------------------------------------------
_reg32rm_:
	call	get_res_reg                             	;получаем новый регистр
@@:
	or		byte ptr [edi+1],al                     	;и записываем его на месно старого регистра
;------------------------------------------------------------------------------------------------
_gogogo_:
	pop		edi
_srav2_:
_isklok02_:
	cmp		esi,ebx                                 	;все ли мы сделали?
	jb		_SECONDSTAGE_
;================================================================================================




;================================================================================================
;||============================================================================================||
;||                        ##########  ##########  ##########                                  ||              
;||				           ##########  ##########  ##########                                  ||        
;||                           ####        ####        ####                                     ||
;||                           ####        ####        ####                                     ||
;||                           ####        ####        ####                                     ||
;||                           ####        ####        ####                                     ||
;||                        ##########  ##########  ##########                                  ||        
;||                        ##########  ##########  ##########                                  ||        
;||============================================================================================||
;================================================================================================
_THIRDSTAGE_:											;III этап
	sub		esi,AddrSrcCode
	mov		SizeSrcCode,esi
	pop		edx
	pop		ecx
	pop		eax                                         ;в eax - адрес (в стэке), где хранятся адреса переходов, записанных в новый буфер уже 5/6-байтовыми
	add		eax,edx                                     ;теперь еах указывает на последний адрес (последний переход) (-4 байта)
	add		esp,NumJMP*4
	test	ecx,ecx            							;есть ли вообще в исходном коде переходы?
	je		_absentjxxcalljmp2_                     	;если нет, то перескакиваем:)!
_cycle2jxx_:
	xor		esi,esi
	inc		esi
	sub		eax,4
	mov		ebx,dword ptr [eax]                         ;в ebx - очередной адрес перехода в искомом буфере
	pop		edx                                         ;вытаскиваем адрес перехода в исходном буфере
	pop		edx                                         ;в edx - операнд (уже полностью скорректированный), соответствующий своему переходу
	cmp		byte ptr [ebx],0fh                          ;это jxx near?
	jne		_jxx5byte_                                  ;если нет (значит это call/jmp near), то перескакиваем дальше
	inc		esi
_jxx5byte_:
	mov		dword ptr [ebx+esi],edx
	dec		ecx
	jne		_cycle2jxx_
	
_absentjxxcalljmp2_:	
	sub		edi,AddrDisCode								;считаем сколько байт мы записали в новый буфер
	push	edi                                     	;и сохраняем его
	pop		dword ptr [ebp-4*1]
	push	AddrDisCode                             	;а также сохраняем адрес этого нового буфера
	pop		dword ptr [ebp-4*8]	
	push	SizeSrcCode
	pop		dword ptr [ebp-4*2]

	popad                                               ;восстанавливаем регистры
	pop		ebp
	ret		4*7                                         ;выходим!
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;Конец функции SPECTR
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx




;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;функция zero_mem
;сброс содержимого некоторого буфера
;Вход:
;edi - адрес буфера, чье содержимое надо обнулить
;Выход:
;еах - 0
;буфер чист
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
zero_mem:
	push	28/4										;
	pop		eax                                     	;в еах - размер структуры для дизасма!!!!!!!
_memset_:
	and		dword ptr [edi+eax*4-4],0               	;обнуляем все поля этой структуры
	dec		eax
	jne		_memset_
	ret
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;конец функции zero_mem
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx





;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;функция get_res_reg
;получение нового регистра, соответствующего старому
;Заметки: делается это так: есть массив этих самых новых регистров, 
;сгенерированных по определенным правилам. Так вот, чтобы, к примеру получить 
;новый рег для eax, берем из этого массива элемент с индексом 0; для ecx - с 
;индексом 1, etc
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
get_res_reg:
	push	ecx
	mov		ecx,TMPAddr
	mov		al,byte ptr [ecx+eax]
	pop		ecx
	ret
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;конец функции get_res_reg
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx








comment #
reg_mut:
	pushad
	mov		edi,TMPAddr
	xor		ecx,ecx
new_reg:
;------------------------------------------------------------------------------------------------
	push	eax
	pushad
_isklspectr4_:                                          ;очередная заглушка:)!
	push	4                                    		;сначала сгенерируем 1-ую группу
	pop		eax	
	call	dword ptr [esp+36+4+32]							;вызываем ГСЧ
	mov		dword ptr [esp+32],eax;20h
Sizeiskspectr4		equ $ - _isklspectr4_
	popad
	pop		eax
;------------------------------------------------------------------------------------------------	
	lea		edx,[ecx+1]
_check_:
	cmp		al,byte ptr [edi+edx-1]
	je		new_reg	
	dec		edx
	jne		_check_
	mov		byte ptr [edi+ecx],al
	inc		ecx
_cmp_:
	cmp		ecx,4;8
	jne		new_reg
	popad
	ret		4
        #








;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;функция reg_mut
;генерация регистров
;Заметки: в данном движке регистры генерятся по группам:
;1 группа: al(eax),cl(ecx),dl(edx),bl(ebx)
;2 группа: ah(esp),ch(ebp),dh(esi),bh(edi)
;Регистры могут меняться только внутри своей группы, и еще:
;в данном движке не предусмотрено изменение регистро esp & ebp - 
;они стоят на своих местах - быть осторожным!
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
reg_mut:
	pushad
	mov		edi,TMPAddr
	xor		ecx,ecx
new_reg:
;------------------------------------------------------------------------------------------------
	push	eax
	pushad
_isklspectr4_:                                          ;очередная заглушка:)!
	push	4                                    		;сначала сгенерируем 1-ую группу
	pop		eax	
	call	dword ptr [esp+36+4+32]						;вызываем ГСЧ
	mov		dword ptr [esp+32],eax;20h
Sizeiskspectr4		equ $ - _isklspectr4_
	popad
	pop		eax
;------------------------------------------------------------------------------------------------	
	mov		dl,byte ptr [edi+eax]
	mov		dh,byte ptr [edi+ecx]
	mov		byte ptr [edi+eax],dh
	mov		byte ptr [edi+ecx],dl	
	inc		ecx
	cmp		ecx,4;8
	jne		new_reg
	popad
	ret		4
SizeMut	equ		$-reg_mut
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;конец функции reg_mut
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx







;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;Функция swap_eax_reg
;вспомогательная функция (поэтому параматры описывать не буду - смотри исходник:)!
;учавствует в превращении команд вида:   comand al/ax/eax,reg     в     comand reg1,reg2
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
swap_eax_reg:
	mov		byte ptr [edi],al                      		;строим:)!
	inc		edi
	xor		eax,eax
	call	get_res_reg          						;получим регистр, соответствующий регистру eax
	push	eax
	mov		al,byte ptr [edx+9]
	and		al,cl;0;00111000b
	add		al,0c0h                                 	;etc
	add		eax,[esp]
	mov		byte ptr [edi],al
	inc		edi
	pop		eax
	mov		eax,dword ptr [edx+20]
	ret
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;Конец функции swap_eax_reg
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx





;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;Функция obr_iskl_1 (обработка_исключений_1)
;Делает следующее: если текущий проверяемый адрес (esi) есть в таблице исключений, 
;то мы увеличиваем esi на столько байт, сколько 
;указано в табличке исключений. Тем самым, мы перескакиваем через эти байты (то есть дизасм их 
;не обрабатывает).
;Это нужно, если по адресу в esi находятся какие-то данные (например, строка).
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

obr_iskl_1:
	push	eax
	call	poisk_iskl									;вызываем функцию поиска и заданного адреса в таблице исключений (или его там нет)
	test	eax,eax
	je		_noiskl1_
	add		esi,dword ptr [eax+4]
_noiskl1_:
	pop		eax
	ret
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;Конец функции obr_iskl1
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx






;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;Функция obr_iskl_2 (обработка_исключений_2)
;Делает следующее: если текущий проверяемый адрес (esi) есть в таблице исключений, 
;то мы записываем в буфер (edi), начиная с этого адреса (который в esi), столько байт, сколько 
;указано в табличке исключений. Тем самым, эти байты мы только записываем, не изменяя их.
;Это нужно, если по адресу в esi находятся какие-то данные (например, строка).
;И еще эта функция корректирует адреса в табличке исключений.
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
obr_iskl_2:
	push	eax
	push	edx
	push	ebx
	call	poisk_iskl									;вызываем функцию, которая смотрит, есть ли текущий адрес в табличке исключений
	test	eax,eax
	je		_noiskl2_		

	mov		ebx,edi
	sub		ebx,AddrDisCode

	sub		ebx,esi
	add		ebx,AddrSrcCode                             ;в ebx - количество байт, на сколько надо увеличить 
														;заданный адрес в табличке исключений. Это считается так:
														;Узнаем размер записанных байт в новом буфере (на который указывает edi) - обозначим их как A.
														;Затем узнаем размер байт, пройденных нашим дизасмом в старом буфере (на него указывает esi) - обозначим их как B. 
														;ebx= A - B.
														;так как, наверняка мы находили 2-байтовые переходы, превращали их в 5/6-байтовые и записывали 
														;такими в новый буфер (edi), то естесственно в новом буфере мы записали больше байт.

	;mov	edx,esi
	;sub	edx,AddrSrcCode
	;sub	ebx,edx
	add		dword ptr [eax],ebx                         ;увеличиваем

	mov		ebx,dword ptr [eax+4]                       ;в ebx - кол-во байт, которые надо скопировать
_copy_:
	mov		dl,byte ptr [esi]
	mov		byte ptr [edi],dl
	inc		edi
	inc		esi
	dec		ebx                                         ;копируем
	jne		_copy_
	add		eax,8                                       ;корректируем
	mov		AddrIskl,eax                                ;теперь в следующий раз начнем поиск с адреса + 1.
	;jmp	_noiskl_
_noiskl2_:
	pop		ebx
	pop		edx
	pop		eax
	ret
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;Конец функции obr_iskl_2
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx









;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;Функция poisk_iskl (поиск_исключения)
;проверяет, есть текущий адрес (который в esi) в табличке исключений. Если да, то eax!=0, иначе 
;eax=0.
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

poisk_iskl:
	push	edx
	mov		eax,AddrIskl
	test	eax,eax										;табличка пустая?
	je		_noiskl3_
	cmp		word ptr [eax],0ffffh                       ;или же обработаны все адреса в табличке исключений?
	je		_noiskl3_

_nxtaddriskl3_:

	mov		edx,AddrSrcCode                             ;!!!!!!! Вот эти 2 строки следует 
	add		edx,dword ptr [eax]                     	;!!!!!!! закоментить, если ты хочешь в ТИ 
														;!!!!!!! использовать адреса.
	;mov		edx,dword ptr [eax]						;!!!!!!! А вот эту строку раскоментить:)!
	
	cmp		esi,edx                                     ;смотрим, находитя ли заданный адрес в табличке исключений
	je		_OKEAX_

_dececx3_:
	add		eax,8
	cmp		word ptr [eax],0ffffh
	jne		_nxtaddriskl3_
_noiskl3_:
	xor		eax,eax
_OKEAX_:
	pop		edx
	ret
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;Конец функции poisk_iskl
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx






;================================================================================================
;флаги
;------------------------------------------------------------------------------------------------
P_NONE			equ		00h					;xex
P_MODRM			equ		01h             				;present byte MODRM
P_DATA8			equ		02h             				;present imm8,rel8, etc
P_DATA16		equ		04h             				;present imm16,rel16, etc
P_PREFIX6X		equ		08h             				;present imm16/imm32 (в зависимости от наличия префикса 0x66 (0x67 для опкодов 0xA0-0xA3))
P_SEG			equ		10h             				;present segment (пример: 0x2e,0x3E, etc)
P_PFX66			equ		20h             				;present byte 0x66
P_PFX67			equ		40h             				;present byte 0x67
P_LOCK			equ		80h             				;present byte LOCK (0xF0)
P_REP			equ		100h            				;present byte rep[e/ne]
P_OPCODE2		equ		200h            				;present second opcode (first opcode=0x0F)
P_SIB			equ		400h							;present byte SIB
P_RELX			equ		800h							;present jxx/jmp/call (rel8,rel16,rel32)
;================================================================================================

fnDizasm32		equ 	dword ptr [ebp+08]				;адрес дизассемблера
fnRand			equ 	dword ptr [ebp+12]          	;адрес ГСЧ
SizeSrcCode		equ 	dword ptr [ebp+16]              ;размер кода, который надо проморфить                           
AddrSrcCode		equ 	dword ptr [ebp+20]				;адрес кода, который надо проморфить
AddrDisCode		equ 	dword ptr [ebp+24]				;адрес, куда будет записан уже проморфенный код
TMPAddr			equ 	dword ptr [ebp+28]				;буфер для дизасма (в котором будет храниться разобранная 
														;команда + необходимая инфа к ней)
														;!!!!!!! Потом в нем будет храниться адрес массива BufReg!
AddrIskl		equ 	dword ptr [ebp+32]
;ж-----------------------------------------------------------------------------------------------							
SizeOfSPECTR	equ		$-SPECTR
;================================================================================================
