;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
;                                                                                  ;
;                                                                                  ;
;                                                                      ###         ;
;                                                                        ###       ;
;             ###        ####################################################      ;
;             ###        ####################################################      ;
;             ###                      	 ###                             ###       ;
;             ###             ###    	 ###           #########       ###         ;
;             ###             ###    	 ###          ###########                  ;
;             ###                    	 ###         ##         ##                 ;
;             ###             ###    	 ###         ##         ##                 ;
;             ###             ###    	 ###         ##         ##                 ;
;             ###      ###    ###    	 ###         ##         ##                 ;
;             ###      ###    ###    	 ###         ##         ##                 ;
;             ############    ###    	 ###          ###########                  ;
;       ################################################################	   	   ;            
;                                                                                  ;
;                                                                                  ;                                                                          
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
;                                                                                  ;
;             		Advanced Length dIsassembler moTOr:)                           ;
;                                                                                  ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
;                                                                                  ; 
;                               	Версия 2.3					                   ;                                                
;       	(СПЕЦ. ВЫПУСК:) ДЛЯ ПРОВЕРКИ РАБОТОСПОСОБНОСТИ МЕТАМОРФА			   ;                                                                    
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
;функция _LiTo_                                                                    ;
;дизассемблирование машинной команды						                       ;
;определение длины машинной команды                                                ;
;Вход:                                                                             ;
;esi - адрес разбираемой машинной команды                                          ;
;edi - указатель на выходную структуру (или буфер) (назовем ее INSTR:)		       ;
;Выход:                                                                            ;
;в eax - длина машинной команды.                                                   ;
;Заметки:                                                                          ;
;(x) Выходная структура (или буфер) заполняется в процессе дизассемблирования      ;
;инструкции и должна представлять собой следующее:                                 ;
;                                                                                  ;
;	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                                                                   ;
;                                                                                  ;
;(х) понимаются (пока) только general purpose & fpu instructions                   ;
;    (остальные - в топку:)!                                                       ;
;(х) нет проверки на максимальную длину инструкции (15 байт) (нахрен)              ;
;(х) Как построены эти таблички:                                                   ;
;	ОЧЕНЬ ПРОСТО: так как в этом дизасме используются флаги с числовым    	       ;
;	обозначением <=8, то для одного флага достаточно места в половину байта        ;
;	(максимальное число =8 (B_PREFIX6X) - в двоичном представлении =1000b).        ;
;	Зная это, просто тупо в один байт запихиваем 2 флага - вот и все. Таким        ;
;	образом, каждая табличка в 256 байт урезается до 128.                          ;                            
;(х) Для 32-битного исполняемого кода.						                       ;
;(х) Кто хочет, пусть нафиг сам и добавляет остальные команды и всякие там         ;
;    проверки.                                                                     ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
                                                                                   ;
                                                                                   ;
                                                                                   ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
;				ФИЧИ:                                                              ;
;(+) базонезависимость								                               ;
;(+) упакованные таблички							                               ;                                           
;                                                                                  ;
;(-) муторно добавлять новые инструкции						   					   ;                                                                                                                                                   
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
                                                                                   ;
                                                                                   ;
                                                                                   ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
;				ИСПОЛЬЗОВАНИЕ:                                     				   ;
;1)Подключение:                                                                    ;
;	lito.asm                                                                   	   ;
;2)Вызов:(пример)                                                                  ;
;	lea	esi,XXXXXXXXh	;адрес команды, чью длину надо узнать		   			   ;              
;	lea	edi,XXXXXXXXh	;lea edi,INSTR1					                           ;
;	call	LiTo                                                                   ;                                                                                                                  
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
                                                                                   

																	;m1x
							           						;pr0mix@mail.ru	

_LiTo_:
	pushad
	cld
	call	_ddd_
_ddd_:
	pop		ebp	
	sub     ebp,_ddd_
	xor		eax,eax
	xor		ebx,ebx
	xor		edx,edx
	;cdq				        							;в edx: dl(0/1) - нет/есть префикс 0x66
	                                                        ;	dh(0/1) - нет/есть префикс 0x67
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxBEG поиск префиксовxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
_nextpfx_:					
	;lodsb                                					;получаем очередной байт команды
	mov		al,byte ptr [esi]
	inc		esi
	push	edi
	call	_addrpfx_

;===================================================================================
;строка префиксов
pfx:
db 2Eh,36h,3Eh,26h,64h,65h,0F2h,0F3h,0F0h,66h,67h
;-----------------------------------------------------------------------------------
SizePfx		equ $-pfx										;длина pfx
;===================================================================================

