//////////////////////////////////////////////////////////////////////////////// // // // OllyDbg Disassembling Engine v2.01 // // // // Copyright (c) 2007-2013 Oleh Yuschuk, ollydbg@t-online.de // // // // This code is part of the OllyDbg Disassembler v2.01 // // // // Disassembling engine is free software; you can redistribute it and/or // // modify it under the terms of the GNU General Public License as published // // by the Free Software Foundation; either version 3 of the License, or (at // // your option) any later version. // // // // This code is distributed in the hope that it will be useful, but WITHOUT // // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // // more details. // // // // You should have received a copy of the GNU General Public License along // // with this program. If not, see . // // // //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // // // This is a fast disassembler that can be used to determine the length of // // the binary 80x86 32-bit command and its attributes, to convert it to the // // human-readable text form, highlight its operands, and create hexadecimal // // dump of the binary command. // // // // It is a stripped down version of the disassembler used by OllyDbg 2.01. // // It can't analyse and comment the contents of the operands, or predict the // // results of the command execution. Analysis-dependent features are not // // included, too. Most other features are kept. // // // // Disassembler supports integer, FPU, MMX, 3DNow, SSE1-SSE4.1 and AVX // // instructions. 64-bit mode, AVX2, FMA and XOP are not (yet) supported. // // // // This code can be compiled either in ASCII or UNICODE mode. It is reentrant // // (thread-safe, feature not available in the original OllyDbg code). // // // // Typical operation speed on 3-GHz Phenom II in MASM mode is: // // // // Command length and info: 130 ns/command (7,700,000 commands/s) // // Disassembly: 290 ns/command (3,400,000 commands/s) // // Disassembly, dump, highlighting: 350 ns/command (2,800,000 commands/s) // // // //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// ////////////// PREFERRED SETTINGS AND FIXES FOR BORLAND COMPILERS ////////////// #ifdef __BORLANDC__ #pragma option -a1 // Byte alignment #pragma option -w-pin // Disable "partially bracketed" warning // Redefinition of MAKELONG removes nasty warning under Borland Builder 4.0: // boolean OR in one row with arithmetical shift. #undef MAKELONG #define MAKELONG(lo,hi) ((LONG)(((WORD)(lo))|(((DWORD)((WORD)(hi)))<<16))) #endif #define MAKEWP(lo,hi) ((WPARAM)MAKELONG(lo,hi)) #define MAKELP(lo,hi) ((LPARAM)MAKELONG(lo,hi)) #define LOINT(l) ((signed short)((WORD)(l))) #define HIINT(l) ((signed short)(((DWORD)(l)>>16) & 0xFFFF)) #ifndef FIELD_OFFSET #define FIELD_OFFSET(type,field) ((long)&(((type *)0)->field)) #endif //////////////////////////////////////////////////////////////////////////////// #define TEXTLEN 256 // Max length of text string #define SHORTNAME 32 // Max length of short or module name #ifdef UNICODE #define tchar wchar_t // Or replace it with TCHAR #define T(x) L##x #define tstrlen wcslen #define tstrcpy wcscpy #define tstrcmp wcscmp #define tstrlwr _wcslwr #define tsprintf swprintf #define ttolower towlower #else #define tchar char #define T(x) x #define tstrlen strlen #define tstrcpy strcpy #define tstrcmp strcmp #define tstrlwr strlwr #define tsprintf sprintf #define ttolower tolower #endif #define NOPERAND 4 // Maximal allowed number of operands #define NREG 8 // Number of registers (of any type) #define NSEG 6 // Number of valid segment registers #define MAXCMDSIZE 16 // Maximal length of valid 80x86 command #define NEGLIMIT (-16384) // Limit to decode offsets as negative #define DECLIMIT 16384 // Limit to decode constants as decimal typedef unsigned char uchar; // Unsigned character (byte) typedef unsigned short ushort; // Unsigned short typedef unsigned int uint; // Unsigned integer typedef unsigned long ulong; // Unsigned long // CMDMASK can be used to balance between the necessary memory size and the // disassembly time. #define CMDMASK 0x3FFF // Search mask for Disassembler, 2**n-1 #define NCHAIN 44300 // Max allowed number of chain links // Registers. #define REG_UNDEF (-1) // Codes of general purpose registers #define REG_EAX 0 #define REG_ECX 1 #define REG_EDX 2 #define REG_EBX 3 #define REG_ESP 4 #define REG_EBP 5 #define REG_ESI 6 #define REG_EDI 7 #define REG_AL 0 // Symbolic indices of 8-bit registers #define REG_CL 1 #define REG_DL 2 #define REG_BL 3 #define REG_AH 4 #define REG_CH 5 #define REG_DH 6 #define REG_BH 7 #define SEG_UNDEF (-1) // Codes of segment/selector registers #define SEG_ES 0 #define SEG_CS 1 #define SEG_SS 2 #define SEG_DS 3 #define SEG_FS 4 #define SEG_GS 5 // Command highlighting. #define DRAW_PLAIN '.' //0x0000000C // Plain commands #define DRAW_JUMP '>' //0x0000000D // Unconditional jump commands #define DRAW_CJMP '?' //0x0000000E // Conditional jump commands #define DRAW_PUSHPOP '=' //0x0000000F // PUSH/POP commands #define DRAW_CALL '@' //0x00000010 // CALL commands #define DRAW_RET '<' //0x00000011 // RET commands #define DRAW_FPU '1' //0x00000012 // FPU, MMX, 3DNow! and SSE commands #define DRAW_SUSPECT '!' //0x00000013 // Bad, system and privileged commands // Operand highlighting. #define DRAW_IREG 'R' //0x00000018 // General purpose registers #define DRAW_FREG 'F' //0x00000019 // FPU, MMX and SSE registers #define DRAW_SYSREG 'S' //0x0000001A // Segment and system registers #define DRAW_STKMEM 'K' //0x0000001B // Memory accessed over ESP or EBP #define DRAW_MEM 'M' //0x0000001C // Any other memory #define DRAW_CONST 'C' //0x0000001E // Constant #define D_NONE 0x00000000 // No special features // General type of command, only one is allowed. #define D_CMDTYPE 0x0000001F // Mask to extract type of command #define D_CMD 0x00000000 // Ordinary (none of listed below) #define D_MOV 0x00000001 // Move to or from integer register #define D_MOVC 0x00000002 // Conditional move to integer register #define D_SETC 0x00000003 // Conditional set integer register #define D_TEST 0x00000004 // Used to test data (CMP, TEST, AND...) #define D_STRING 0x00000005 // String command with REPxxx prefix #define D_JMP 0x00000006 // Unconditional near jump #define D_JMPFAR 0x00000007 // Unconditional far jump #define D_JMC 0x00000008 // Conditional jump on flags #define D_JMCX 0x00000009 // Conditional jump on (E)CX (and flags) #define D_PUSH 0x0000000A // PUSH exactly 1 (d)word of data #define D_POP 0x0000000B // POP exactly 1 (d)word of data #define D_CALL 0x0000000C // Plain near call #define D_CALLFAR 0x0000000D // Far call #define D_INT 0x0000000E // Interrupt #define D_RET 0x0000000F // Plain near return from call #define D_RETFAR 0x00000010 // Far return or IRET #define D_FPU 0x00000011 // FPU command #define D_MMX 0x00000012 // MMX instruction, incl. SSE extensions #define D_3DNOW 0x00000013 // 3DNow! instruction #define D_SSE 0x00000014 // SSE instruction #define D_IO 0x00000015 // Accesses I/O ports #define D_SYS 0x00000016 // Legal but useful in system code only #define D_PRIVILEGED 0x00000017 // Privileged (non-Ring3) command #define D_AVX 0x00000018 // AVX instruction #define D_XOP 0x00000019 // AMD instruction with XOP prefix #define D_DATA 0x0000001C // Data recognized by Analyser #define D_PSEUDO 0x0000001D // Pseudocommand, for search models only #define D_PREFIX 0x0000001E // Standalone prefix #define D_BAD 0x0000001F // Bad or unrecognized command // Additional parts of the command. #define D_SIZE01 0x00000020 // Bit 0x01 in last cmd is data size #define D_POSTBYTE 0x00000040 // Command continues in postbyte // For string commands, either long or short form can be selected. #define D_LONGFORM 0x00000080 // Long form of string command // Decoding of some commands depends on data or address size. #define D_SIZEMASK 0x00000F00 // Mask for data/address size dependence #define D_DATA16 0x00000100 // Requires 16-bit data size #define D_DATA32 0x00000200 // Requires 32-bit data size #define D_ADDR16 0x00000400 // Requires 16-bit address size #define D_ADDR32 0x00000800 // Requires 32-bit address size // Prefixes that command may, must or must not possess. #define D_MUSTMASK 0x0000F000 // Mask for fixed set of prefixes #define D_NOMUST 0x00000000 // No obligatory prefixes (default) #define D_MUST66 0x00001000 // (SSE,AVX) Requires 66, no F2 or F3 #define D_MUSTF2 0x00002000 // (SSE,AVX) Requires F2, no 66 or F3 #define D_MUSTF3 0x00003000 // (SSE,AVX) Requires F3, no 66 or F2 #define D_MUSTNONE 0x00004000 // (MMX,SSE,AVX) Requires no 66, F2, F3 #define D_NEEDF2 0x00005000 // (SSE,AVX) Requires F2, no F3 #define D_NEEDF3 0x00006000 // (SSE,AVX) Requires F3, no F2 #define D_NOREP 0x00007000 // Must not include F2 or F3 #define D_MUSTREP 0x00008000 // Must include F3 (REP) #define D_MUSTREPE 0x00009000 // Must include F3 (REPE) #define D_MUSTREPNE 0x0000A000 // Must include F2 (REPNE) #define D_LOCKABLE 0x00010000 // Allows for F0 (LOCK, memory only) #define D_BHINT 0x00020000 // Allows for branch hints (2E, 3E) // Decoding of some commands with ModRM-SIB depends whether register or memory. #define D_MEMORY 0x00040000 // Mod field must indicate memory #define D_REGISTER 0x00080000 // Mod field must indicate register // Side effects caused by command. #define D_FLAGMASK 0x00700000 // Mask to extract modified flags #define D_NOFLAGS 0x00000000 // Flags S,Z,P,O,C remain unchanged #define D_ALLFLAGS 0x00100000 // Modifies flags S,Z,P,O,C #define D_FLAGZ 0x00200000 // Modifies flag Z only #define D_FLAGC 0x00300000 // Modifies flag C only #define D_FLAGSCO 0x00400000 // Modifies flag C and O only #define D_FLAGD 0x00500000 // Modifies flag D only #define D_FLAGSZPC 0x00600000 // Modifies flags Z, P and C only (FPU) #define D_NOCFLAG 0x00700000 // S,Z,P,O modified, C unaffected #define D_FPUMASK 0x01800000 // Mask for effects on FPU stack #define D_FPUSAME 0x00000000 // Doesn't rotate FPU stack (default) #define D_FPUPOP 0x00800000 // Pops FPU stack #define D_FPUPOP2 0x01000000 // Pops FPU stack twice #define D_FPUPUSH 0x01800000 // Pushes FPU stack #define D_CHGESP 0x02000000 // Command indirectly modifies ESP // Command features. #define D_HLADIR 0x04000000 // Nonstandard order of operands in HLA #define D_WILDCARD 0x08000000 // Mnemonics contains W/D wildcard ('*') #define D_COND 0x10000000 // Conditional (action depends on flags) #define D_USESCARRY 0x20000000 // Uses Carry flag #define D_USEMASK 0xC0000000 // Mask to detect unusual commands #define D_RARE 0x40000000 // Rare or obsolete in Win32 apps #define D_SUSPICIOUS 0x80000000 // Suspicious command #define D_UNDOC 0xC0000000 // Undocumented command // Extension of D_xxx. #define DX_ZEROMASK 0x00000003 // How to decode FLAGS.Z flag #define DX_JE 0x00000001 // JE, JNE instead of JZ, JNZ #define DX_JZ 0x00000002 // JZ, JNZ instead of JE, JNE #define DX_CARRYMASK 0x0000000C // How to decode FLAGS.C flag #define DX_JB 0x00000004 // JAE, JB instead of JC, JNC #define DX_JC 0x00000008 // JC, JNC instead of JAE, JB #define DX_RETN 0x00000010 // The mnemonics is RETN #define DX_VEX 0x00000100 // Requires VEX prefix #define DX_VLMASK 0x00000600 // Mask to extract VEX operand length #define DX_LSHORT 0x00000000 // 128-bit only #define DX_LBOTH 0x00000200 // Both 128- and 256-bit versions #define DX_LLONG 0x00000400 // 256-bit only #define DX_IGNOREL 0x00000600 // Ignore VEX.L #define DX_NOVREG 0x00000800 // VEX.vvvv must be set to all 1's #define DX_VWMASK 0x00003000 // Mask to extract VEX.W #define DX_W0 0x00001000 // VEX.W must be 0 #define DX_W1 0x00002000 // VEX.W must be 1 #define DX_LEADMASK 0x00070000 // Mask to extract leading opcode bytes #define DX_LEAD0F 0x00000000 // Implied 0F leading byte (default) #define DX_LEAD38 0x00010000 // Implied 0F 38 leading opcode bytes #define DX_LEAD3A 0x00020000 // Implied 0F 3A leading opcode bytes #define DX_WONKYTRAP 0x00800000 // Don't single-step this command #define DX_TYPEMASK 0xFF000000 // Precised command type mask #define DX_ADD 0x01000000 // The command is integer ADD #define DX_SUB 0x02000000 // The command is integer SUB #define DX_LEA 0x03000000 // The command is LEA #define DX_NOP 0x04000000 // The command is NOP //#define DX_LVEX (DX_VEX|DX_LBOTH) //#define DX_GVEX (DX_VEX|DX_LLONG) // Type of operand, only one is allowed. Size of SSE operands is given for the // case of 128-bit operations and usually doubles for 256-bit AVX commands. If // B_NOVEXSIZE is set, memory may double but XMM registers are not promoted to // YMM. #define B_ARGMASK 0x000000FF // Mask to extract type of argument #define B_NONE 0x00000000 // Operand absent #define B_AL 0x00000001 // Register AL #define B_AH 0x00000002 // Register AH #define B_AX 0x00000003 // Register AX #define B_CL 0x00000004 // Register CL #define B_CX 0x00000005 // Register CX #define B_DX 0x00000006 // Register DX #define B_DXPORT 0x00000007 // Register DX as I/O port address #define B_EAX 0x00000008 // Register EAX #define B_EBX 0x00000009 // Register EBX #define B_ECX 0x0000000A // Register ECX #define B_EDX 0x0000000B // Register EDX #define B_ACC 0x0000000C // Accumulator (AL/AX/EAX) #define B_STRCNT 0x0000000D // Register CX or ECX as REPxx counter #define B_DXEDX 0x0000000E // Register DX or EDX in DIV/MUL #define B_BPEBP 0x0000000F // Register BP or EBP in ENTER/LEAVE #define B_REG 0x00000010 // 8/16/32-bit register in Reg #define B_REG16 0x00000011 // 16-bit register in Reg #define B_REG32 0x00000012 // 32-bit register in Reg #define B_REGCMD 0x00000013 // 16/32-bit register in last cmd byte #define B_REGCMD8 0x00000014 // 8-bit register in last cmd byte #define B_ANYREG 0x00000015 // Reg field is unused, any allowed #define B_INT 0x00000016 // 8/16/32-bit register/memory in ModRM #define B_INT8 0x00000017 // 8-bit register/memory in ModRM #define B_INT16 0x00000018 // 16-bit register/memory in ModRM #define B_INT32 0x00000019 // 32-bit register/memory in ModRM #define B_INT1632 0x0000001A // 16/32-bit register/memory in ModRM #define B_INT64 0x0000001B // 64-bit integer in ModRM, memory only #define B_INT128 0x0000001C // 128-bit integer in ModRM, memory only #define B_IMMINT 0x0000001D // 8/16/32-bit int at immediate addr #define B_INTPAIR 0x0000001E // Two signed 16/32 in ModRM, memory only #define B_SEGOFFS 0x0000001F // 16:16/16:32 absolute address in memory #define B_STRDEST 0x00000020 // 8/16/32-bit string dest, [ES:(E)DI] #define B_STRDEST8 0x00000021 // 8-bit string destination, [ES:(E)DI] #define B_STRSRC 0x00000022 // 8/16/32-bit string source, [(E)SI] #define B_STRSRC8 0x00000023 // 8-bit string source, [(E)SI] #define B_XLATMEM 0x00000024 // 8-bit memory in XLAT, [(E)BX+AL] #define B_EAXMEM 0x00000025 // Reference to memory addressed by [EAX] #define B_LONGDATA 0x00000026 // Long data in ModRM, mem only #define B_ANYMEM 0x00000027 // Reference to memory, data unimportant #define B_STKTOP 0x00000028 // 16/32-bit int top of stack #define B_STKTOPFAR 0x00000029 // Top of stack (16:16/16:32 far addr) #define B_STKTOPEFL 0x0000002A // 16/32-bit flags on top of stack #define B_STKTOPA 0x0000002B // 16/32-bit top of stack all registers #define B_PUSH 0x0000002C // 16/32-bit int push to stack #define B_PUSHRET 0x0000002D // 16/32-bit push of return address #define B_PUSHRETF 0x0000002E // 16:16/16:32-bit push of far retaddr #define B_PUSHA 0x0000002F // 16/32-bit push all registers #define B_EBPMEM 0x00000030 // 16/32-bit int at [EBP] #define B_SEG 0x00000031 // Segment register in Reg #define B_SEGNOCS 0x00000032 // Segment register in Reg, but not CS #define B_SEGCS 0x00000033 // Segment register CS #define B_SEGDS 0x00000034 // Segment register DS #define B_SEGES 0x00000035 // Segment register ES #define B_SEGFS 0x00000036 // Segment register FS #define B_SEGGS 0x00000037 // Segment register GS #define B_SEGSS 0x00000038 // Segment register SS #define B_ST 0x00000039 // 80-bit FPU register in last cmd byte #define B_ST0 0x0000003A // 80-bit FPU register ST0 #define B_ST1 0x0000003B // 80-bit FPU register ST1 #define B_FLOAT32 0x0000003C // 32-bit float in ModRM, memory only #define B_FLOAT64 0x0000003D // 64-bit float in ModRM, memory only #define B_FLOAT80 0x0000003E // 80-bit float in ModRM, memory only #define B_BCD 0x0000003F // 80-bit BCD in ModRM, memory only #define B_MREG8x8 0x00000040 // MMX register as 8 8-bit integers #define B_MMX8x8 0x00000041 // MMX reg/memory as 8 8-bit integers #define B_MMX8x8DI 0x00000042 // MMX 8 8-bit integers at [DS:(E)DI] #define B_MREG16x4 0x00000043 // MMX register as 4 16-bit integers #define B_MMX16x4 0x00000044 // MMX reg/memory as 4 16-bit integers #define B_MREG32x2 0x00000045 // MMX register as 2 32-bit integers #define B_MMX32x2 0x00000046 // MMX reg/memory as 2 32-bit integers #define B_MREG64 0x00000047 // MMX register as 1 64-bit integer #define B_MMX64 0x00000048 // MMX reg/memory as 1 64-bit integer #define B_3DREG 0x00000049 // 3DNow! register as 2 32-bit floats #define B_3DNOW 0x0000004A // 3DNow! reg/memory as 2 32-bit floats #define B_XMM0I32x4 0x0000004B // XMM0 as 4 32-bit integers #define B_XMM0I64x2 0x0000004C // XMM0 as 2 64-bit integers #define B_XMM0I8x16 0x0000004D // XMM0 as 16 8-bit integers #define B_SREGF32x4 0x0000004E // SSE register as 4 32-bit floats #define B_SREGF32L 0x0000004F // Low 32-bit float in SSE register #define B_SREGF32x2L 0x00000050 // Low 2 32-bit floats in SSE register #define B_SSEF32x4 0x00000051 // SSE reg/memory as 4 32-bit floats #define B_SSEF32L 0x00000052 // Low 32-bit float in SSE reg/memory #define B_SSEF32x2L 0x00000053 // Low 2 32-bit floats in SSE reg/memory #define B_SREGF64x2 0x00000054 // SSE register as 2 64-bit floats #define B_SREGF64L 0x00000055 // Low 64-bit float in SSE register #define B_SSEF64x2 0x00000056 // SSE reg/memory as 2 64-bit floats #define B_SSEF64L 0x00000057 // Low 64-bit float in SSE reg/memory #define B_SREGI8x16 0x00000058 // SSE register as 16 8-bit sigints #define B_SSEI8x16 0x00000059 // SSE reg/memory as 16 8-bit sigints #define B_SSEI8x16DI 0x0000005A // SSE 16 8-bit sigints at [DS:(E)DI] #define B_SSEI8x8L 0x0000005B // Low 8 8-bit ints in SSE reg/memory #define B_SSEI8x4L 0x0000005C // Low 4 8-bit ints in SSE reg/memory #define B_SSEI8x2L 0x0000005D // Low 2 8-bit ints in SSE reg/memory #define B_SREGI16x8 0x0000005E // SSE register as 8 16-bit sigints #define B_SSEI16x8 0x0000005F // SSE reg/memory as 8 16-bit sigints #define B_SSEI16x4L 0x00000060 // Low 4 16-bit ints in SSE reg/memory #define B_SSEI16x2L 0x00000061 // Low 2 16-bit ints in SSE reg/memory #define B_SREGI32x4 0x00000062 // SSE register as 4 32-bit sigints #define B_SREGI32L 0x00000063 // Low 32-bit sigint in SSE register #define B_SREGI32x2L 0x00000064 // Low 2 32-bit sigints in SSE register #define B_SSEI32x4 0x00000065 // SSE reg/memory as 4 32-bit sigints #define B_SSEI32x2L 0x00000066 // Low 2 32-bit sigints in SSE reg/memory #define B_SREGI64x2 0x00000067 // SSE register as 2 64-bit sigints #define B_SSEI64x2 0x00000068 // SSE reg/memory as 2 64-bit sigints #define B_SREGI64L 0x00000069 // Low 64-bit sigint in SSE register #define B_EFL 0x0000006A // Flags register EFL #define B_FLAGS8 0x0000006B // Flags (low byte) #define B_OFFSET 0x0000006C // 16/32 const offset from next command #define B_BYTEOFFS 0x0000006D // 8-bit sxt const offset from next cmd #define B_FARCONST 0x0000006E // 16:16/16:32 absolute address constant #define B_DESCR 0x0000006F // 16:32 descriptor in ModRM #define B_1 0x00000070 // Immediate constant 1 #define B_CONST8 0x00000071 // Immediate 8-bit constant #define B_CONST8_2 0x00000072 // Immediate 8-bit const, second in cmd #define B_CONST16 0x00000073 // Immediate 16-bit constant #define B_CONST 0x00000074 // Immediate 8/16/32-bit constant #define B_CONSTL 0x00000075 // Immediate 16/32-bit constant #define B_SXTCONST 0x00000076 // Immediate 8-bit sign-extended to size #define B_CR 0x00000077 // Control register in Reg #define B_CR0 0x00000078 // Control register CR0 #define B_DR 0x00000079 // Debug register in Reg #define B_FST 0x0000007A // FPU status register #define B_FCW 0x0000007B // FPU control register #define B_MXCSR 0x0000007C // SSE media control and status register #define B_SVEXF32x4 0x0000007D // SSE reg in VEX as 4 32-bit floats #define B_SVEXF32L 0x0000007E // Low 32-bit float in SSE in VEX #define B_SVEXF64x2 0x0000007F // SSE reg in VEX as 2 64-bit floats #define B_SVEXF64L 0x00000080 // Low 64-bit float in SSE in VEX #define B_SVEXI8x16 0x00000081 // SSE reg in VEX as 16 8-bit sigints #define B_SVEXI16x8 0x00000082 // SSE reg in VEX as 8 16-bit sigints #define B_SVEXI32x4 0x00000083 // SSE reg in VEX as 4 32-bit sigints #define B_SVEXI64x2 0x00000084 // SSE reg in VEX as 2 64-bit sigints #define B_SIMMI8x16 0x00000085 // SSE reg in immediate 8-bit constant // Type modifiers, used for interpretation of contents, only one is allowed. #define B_MODMASK 0x000F0000 // Mask to extract type modifier #define B_NONSPEC 0x00000000 // Non-specific operand #define B_UNSIGNED 0x00010000 // Decode as unsigned decimal #define B_SIGNED 0x00020000 // Decode as signed decimal #define B_BINARY 0x00030000 // Decode as binary (full hex) data #define B_BITCNT 0x00040000 // Bit count #define B_SHIFTCNT 0x00050000 // Shift count #define B_COUNT 0x00060000 // General-purpose count #define B_NOADDR 0x00070000 // Not an address #define B_JMPCALL 0x00080000 // Near jump/call/return destination #define B_JMPCALLFAR 0x00090000 // Far jump/call/return destination #define B_STACKINC 0x000A0000 // Unsigned stack increment/decrement #define B_PORT 0x000B0000 // I/O port #define B_ADDR 0x000F0000 // Used internally // Validity markers. #define B_MEMORY 0x00100000 // Memory only, reg version different #define B_REGISTER 0x00200000 // Register only, mem version different #define B_MEMONLY 0x00400000 // Warn if operand in register #define B_REGONLY 0x00800000 // Warn if operand in memory #define B_32BITONLY 0x01000000 // Warn if 16-bit operand #define B_NOESP 0x02000000 // ESP is not allowed // Miscellaneous options. #define B_NOVEXSIZE 0x04000000 // Always 128-bit SSE in 256-bit AVX #define B_SHOWSIZE 0x08000000 // Always show argument size in disasm #define B_CHG 0x10000000 // Changed, old contents is not used #define B_UPD 0x20000000 // Modified using old contents #define B_PSEUDO 0x40000000 // Pseoudooperand, not in assembler cmd #define B_NOSEG 0x80000000 // Don't add offset of selector // Location of operand, only one bit is allowed. #define OP_SOMEREG 0x000000FF // Mask for any kind of register #define OP_REGISTER 0x00000001 // Operand is a general-purpose register #define OP_SEGREG 0x00000002 // Operand is a segment register #define OP_FPUREG 0x00000004 // Operand is a FPU register #define OP_MMXREG 0x00000008 // Operand is a MMX register #define OP_3DNOWREG 0x00000010 // Operand is a 3DNow! register #define OP_SSEREG 0x00000020 // Operand is a SSE register #define OP_CREG 0x00000040 // Operand is a control register #define OP_DREG 0x00000080 // Operand is a debug register #define OP_MEMORY 0x00000100 // Operand is in memory #define OP_CONST 0x00000200 // Operand is an immediate constant // Additional operand properties. #define OP_PORT 0x00000400 // Used to access I/O port #define OP_OTHERREG 0x00000800 // Special register like EFL or MXCSR #define OP_INVALID 0x00001000 // Invalid operand, like reg in mem-only #define OP_PSEUDO 0x00002000 // Pseudooperand (not in mnenonics) #define OP_MOD 0x00004000 // Command may change/update operand #define OP_MODREG 0x00008000 // Memory, but modifies reg (POP,MOVSD) #define OP_IMPORT 0x00020000 // Value imported from different module #define OP_SELECTOR 0x00040000 // Includes immediate selector // Additional properties of memory address. #define OP_INDEXED 0x00080000 // Memory address contains registers #define OP_OPCONST 0x00100000 // Memory address contains constant #define OP_ADDR16 0x00200000 // 16-bit memory address #define OP_ADDR32 0x00400000 // Explicit 32-bit memory address #define DAMODE_MASM 0 // MASM assembling/disassembling style #define DAMODE_IDEAL 1 // IDEAL assembling/disassembling style #define DAMODE_HLA 2 // HLA assembling/disassembling style #define DAMODE_ATT 3 // AT&T disassembling style #define NUM_STYLE 0x0003 // Mask to extract hex style #define NUM_STD 0x0000 // 123, 12345678h, 0ABCD1234h #define NUM_X 0x0001 // 123, 0x12345678, 0xABCD1234 #define NUM_OLLY 0x0002 // 123., 12345678, 0ABCD1234 #define NUM_LONG 0x0010 // 00001234h instead of 1234h #define NUM_DECIMAL 0x0020 // 123 instead of 7Bh if under DECLIMIT // Disassembling options. #define DA_TEXT 0x00000001 // Decode command to text and comment #define DA_HILITE 0x00000002 // Use syntax highlighting #define DA_JZ 0x00000004 // JZ, JNZ instead of JE, JNE #define DA_JC 0x00000008 // JC, JNC instead of JAE, JB #define DA_DUMP 0x00000020 // Dump command to hexadecimal text #define DA_PSEUDO 0x00000400 // List pseudooperands // Disassembling errors. #define DAE_NOERR 0x00000000 // No errors #define DAE_BADCMD 0x00000001 // Unrecognized command #define DAE_CROSS 0x00000002 // Command crosses end of memory block #define DAE_MEMORY 0x00000004 // Register where only memory allowed #define DAE_REGISTER 0x00000008 // Memory where only register allowed #define DAE_LOCK 0x00000010 // LOCK prefix is not allowed #define DAE_BADSEG 0x00000020 // Invalid segment register #define DAE_SAMEPREF 0x00000040 // Two prefixes from the same group #define DAE_MANYPREF 0x00000080 // More than 4 prefixes #define DAE_BADCR 0x00000100 // Invalid CR register #define DAE_INTERN 0x00000200 // Internal error // Disassembling warnings. #define DAW_NOWARN 0x00000000 // No warnings #define DAW_DATASIZE 0x00000001 // Superfluous data size prefix #define DAW_ADDRSIZE 0x00000002 // Superfluous address size prefix #define DAW_SEGPREFIX 0x00000004 // Superfluous segment override prefix #define DAW_REPPREFIX 0x00000008 // Superfluous REPxx prefix #define DAW_DEFSEG 0x00000010 // Segment prefix coincides with default #define DAW_JMP16 0x00000020 // 16-bit jump, call or return #define DAW_FARADDR 0x00000040 // Far jump or call #define DAW_SEGMOD 0x00000080 // Modifies segment register #define DAW_PRIV 0x00000100 // Privileged command #define DAW_IO 0x00000200 // I/O command #define DAW_SHIFT 0x00000400 // Shift out of range 1..31 #define DAW_LOCK 0x00000800 // Command with valid LOCK prefix #define DAW_STACK 0x00001000 // Unaligned stack operation #define DAW_NOESP 0x00002000 // Suspicious use of stack pointer #define DAW_RARE 0x00004000 // Rare, seldom used command #define DAW_NONCLASS 0x00008000 // Non-standard or non-documented code #define DAW_INTERRUPT 0x00010000 // Interrupt command // List of prefixes. #define PF_SEGMASK 0x0000003F // Mask for segment override prefixes #define PF_ES 0x00000001 // 0x26, ES segment override #define PF_CS 0x00000002 // 0x2E, CS segment override #define PF_SS 0x00000004 // 0x36, SS segment override #define PF_DS 0x00000008 // 0x3E, DS segment override #define PF_FS 0x00000010 // 0x64, FS segment override #define PF_GS 0x00000020 // 0x65, GS segment override #define PF_DSIZE 0x00000040 // 0x66, data size override #define PF_ASIZE 0x00000080 // 0x67, address size override #define PF_LOCK 0x00000100 // 0xF0, bus lock #define PF_REPMASK 0x00000600 // Mask for repeat prefixes #define PF_REPNE 0x00000200 // 0xF2, REPNE prefix #define PF_REP 0x00000400 // 0xF3, REP/REPE prefix #define PF_BYTE 0x00000800 // Size bit in command, used in cmdexec #define PF_MUSTMASK D_MUSTMASK // Necessary prefixes, used in t_asmmod #define PF_VEX2 0x00010000 // 2-byte VEX prefix #define PF_VEX3 0x00020000 // 3-byte VEX prefix // Useful shortcuts. #define PF_66 PF_DSIZE // Alternative names for SSE prefixes #define PF_F2 PF_REPNE #define PF_F3 PF_REP #define PF_HINT (PF_CS|PF_DS) // Alternative names for branch hints #define PF_NOTTAKEN PF_CS #define PF_TAKEN PF_DS #define PF_VEX (PF_VEX2|PF_VEX3) typedef struct t_modrm { // ModRM byte decoding ulong size; // Total size with SIB and disp, bytes struct t_modrm *psib; // Pointer to SIB table or NULL ulong dispsize; // Size of displacement or 0 if none ulong features; // Operand features, set of OP_xxx int reg; // Register index or REG_UNDEF int defseg; // Default selector (SEG_xxx) uchar scale[NREG]; // Scales of registers in memory address ulong aregs; // List of registers used in address int basereg; // Register used as base or REG_UNDEF tchar ardec[SHORTNAME]; // Register part of address, INTEL fmt tchar aratt[SHORTNAME]; // Register part of address, AT&T fmt } t_modrm; typedef struct t_bincmd { // Description of 80x86 command tchar *name; // Symbolic name for this command ulong cmdtype; // Command's features, set of D_xxx ulong exttype; // More features, set of DX_xxx ulong length; // Length of main code (before ModRM/SIB) ulong mask; // Mask for first 4 bytes of the command ulong code; // Compare masked bytes with this ulong postbyte; // Postbyte ulong arg[NOPERAND]; // Types of arguments, set of B_xxx } t_bincmd; typedef struct t_chain { // Element of command chain const t_bincmd *pcmd; // Pointer to command descriptor or NULL struct t_chain *pnext; // Pointer to next element in chain } t_chain; typedef struct t_config { // Disassembler configuration int disasmmode; // Main style, one of DAMODE_xxx int memmode; // Constant part of address, NUM_xxx int jmpmode; // Jump/call destination, NUM_xxx int binconstmode; // Binary constants, NUM_xxx int constmode; // Numeric constants, NUM_xxx int lowercase; // Force lowercase display int tabarguments; // Tab between mnemonic and arguments int extraspace; // Extra space between arguments int useretform; // Use RET instead of RETN int shortstringcmds; // Use short form of string commands int putdefseg; // Display default segments in listing int showmemsize; // Always show memory size int shownear; // Show NEAR modifiers int ssesizemode; // How to decode size of SSE operands int jumphintmode; // How to decode jump hints int sizesens; // How to decode size-sensitive mnemonics int simplifiedst; // How to decode top of FPU stack int hiliteoperands; // Highlight operands } t_config; typedef struct t_operand { // Description of disassembled operand // Description of operand. ulong features; // Operand features, set of OP_xxx ulong arg; // Operand type, set of B_xxx // int optype; // DEC_INT, DEC_FLOAT or DEC_UNKNOWN int opsize; // Total size of data, bytes int granularity; // Size of element (opsize exc. MMX/SSE) int reg; // REG_xxx (also ESP in POP) or REG_UNDEF ulong uses; // List of used regs (not in address!) ulong modifies; // List of modified regs (not in addr!) // Description of memory address. int seg; // Selector (SEG_xxx) uchar scale[NREG]; // Scales of registers in memory address ulong aregs; // List of registers used in address ulong opconst; // Constant or const part of address ulong selector; // Immediate selector in far jump/call // Textual decoding. tchar text[TEXTLEN]; // Operand, decoded to text } t_operand; // Note that used registers are those which contents is necessary to create // result. Modified registers are those which value is changed. For example, // command MOV EAX,[EBX+ECX] uses EBX and ECX and modifies EAX. Command // ADD ESI,EDI uses ESI and EDI and modifies ESI. typedef struct t_disasm { // Disassembled command ulong ip; // Address of first command byte ulong size; // Full length of command, bytes ulong cmdtype; // Type of command, D_xxx ulong exttype; // More features, set of DX_xxx ulong prefixes; // List of prefixes, set of PF_xxx ulong nprefix; // Number of prefixes, including SSE2 ulong memfixup; // Offset of first 4-byte fixup or -1 ulong immfixup; // Offset of second 4-byte fixup or -1 int errors; // Set of DAE_xxx int warnings; // Set of DAW_xxx ulong uses; // List of used registers ulong modifies; // List of modified registers ulong memconst; // Constant in memory address or 0 ulong stackinc; // Data size in ENTER/RETN/RETF t_operand op[NOPERAND]; // Operands tchar dump[TEXTLEN]; // Hex dump of the command tchar result[TEXTLEN]; // Fully decoded command as text uchar mask[TEXTLEN]; // Mask to highlight result int masksize; // Length of mask corresponding to result } t_disasm; extern t_modrm modrm16[256]; // 16-bit ModRM decodings extern t_modrm modrm32[256]; // 32-bit ModRM decodings without SIB extern t_modrm sib0[256]; // ModRM-SIB decodings with Mod=00 extern t_modrm sib1[256]; // ModRM-SIB decodings with Mod=01 extern t_modrm sib2[256]; // ModRM-SIB decodings with Mod=10 extern const t_bincmd bincmd[]; // List of 80x86 commands extern t_chain *cmdchain; // Commands sorted by first CMDMASK bits int Preparedisasm(void); void Finishdisasm(void); ulong Disasm(uchar const *cmd,ulong cmdsize,ulong cmdip, t_disasm *da,int cmdmode,t_config *cmdconfig, int (*decodeaddress)(tchar *s,ulong addr)); tchar *Geterrwarnmessage(ulong errors,ulong warnings);