;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; ; ; ### ; ; ### ; ; ### #################################################### ; ; ### #################################################### ; ; ### ### ### ; ; ### ### ### ######### ### ; ; ### ### ### ########### ; ; ### ### ## ## ; ; ### ### ### ## ## ; ; ### ### ### ## ## ; ; ### ### ### ### ## ## ; ; ### ### ### ### ## ## ; ; ############ ### ### ########### ; ; ################################################################ ; ; ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; Advanced Length dIsassembler moTOr:) ; ; ; ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ; ; ; Версия 2.1 ; ; ; ;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 call _delta_lito_ ;=================================================================================== ;строка префиксов pfx: db 2Eh,36h,3Eh,26h,64h,65h,0F2h,0F3h,0F0h,66h,67h SizePfx equ $-pfx ;длина pfx ;=================================================================================== ;таблица флагов для однобайтных опкодов 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 $-pfx ;=================================================================================== ;флаги ;----------------------------------------------------------------------------------- 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) ;=================================================================================== _delta_lito_: pop ebp cld xor eax,eax xor ebx,ebx cdq ;в edx: dl(0/1) - нет/есть префикс 0x66 ; dh(0/1) - нет/есть префикс 0x67 ;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxBEG поиск префиксовxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx _nextpfx_: lodsb ;получаем очередной байт команды push edi lea edi,[ebp+(pfx-_delta_lito_+SizeTbl)] ;в edi - адрес строки префиксов db 6Ah,SizePfx pop ecx repne scasb ;есть ли в разбираемой команде префиксы? pop edi jne _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_: mov ch,al and ch,0FEh cmp ch,0E8h je _jxxok_ mov ch,al and ch,11110000b cmp ch,70h je _jxxok_ cmp al,0EBh je _jxxok_ cmp al,0Fh ;опкод состоит из 2-х байт? jne _opcode_ lodsb ;если да, то берем 2-ой байт опкода mov cl,80h ;и увеличиваем cl=80h or bx,B_OPCODE2 mov ch,al and ch,11110000b cmp ch,80h jne _opcode_ _jxxok_: or bx,B_RELX ;----------------------------------------------------------------------------------- _opcode_: xor ch,ch mov byte ptr [edi+09h],al ;save first opcode lea ebp,[ebp+ecx+(TableFlags1-_delta_lito_+SizeTbl)];в edi - адрес нужной таблицы флагов(хар-к) 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_ ;нет? на выход 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 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 rep movsb sub edi,ebp add edi,8 mov ecx,ebx 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 SizeOfLiTo equ $-_LiTo_ ;размер функции _LiTo_