_addrpfx_:
	pop		edi
	db		6Ah,SizePfx
	pop		ecx
_nxtprefix_:
	cmp		byte ptr [edi],al
	je		@F
	inc		edi
	dec		ecx
	jne		_nxtprefix_
	;repne	scasb                                           ;есть ли в разбираемой команде префиксы?
@@:
	pop		edi
	test	ecx,ecx
	je		_endpfx_                                        ;нет? - на выход
	cmp		ecx,5
	jl		_lock_
	or		bl,B_SEG
	mov		byte ptr [edi+05h],al							;seg
_lock_:
	cmp		al,0F0h
	jne		_rep_
	or		bl,B_LOCK
_rep_:
	mov		ch,al
	and		ch,0FEh
	cmp		ch,0F2h
	jne		_66_
	or		bx,B_REP
	mov		byte ptr [edi+06h],al							;rep
_66_:
	cmp		al,66h                                          ;иначе смотрим, это 0x66?
	jne		_67_
	mov		dl,1
	or		bl,B_PFX66
_67_:
	cmp		al,67h                                          ;иначе, это 0x67?
	jnz		_nextpfx_                                       ;если нет, то ищем другие префиксы
	mov		dh,1
	or		bl,B_PFX67
	jmp		_nextpfx_                                       ;продолжаем поиск
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxEND поиск префиксовxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
_endpfx_:
_search_jxx_call_jmp_:
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxBEG это jmp/jxx/call ?xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
	mov		ch,al
	and		ch,0FEh
	cmp		ch,0E8h                                         ;0xe9, 0xe8 (call/jmp near)
	je		_jxxok_		
	mov		ch,al
	and		ch,11110000b
	cmp		ch,70h                                          ;[0x70,0x7f] (jxx short)
	je		_jxxok_
	cmp		al,0EBh                                         ;0xEB (jmp short)
	je		_jxxok_
	cmp		al,0Fh                                        	;опкод состоит из 2-х байт?
	jne		_opcode_
	mov		al,byte ptr [esi]
	inc		esi
	;lodsb                                                  ;если да, то берем 2-ой байт опкода
	mov		cl,80h                                          ;и увеличиваем cl=80h
	or		bx,B_OPCODE2
	mov		ch,al
	and		ch,11110000b
	cmp		ch,80h                                          ;[0x80,0x8f] (jxx near:)!:)!!!!!
	jne		_opcode_
_jxxok_:
	or		bx,B_RELX                                       ;если это какой-нить из перечисленных переходов, то возводим нужный флаг:)!
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxEND это jmp/jxx/call ?xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;-----------------------------------------------------------------------------------
_opcode_:
	xor		ch,ch
    mov		byte ptr [edi+09h],al							;save first opcode
	call	_addrtbl_

;===================================================================================
;таблица флагов для однобайтных опкодов
TableFlags1:

;  01  23  45  67  89  AB  CD  EF
db 11h,11h,28h,00h,11h,11h,28h,00h	;00
db 11h,11h,28h,00h,11h,11h,28h,00h  ;01
db 11h,11h,28h,00h,11h,11h,28h,00h  ;02
db 11h,11h,28h,00h,11h,11h,28h,00h  ;03
db 00h,00h,00h,00h,00h,00h,00h,00h	;04
db 00h,00h,00h,00h,00h,00h,00h,00h	;05
db 00h,11h,00h,00h,89h,23h,00h,00h	;06
db 22h,22h,22h,22h,22h,22h,22h,22h	;07
db 39h,33h,11h,11h,11h,11h,11h,11h	;08
db 00h,00h,00h,00h,00h,0C0h,00h,00h	;09
db 88h,88h,00h,00h,28h,00h,00h,00h	;0A
db 22h,22h,22h,22h,88h,88h,88h,88h	;0B
db 33h,40h,11h,39h,60h,40h,02h,00h	;0C
db 11h,11h,22h,00h,11h,11h,11h,11h	;0D
db 22h,22h,22h,22h,88h,0C2h,00h,00h	;0E
db 00h,00h,00h,11h,00h,00h,00h,11h	;0F


;===================================================================================

;таблица флагов для двухбайтных опкодов
TableFlags2:

;  01  23  45  67  89  AB  CD  EF
db 11h,11h,00h,00h,00h,00h,01h,00h	;00
db 00h,00h,00h,00h,00h,00h,00h,01h	;01
db 11h,11h,00h,00h,00h,00h,00h,00h	;02
db 00h,00h,00h,00h,00h,00h,00h,00h	;03
db 11h,11h,11h,11h,11h,11h,11h,11h	;04
db 00h,00h,00h,00h,00h,00h,00h,00h	;05
db 00h,00h,00h,00h,00h,00h,00h,00h	;06
db 00h,00h,00h,00h,00h,00h,00h,00h	;07
db 88h,88h,88h,88h,88h,88h,88h,88h	;08
db 11h,11h,11h,11h,11h,11h,11h,11h	;09
db 00h,01h,31h,00h,00h,01h,31h,01h	;0A
db 11h,11h,11h,11h,00h,31h,11h,11h	;0B
db 11h,00h,00h,01h,00h,00h,00h,00h	;0C
db 00h,00h,00h,00h,00h,00h,00h,00h	;0D
db 00h,00h,00h,00h,00h,00h,00h,00h	;0E
db 00h,00h,00h,00h,00h,00h,00h,00h	;0F   
;===================================================================================

SizeTbl		equ $-TableFlags1
;===================================================================================

_addrtbl_:
	pop		ebp
	add		ebp,ecx
	cmp		al,0A0h                                         ;если опкод>=0xA0 и опкод<=A3,
	jl		_01_;jb                                            ;
	cmp		al,0A3h
	jg		_01_
	test	cl,cl
	jne		_01_;je                                 		;то dl=dh
	mov		dl,dh											;mov	dl,dh
;-----------------------------------------------------------------------------------
_01_:
	push	eax
	shr		eax,1
	mov		cl,byte ptr [ebp+eax]							;в cl - флаги команды
	jc		_noCF_
	shr		cl,4
_noCF_:
    and		cl,0Fh
	xor		ebp,ebp				        					;в ebp - будет храниться длина смещения(offset)

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxBEG разбор MODRMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

    or		ecx,ebx
	pop		ebx												;bl=opcode
	test	cl,B_MODRM                                      ;присутствует ли байт modrm?
	je		_endmodrm_                                      ;нет? на выход
	mov		al,byte ptr [esi]
	inc		esi
	;lodsb                 	  								;al=modrm
	mov		byte ptr [edi+10],al							;MODRM
	mov		ah,al
;-----------------------------------------------------------------------------------
	shr		ah,6   											;ah=mod
;-----------------------------------------------------------------------------------	
	test	al,38h    										;далее смотрим, равно ли поле reg==0?
	jne		_03_
	sub		bl,0F6h                                         ;если да, то смотрим на опкод:
	jne		_02_                                            ;равен ли он 0xF6 или 0xF7(test)?
	or		cl,B_DATA8                                      ;если да, то устанавливаем нужный флаг
_02_:
	dec		ebx
	jne		_03_
	or		cl,B_PREFIX6X
;-----------------------------------------------------------------------------------	
_03_:
	and		al,07h
	xor		ebx,ebx                                         ;bl отвечает за присутствие байта sib
	mov		bh,ah                                           ;bh=mod
	cmp		dh,1                                      		;есть ли в разбираемой команде префикс 0x67?                            		
	je		_mod00_                                         ;если да, то перескакиваем
	cmp		al,4                                            ;иначе проверяем,равно ли поле rm==4?
	jne		_mod00_
	inc		ebx                                             ;если да, то возможно есть sib
;-----------------------------------------------------------------------------------
_mod00_:
	test	ah,ah                                           ;поле mod==0?
	jne		_mod01_
	dec		dh                                      		;содержит ли команда 0x67?						
	jne		_nop67_	                                        ;нет? перескакиваем
	cmp		al,6                                            ;если да, то rm==6?
	jne		_sib_
	inc		ebp                                             ;если да, то длина смещения=2(16 bit)
	inc		ebp
_nop67_:
	cmp		al,5                                            ;иначе, rm==5?
	jne		_sib_
	add		ebp,4                                           ;если да, то длина оффсета=4 (32 bit)
	jmp		_sib_                                           ;идем дальше
;-----------------------------------------------------------------------------------		
_mod01_:		                                        	;mod==1?
	dec		ah                                              
	jne		_mod02_
	inc		ebp                                             ;да? тогда ebp=1
	jmp		_sib_		
;-----------------------------------------------------------------------------------	                        
_mod02_:                                    				;mod==2?
	dec		ah
	jne		_mod03_
	inc		ebp             								;ebp=2
	inc		ebp
	dec		dh                                      		;если есть префикса 0x67, перескакиваем дальше
	je		_sib_
	inc		ebp                                             ;то ebp+=2
	inc		ebp          	
	inc		ebx
;-----------------------------------------------------------------------------------
_mod03_:                                                    ;mod==3?
    dec		bl                                              ;если да, тогда sib'а точно нет!
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxEND разбор MODRMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxBEG получение SIBxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
_sib_:
	dec		bl                                              ;есть ли байт sib?
	jne		_endmodrm_
	or		cx,B_SIB
	mov		al,byte ptr [esi]
	inc		esi
	;lodsb                                                  ;если да, то в al теперь лежит sib(al=sib) 
	mov		byte ptr [edi+11],al							;SIB
	and		al,7                                            ;далее, 
	cmp		al,5                                            ;al==5?
	jne		_endmodrm_
	test	bh,bh                                           ;если да, то смотрим, поле mod==0?
	jne		_endmodrm_
	push	4                                               ;если да, то есть 4-байтовое смещение
	pop		ebp
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxEND получение SIBxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxBEG флагиxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
_endmodrm_:
    xor		ebx,ebx
	test	cl,B_DATA8                                  	;есть ли однобайтовое смещение?
	je		_nf1_
	inc		ebx
_nf1_:
	test	cl,B_DATA16                                     ;есть ли двухбайтовое смещение?
	je		_nf2_
	inc		ebx
	inc		ebx
_nf2_:
	test	cl,B_PREFIX6X                                   ;есть ли в команде непосредственное значение?
	je		_endflag_
	dec		dl												;есть ли 0x66(0x67 для [0xA0,0xA3]) в разбираемой команде?                                              
	je		_okp66_
	inc		ebx
	inc		ebx
_okp66_:
    inc		ebx
    inc		ebx
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxEND флагиxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
_endflag_:
    push	ecx
    push	edi
    mov		ecx,ebp
    add		edi,12
    test	ecx,ecx											;есть ли у разбираемой команды смещение
    je		@F
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxBEG копируем смещение (если оно есть)xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
_repmovsb1_:
	mov		al,byte ptr [esi]
	mov		byte ptr [edi],al
	inc		esi
	inc		edi
	dec		ecx
	jne		_repmovsb1_
    ;rep	movsb
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxEND копируем смещение (если оно есть)xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    	
@@:
    sub		edi,ebp
    add		edi,8
    mov		ecx,ebx
    test	ecx,ecx 										;есть ли у разбираемой команды операнд
    je		@F
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxBEG копируем операнд (если он есть)xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
_repmovsb2_:
	mov		al,byte ptr [esi]
	mov		byte ptr [edi],al
	inc		esi
	inc		edi
	dec		ecx
	jne		_repmovsb2_
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxEND копируем операнд (если он есть)xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
@@:
    ;rep	movsb
    pop		edi
	pop		dword ptr [edi+1]
	sub		esi,dword ptr [esp+4];eax
	xchg	esi,eax
	mov		byte ptr [edi+0],al
	mov		dword ptr [esp+7*4],eax                         ;сохраняем размер в еах
	xchg	ebp,eax
	mov		byte ptr [edi+7],al
	mov		byte ptr [edi+8],bl	
	popad
	ret	                                               		;выходим:)
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
;Конец функции _LiTo_                                                              ;
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx



;===================================================================================
;флаги
;-----------------------------------------------------------------------------------
B_NONE		equ	00h		;xex
B_MODRM		equ	01h             ;present byte MODRM
B_DATA8		equ	02h             ;present imm8,rel8, etc
B_DATA16	equ	04h             ;present imm16,rel16, etc
B_PREFIX6X	equ	08h             ;present imm16/imm32 (в зависимости от наличия префикса 0x66 (0x67 для опкодов 0xA0-0xA3))
B_SEG		equ	10h             ;present segment (пример: 0x2e,0x3E, etc)
B_PFX66		equ	20h             ;present byte 0x66
B_PFX67		equ	40h             ;present byte 0x67
B_LOCK		equ	80h             ;present byte LOCK (0xF0)
B_REP		equ	100h            ;present byte rep[e/ne]
B_OPCODE2	equ	200h            ;present second opcode (first opcode=0x0F)
B_SIB		equ	400h			;present byte SIB
B_RELX		equ	800h			;present jxx/jmp/call (rel8,rel16,rel32)
;===================================================================================

SizeOfLiTo	equ $-_LiTo_		;размер функции _LiTo_
