├── kextstat_aslr ├── prefix.c ├── decoder.h ├── operands.h ├── wstring.c ├── wstring.h ├── textdefs.h ├── insts.h ├── x86defs.h ├── prefix.h ├── config.h ├── textdefs.c ├── distorm.c ├── instructions.h ├── distorm.h ├── main.c ├── mnemonics.h ├── mnemonics.c ├── instructions.c └── decoder.c ├── README └── kextstat_aslr.xcodeproj └── project.pbxproj /kextstat_aslr/prefix.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdbinit/kextstat_aslr/HEAD/kextstat_aslr/prefix.c -------------------------------------------------------------------------------- /kextstat_aslr/decoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | decoder.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2011 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef DECODER_H 25 | #define DECODER_H 26 | 27 | #include "config.h" 28 | 29 | typedef unsigned int _iflags; 30 | 31 | _DecodeResult decode_internal(_CodeInfo* ci, int supportOldIntr, _DInst result[], unsigned int maxResultCount, unsigned int* usedInstructionsCount); 32 | 33 | #endif /* DECODER_H */ 34 | -------------------------------------------------------------------------------- /kextstat_aslr/operands.h: -------------------------------------------------------------------------------- 1 | /* 2 | operands.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef OPERANDS_H 25 | #define OPERANDS_H 26 | 27 | #include "config.h" 28 | #include "decoder.h" 29 | #include "prefix.h" 30 | #include "instructions.h" 31 | 32 | 33 | extern uint16_t _REGISTERTORCLASS[]; 34 | 35 | int operands_extract(_CodeInfo* ci, _DInst* di, _InstInfo* ii, 36 | _iflags instFlags, _OpType type, _OperandNumberType opNum, 37 | unsigned int modrm, _PrefixState* ps, _DecodeType effOpSz, 38 | _DecodeType effAdrSz, int* lockableInstruction); 39 | 40 | #endif /* OPERANDS_H */ 41 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | _____ _____ 2 | __| __ |__ ______ __ __ __ __|_ |__ ______ ____ _____ 3 | | |/ / || ___| \ ` / _| |_ | \ || ___|| | | | 4 | | \ || ___| / \|_ _|| \ | `-.`-. | |_ | \ 5 | |__|\__\ __||______|/__/\_\ |__| |__|\__\ __||______||______||__|\__\ 6 | |_____| |_____| 7 | 8 | Kextstat ASLR 9 | 10 | A small util to list OS X kernel extensions with true addresses. 11 | System kextstat util doesn't return info with kernel ASLR slide. 12 | 13 | (c) fG!, 2012, 2013, 2014 - reverser@put.as - http://reverse.put.as 14 | 15 | Uses processor_set_tasks() vulnerability or /dev/kmem to 16 | read kernel memory. 17 | 18 | If processor_set_tasks() vuln not available you need to enable /dev/kmem. 19 | Edit /Library/Preferences/SystemConfiguration/com.apple.Boot.plist 20 | add kmem=1 parameter, and reboot! 21 | 22 | This version can work with all Mountain Lion/Mavericks versions out of the box. 23 | It should work with any future OS X versions if OSArray class doesn't change. 24 | 25 | The license is GPLv3 due to diStorm licensing terms. 26 | 27 | Enjoy, 28 | fG! 29 | 30 | 31 | Change log: 32 | 33 | v0.1 - Initial version 34 | v0.2 - Retrieve kaslr slide via kas_info() syscall. Thanks to posixninja for the tip :-) 35 | v0.3 - Cleanups 36 | v1.0 - Use diStorm to find sLoadedKexts so everything is dynamic 37 | The only dependency is on OSArray class, since we are using fixed offsets 38 | v1.1 - Try to use processor_set_tasks() vulnerability to read kernel memory 39 | before trying to use /dev/kmem 40 | -------------------------------------------------------------------------------- /kextstat_aslr/wstring.c: -------------------------------------------------------------------------------- 1 | /* 2 | wstring.c 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #include "wstring.h" 25 | 26 | #ifndef DISTORM_LIGHT 27 | 28 | void strclear_WS(_WString* s) 29 | { 30 | s->p[0] = '\0'; 31 | s->length = 0; 32 | } 33 | 34 | void chrcat_WS(_WString* s, uint8_t ch) 35 | { 36 | s->p[s->length] = ch; 37 | s->p[s->length + 1] = '\0'; 38 | s->length += 1; 39 | } 40 | 41 | void strcpylen_WS(_WString* s, const int8_t* buf, unsigned int len) 42 | { 43 | s->length = len; 44 | memcpy((int8_t*)s->p, buf, len + 1); 45 | } 46 | 47 | void strcatlen_WS(_WString* s, const int8_t* buf, unsigned int len) 48 | { 49 | memcpy((int8_t*)&s->p[s->length], buf, len + 1); 50 | s->length += len; 51 | } 52 | 53 | void strcat_WS(_WString* s, const _WString* s2) 54 | { 55 | memcpy((int8_t*)&s->p[s->length], s2->p, s2->length + 1); 56 | s->length += s2->length; 57 | } 58 | 59 | #endif /* DISTORM_LIGHT */ 60 | -------------------------------------------------------------------------------- /kextstat_aslr/wstring.h: -------------------------------------------------------------------------------- 1 | /* 2 | wstring.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef WSTRING_H 25 | #define WSTRING_H 26 | 27 | #include "config.h" 28 | 29 | #ifndef DISTORM_LIGHT 30 | 31 | void strclear_WS(_WString* s); 32 | void chrcat_WS(_WString* s, uint8_t ch); 33 | void strcpylen_WS(_WString* s, const int8_t* buf, unsigned int len); 34 | void strcatlen_WS(_WString* s, const int8_t* buf, unsigned int len); 35 | void strcat_WS(_WString* s, const _WString* s2); 36 | 37 | /* 38 | * Warning, this macro should be used only when the compiler knows the size of string in advance! 39 | * This macro is used in order to spare the call to strlen when the strings are known already. 40 | * Note: sizeof includes NULL terminated character. 41 | */ 42 | #define strcat_WSN(s, t) strcatlen_WS((s), ((const int8_t*)t), sizeof((t))-1) 43 | #define strcpy_WSN(s, t) strcpylen_WS((s), ((const int8_t*)t), sizeof((t))-1) 44 | 45 | #endif /* DISTORM_LIGHT */ 46 | 47 | #endif /* WSTRING_H */ 48 | -------------------------------------------------------------------------------- /kextstat_aslr/textdefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | textdefs.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef TEXTDEFS_H 25 | #define TEXTDEFS_H 26 | 27 | #include "config.h" 28 | #include "wstring.h" 29 | 30 | #ifndef DISTORM_LIGHT 31 | 32 | #define PLUS_DISP_CHR '+' 33 | #define MINUS_DISP_CHR '-' 34 | #define OPEN_CHR '[' 35 | #define CLOSE_CHR ']' 36 | #define SP_CHR ' ' 37 | #define SEG_OFF_CHR ':' 38 | 39 | /* 40 | Naming Convention: 41 | 42 | * get - returns a pointer to a string. 43 | * str - concatenates to string. 44 | 45 | * hex - means the function is used for hex dump (number is padded to required size) - Little Endian output. 46 | * code - means the function is used for disassembled instruction - Big Endian output. 47 | * off - means the function is used for 64bit offset - Big Endian output. 48 | 49 | * h - '0x' in front of the string. 50 | 51 | * b - byte 52 | * dw - double word (can be used for word also) 53 | * qw - quad word 54 | 55 | * all numbers are in HEX. 56 | */ 57 | 58 | extern int8_t TextBTable[256][4]; 59 | 60 | void _FASTCALL_ str_hex_b(_WString* s, unsigned int x); 61 | void _FASTCALL_ str_code_hb(_WString* s, unsigned int x); 62 | void _FASTCALL_ str_code_hdw(_WString* s, uint32_t x); 63 | void _FASTCALL_ str_code_hqw(_WString* s, uint8_t src[8]); 64 | 65 | #ifdef SUPPORT_64BIT_OFFSET 66 | void _FASTCALL_ str_off64(_WString* s, OFFSET_INTEGER x); 67 | #endif 68 | 69 | #endif /* DISTORM_LIGHT */ 70 | 71 | #endif /* TEXTDEFS_H */ 72 | -------------------------------------------------------------------------------- /kextstat_aslr/insts.h: -------------------------------------------------------------------------------- 1 | /* 2 | insts.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef INSTS_H 25 | #define INSTS_H 26 | 27 | #include "instructions.h" 28 | 29 | 30 | /* Flags Table */ 31 | extern _iflags FlagsTable[]; 32 | 33 | /* Root Trie DB */ 34 | extern _InstSharedInfo InstSharedInfoTable[]; 35 | extern _InstInfo InstInfos[]; 36 | extern _InstInfoEx InstInfosEx[]; 37 | extern _InstNode InstructionsTree[]; 38 | 39 | /* 3DNow! Trie DB */ 40 | extern _InstNode Table_0F_0F; 41 | /* AVX related: */ 42 | extern _InstNode Table_0F, Table_0F_38, Table_0F_3A; 43 | 44 | /* 45 | * The inst_lookup will return on of these two instructions according to the specified decoding mode. 46 | * ARPL or MOVSXD on 64 bits is one byte instruction at index 0x63. 47 | */ 48 | extern _InstInfo II_ARPL; 49 | extern _InstInfo II_MOVSXD; 50 | 51 | /* 52 | * The NOP instruction can be prefixed by REX in 64bits, therefore we have to decide in runtime whether it's an XCHG or NOP instruction. 53 | * If 0x90 is prefixed by a useable REX it will become XCHG, otherwise it will become a NOP. 54 | * Also note that if it's prefixed by 0xf3, it becomes a Pause. 55 | */ 56 | extern _InstInfo II_NOP; 57 | extern _InstInfo II_PAUSE; 58 | 59 | /* 60 | * Used for letting the extract operand know the type of operands without knowing the 61 | * instruction itself yet, because of the way those instructions work. 62 | * See function instructions.c!inst_lookup_3dnow. 63 | */ 64 | extern _InstInfo II_3DNOW; 65 | 66 | /* Helper tables for pesudo compare mnemonics. */ 67 | extern uint16_t CmpMnemonicOffsets[8]; /* SSE */ 68 | extern uint16_t VCmpMnemonicOffsets[32]; /* AVX */ 69 | 70 | #endif /* INSTS_H */ 71 | -------------------------------------------------------------------------------- /kextstat_aslr/x86defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | x86defs.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef X86DEFS_H 25 | #define X86DEFS_H 26 | 27 | 28 | #define SEG_REGS_MAX (6) 29 | #define CREGS_MAX (9) 30 | #define DREGS_MAX (8) 31 | 32 | /* Maximum instruction size, including prefixes */ 33 | #define INST_MAXIMUM_SIZE (15) 34 | 35 | /* Maximum range of imm8 (comparison type) of special SSE CMP instructions. */ 36 | #define INST_CMP_MAX_RANGE (8) 37 | 38 | /* Maximum range of imm8 (comparison type) of special AVX VCMP instructions. */ 39 | #define INST_VCMP_MAX_RANGE (32) 40 | 41 | /* Wait instruction byte code. */ 42 | #define INST_WAIT_INDEX (0x9b) 43 | 44 | /* Lea instruction byte code. */ 45 | #define INST_LEA_INDEX (0x8d) 46 | 47 | /* NOP/XCHG instruction byte code. */ 48 | #define INST_NOP_INDEX (0x90) 49 | 50 | /* ARPL/MOVSXD instruction byte code. */ 51 | #define INST_ARPL_INDEX (0x63) 52 | 53 | /* 54 | * Minimal MODR/M value of divided instructions. 55 | * It's 0xc0, two MSBs set, which indicates a general purpose register is used too. 56 | */ 57 | #define INST_DIVIDED_MODRM (0xc0) 58 | 59 | /* This is the escape byte value used for 3DNow! instructions. */ 60 | #define _3DNOW_ESCAPE_BYTE (0x0f) 61 | 62 | #define PREFIX_LOCK (0xf0) 63 | #define PREFIX_REPNZ (0xf2) 64 | #define PREFIX_REP (0xf3) 65 | #define PREFIX_CS (0x2e) 66 | #define PREFIX_SS (0x36) 67 | #define PREFIX_DS (0x3e) 68 | #define PREFIX_ES (0x26) 69 | #define PREFIX_FS (0x64) 70 | #define PREFIX_GS (0x65) 71 | #define PREFIX_OP_SIZE (0x66) 72 | #define PREFIX_ADDR_SIZE (0x67) 73 | #define PREFIX_VEX2b (0xc5) 74 | #define PREFIX_VEX3b (0xc4) 75 | 76 | /* REX prefix value range, 64 bits mode decoding only. */ 77 | #define PREFIX_REX_LOW (0x40) 78 | #define PREFIX_REX_HI (0x4f) 79 | /* In order to use the extended GPR's we have to add 8 to the Modr/M info values. */ 80 | #define EX_GPR_BASE (8) 81 | 82 | /* Mask for REX and VEX features: */ 83 | /* Base */ 84 | #define PREFIX_EX_B (1) 85 | /* Index */ 86 | #define PREFIX_EX_X (2) 87 | /* Register */ 88 | #define PREFIX_EX_R (4) 89 | /* Operand Width */ 90 | #define PREFIX_EX_W (8) 91 | /* Vector Lengh */ 92 | #define PREFIX_EX_L (0x10) 93 | 94 | #endif /* X86DEFS_H */ 95 | -------------------------------------------------------------------------------- /kextstat_aslr/prefix.h: -------------------------------------------------------------------------------- 1 | /* 2 | prefix.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef PREFIX_H 25 | #define PREFIX_H 26 | 27 | #include "config.h" 28 | #include "decoder.h" 29 | 30 | 31 | /* Specifies the type of the extension prefix, such as: REX, 2 bytes VEX, 3 bytes VEX. */ 32 | typedef enum {PET_NONE = 0, PET_REX, PET_VEX2BYTES, PET_VEX3BYTES} _PrefixExtType; 33 | 34 | /* Specifies an index into a table of prefixes by their type. */ 35 | typedef enum {PFXIDX_NONE = -1, PFXIDX_REX, PFXIDX_LOREP, PFXIDX_SEG, PFXIDX_OP_SIZE, PFXIDX_ADRS, PFXIDX_MAX} _PrefixIndexer; 36 | 37 | /* 38 | * This holds the prefixes state for the current instruction we decode. 39 | * decodedPrefixes includes all specific prefixes that the instruction got. 40 | * start is a pointer to the first prefix to take into account. 41 | * last is a pointer to the last byte we scanned. 42 | * Other pointers are used to keep track of prefixes positions and help us know if they appeared already and where. 43 | */ 44 | typedef struct { 45 | _iflags decodedPrefixes, usedPrefixes; 46 | const uint8_t *start, *last, *vexPos, *rexPos; 47 | _PrefixExtType prefixExtType; 48 | uint16_t unusedPrefixesMask; 49 | /* Indicates whether the operand size prefix (0x66) was used as a mandatory prefix. */ 50 | int isOpSizeMandatory; 51 | /* If VEX prefix is used, store the VEX.vvvv field. */ 52 | unsigned int vexV; 53 | /* The fields B/X/R/W/L of REX and VEX are stored together in this byte. */ 54 | unsigned int vrex; 55 | 56 | /* !! Make sure pfxIndexer is LAST! Otherwise memset won't work well with it. !! */ 57 | 58 | /* Holds the offset to the prefix byte by its type. */ 59 | int pfxIndexer[PFXIDX_MAX]; 60 | } _PrefixState; 61 | 62 | /* 63 | * Intel supports 6 types of prefixes, whereas AMD supports 5 types (lock is seperated from rep/nz). 64 | * REX is the fifth prefix type, this time I'm based on AMD64. 65 | * VEX is the 6th, though it can't be repeated. 66 | */ 67 | #define MAX_PREFIXES (5) 68 | 69 | int prefixes_is_valid(unsigned int ch, _DecodeType dt); 70 | void prefixes_ignore(_PrefixState* ps, _PrefixIndexer pi); 71 | void prefixes_ignore_all(_PrefixState* ps); 72 | uint16_t prefixes_set_unused_mask(_PrefixState* ps); 73 | void prefixes_decode(const uint8_t* code, int codeLen, _PrefixState* ps, _DecodeType dt); 74 | void prefixes_use_segment(_iflags defaultSeg, _PrefixState* ps, _DecodeType dt, _DInst* di); 75 | 76 | #endif /* PREFIX_H */ 77 | -------------------------------------------------------------------------------- /kextstat_aslr/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | config.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef CONFIG_H 25 | #define CONFIG_H 26 | 27 | /* diStorm version number. */ 28 | #define __DISTORMV__ 0x030300 29 | 30 | #include /* memset, memcpy - can be easily self implemented for libc independency. */ 31 | 32 | #include "distorm.h" 33 | 34 | 35 | /* 36 | * 64 bit offsets support: 37 | * This macro should be defined from compiler command line flags, e.g: -DSUPPORT_64BIT_OFFSET 38 | * Note: make sure that the caller (library user) defines it too! 39 | */ 40 | /* #define SUPPORT_64BIT_OFFSET */ 41 | 42 | /* 43 | * If you compile diStorm as a dynamic library (.dll or .so) file, make sure you uncomment the next line. 44 | * So the interface functions will be exported, otherwise they are useable only for static library. 45 | * For example, this macro is being set for compiling diStorm as a .dll for Python with CTypes. 46 | */ 47 | /* #define DISTORM_DYNAMIC */ 48 | 49 | /* 50 | * If DISTORM_LIGHT is defined, everything involved in formatting the instructions 51 | * as text will be excluded from compilation. 52 | * distorm_decode(..) and distorm_format(..) will not be available. 53 | * This will decrease the size of the executable and leave you with decomposition functionality only. 54 | * 55 | * Note: it should be either set in the preprocessor definitions manually or in command line -D switch. 56 | * #define DISTORM_LIGHT 57 | */ 58 | 59 | /* 60 | * diStorm now supports little/big endian CPU's. 61 | * It should detect the endianness according to predefined macro's of the compiler. 62 | * If you don't use GCC/MSVC you will have to define it on your own. 63 | */ 64 | 65 | /* These macros are used in order to make the code portable. */ 66 | #ifdef __GNUC__ 67 | 68 | #include 69 | 70 | #define _DLLEXPORT_ 71 | #define _FASTCALL_ 72 | #define _INLINE_ static 73 | /* GCC ignores this directive... */ 74 | /*#define _FASTCALL_ __attribute__((__fastcall__))*/ 75 | 76 | /* Set endianity (supposed to be LE though): */ 77 | #ifdef __BIG_ENDIAN__ 78 | #define BE_SYSTEM 79 | #endif 80 | 81 | /* End of __GCC__ */ 82 | 83 | #elif __WATCOMC__ 84 | 85 | #include 86 | 87 | #define _DLLEXPORT_ 88 | #define _FASTCALL_ 89 | #define _INLINE_ __inline 90 | 91 | /* End of __WATCOMC__ */ 92 | 93 | #elif __DMC__ 94 | 95 | #include 96 | 97 | #define _DLLEXPORT_ 98 | #define _FASTCALL_ 99 | #define _INLINE_ __inline 100 | 101 | /* End of __DMC__ */ 102 | 103 | #elif __TINYC__ 104 | 105 | #include 106 | 107 | #define _DLLEXPORT_ 108 | #define _FASTCALL_ 109 | #define _INLINE_ 110 | 111 | /* End of __TINYC__ */ 112 | 113 | #elif _MSC_VER 114 | 115 | /* stdint alternative is defined in distorm.h */ 116 | 117 | #define _DLLEXPORT_ __declspec(dllexport) 118 | #define _FASTCALL_ __fastcall 119 | #define _INLINE_ __inline 120 | 121 | /* Set endianity (supposed to be LE though): */ 122 | #if !defined(_M_IX86) && !defined(_M_X64) 123 | #define BE_SYSTEM 124 | #endif 125 | 126 | #endif /* #elif _MSC_VER */ 127 | 128 | /* If the library isn't compiled as a dynamic library don't export any functions. */ 129 | #ifndef DISTORM_DYNAMIC 130 | #undef _DLLEXPORT_ 131 | #define _DLLEXPORT_ 132 | #endif 133 | 134 | #ifndef FALSE 135 | #define FALSE 0 136 | #endif 137 | #ifndef TRUE 138 | #define TRUE 1 139 | #endif 140 | 141 | /* Define stream read functions for big endian systems. */ 142 | #ifdef BE_SYSTEM 143 | /* 144 | * These functions can read from the stream safely! 145 | * Swap endianity of input to little endian. 146 | */ 147 | static _INLINE_ int16_t RSHORT(const uint8_t *s) 148 | { 149 | return s[0] | (s[1] << 8); 150 | } 151 | static _INLINE_ uint16_t RUSHORT(const uint8_t *s) 152 | { 153 | return s[0] | (s[1] << 8); 154 | } 155 | static _INLINE_ int32_t RLONG(const uint8_t *s) 156 | { 157 | return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); 158 | } 159 | static _INLINE_ uint32_t RULONG(const uint8_t *s) 160 | { 161 | return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); 162 | } 163 | static _INLINE_ int64_t RLLONG(const uint8_t *s) 164 | { 165 | return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24) | ((uint64_t)s[4] << 32) | ((uint64_t)s[5] << 40) | ((uint64_t)s[6] << 48) | ((uint64_t)s[7] << 56); 166 | } 167 | static _INLINE_ uint64_t RULLONG(const uint8_t *s) 168 | { 169 | return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24) | ((uint64_t)s[4] << 32) | ((uint64_t)s[5] << 40) | ((uint64_t)s[6] << 48) | ((uint64_t)s[7] << 56); 170 | } 171 | #else 172 | /* Little endian macro's will just make the cast. */ 173 | #define RSHORT(x) *(int16_t *)x 174 | #define RUSHORT(x) *(uint16_t *)x 175 | #define RLONG(x) *(int32_t *)x 176 | #define RULONG(x) *(uint32_t *)x 177 | #define RLLONG(x) *(int64_t *)x 178 | #define RULLONG(x) *(uint64_t *)x 179 | #endif 180 | 181 | #endif /* CONFIG_H */ 182 | -------------------------------------------------------------------------------- /kextstat_aslr/textdefs.c: -------------------------------------------------------------------------------- 1 | /* 2 | textdefs.c 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #include "textdefs.h" 25 | 26 | #ifndef DISTORM_LIGHT 27 | 28 | static uint8_t Nibble2ChrTable[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 29 | #define NIBBLE_TO_CHR Nibble2ChrTable[t] 30 | 31 | void _FASTCALL_ str_hex_b(_WString* s, unsigned int x) 32 | { 33 | /* 34 | * def prebuilt(): 35 | * s = "" 36 | * for i in xrange(256): 37 | * if ((i % 0x10) == 0): 38 | * s += "\r\n" 39 | * s += "\"%02x\", " % (i) 40 | * return s 41 | */ 42 | static int8_t TextBTable[256][3] = { 43 | "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", 44 | "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", 45 | "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", 46 | "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", 47 | "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", 48 | "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", 49 | "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", 50 | "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", 51 | "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", 52 | "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", 53 | "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", 54 | "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", 55 | "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", 56 | "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", 57 | "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", 58 | "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff" 59 | }; 60 | 61 | /* 62 | * Fixed length of 3 including null terminate character. 63 | */ 64 | memcpy(&s->p[s->length], TextBTable[x & 255], 3); 65 | s->length += 2; 66 | } 67 | 68 | void _FASTCALL_ str_code_hb(_WString* s, unsigned int x) 69 | { 70 | static int8_t TextHBTable[256][5] = { 71 | /* 72 | * def prebuilt(): 73 | * s = "" 74 | * for i in xrange(256): 75 | * if ((i % 0x10) == 0): 76 | * s += "\r\n" 77 | * s += "\"0x%x\", " % (i) 78 | * return s 79 | */ 80 | "0x0", "0x1", "0x2", "0x3", "0x4", "0x5", "0x6", "0x7", "0x8", "0x9", "0xa", "0xb", "0xc", "0xd", "0xe", "0xf", 81 | "0x10", "0x11", "0x12", "0x13", "0x14", "0x15", "0x16", "0x17", "0x18", "0x19", "0x1a", "0x1b", "0x1c", "0x1d", "0x1e", "0x1f", 82 | "0x20", "0x21", "0x22", "0x23", "0x24", "0x25", "0x26", "0x27", "0x28", "0x29", "0x2a", "0x2b", "0x2c", "0x2d", "0x2e", "0x2f", 83 | "0x30", "0x31", "0x32", "0x33", "0x34", "0x35", "0x36", "0x37", "0x38", "0x39", "0x3a", "0x3b", "0x3c", "0x3d", "0x3e", "0x3f", 84 | "0x40", "0x41", "0x42", "0x43", "0x44", "0x45", "0x46", "0x47", "0x48", "0x49", "0x4a", "0x4b", "0x4c", "0x4d", "0x4e", "0x4f", 85 | "0x50", "0x51", "0x52", "0x53", "0x54", "0x55", "0x56", "0x57", "0x58", "0x59", "0x5a", "0x5b", "0x5c", "0x5d", "0x5e", "0x5f", 86 | "0x60", "0x61", "0x62", "0x63", "0x64", "0x65", "0x66", "0x67", "0x68", "0x69", "0x6a", "0x6b", "0x6c", "0x6d", "0x6e", "0x6f", 87 | "0x70", "0x71", "0x72", "0x73", "0x74", "0x75", "0x76", "0x77", "0x78", "0x79", "0x7a", "0x7b", "0x7c", "0x7d", "0x7e", "0x7f", 88 | "0x80", "0x81", "0x82", "0x83", "0x84", "0x85", "0x86", "0x87", "0x88", "0x89", "0x8a", "0x8b", "0x8c", "0x8d", "0x8e", "0x8f", 89 | "0x90", "0x91", "0x92", "0x93", "0x94", "0x95", "0x96", "0x97", "0x98", "0x99", "0x9a", "0x9b", "0x9c", "0x9d", "0x9e", "0x9f", 90 | "0xa0", "0xa1", "0xa2", "0xa3", "0xa4", "0xa5", "0xa6", "0xa7", "0xa8", "0xa9", "0xaa", "0xab", "0xac", "0xad", "0xae", "0xaf", 91 | "0xb0", "0xb1", "0xb2", "0xb3", "0xb4", "0xb5", "0xb6", "0xb7", "0xb8", "0xb9", "0xba", "0xbb", "0xbc", "0xbd", "0xbe", "0xbf", 92 | "0xc0", "0xc1", "0xc2", "0xc3", "0xc4", "0xc5", "0xc6", "0xc7", "0xc8", "0xc9", "0xca", "0xcb", "0xcc", "0xcd", "0xce", "0xcf", 93 | "0xd0", "0xd1", "0xd2", "0xd3", "0xd4", "0xd5", "0xd6", "0xd7", "0xd8", "0xd9", "0xda", "0xdb", "0xdc", "0xdd", "0xde", "0xdf", 94 | "0xe0", "0xe1", "0xe2", "0xe3", "0xe4", "0xe5", "0xe6", "0xe7", "0xe8", "0xe9", "0xea", "0xeb", "0xec", "0xed", "0xee", "0xef", 95 | "0xf0", "0xf1", "0xf2", "0xf3", "0xf4", "0xf5", "0xf6", "0xf7", "0xf8", "0xf9", "0xfa", "0xfb", "0xfc", "0xfd", "0xfe", "0xff" 96 | }; 97 | 98 | if (x < 0x10) { /* < 0x10 has a fixed length of 4 including null terminate. */ 99 | memcpy(&s->p[s->length], TextHBTable[x & 255], 4); 100 | s->length += 3; 101 | } else { /* >= 0x10 has a fixed length of 5 including null terminate. */ 102 | memcpy(&s->p[s->length], TextHBTable[x & 255], 5); 103 | s->length += 4; 104 | } 105 | } 106 | 107 | void _FASTCALL_ str_code_hdw(_WString* s, uint32_t x) 108 | { 109 | int8_t* buf; 110 | int i = 0, shift = 0; 111 | unsigned int t = 0; 112 | 113 | buf = (int8_t*)&s->p[s->length]; 114 | 115 | buf[0] = '0'; 116 | buf[1] = 'x'; 117 | buf += 2; 118 | 119 | for (shift = 28; shift != 0; shift -= 4) { 120 | t = (x >> shift) & 0xf; 121 | if (i | t) buf[i++] = NIBBLE_TO_CHR; 122 | } 123 | t = x & 0xf; 124 | buf[i++] = NIBBLE_TO_CHR; 125 | 126 | s->length += i + 2; 127 | buf[i] = '\0'; 128 | } 129 | 130 | void _FASTCALL_ str_code_hqw(_WString* s, uint8_t src[8]) 131 | { 132 | int8_t* buf; 133 | int i = 0, shift = 0; 134 | uint32_t x = RULONG(&src[sizeof(int32_t)]); 135 | int t; 136 | 137 | buf = (int8_t*)&s->p[s->length]; 138 | buf[0] = '0'; 139 | buf[1] = 'x'; 140 | buf += 2; 141 | 142 | for (shift = 28; shift != -4; shift -= 4) { 143 | t = (x >> shift) & 0xf; 144 | if (i | t) buf[i++] = NIBBLE_TO_CHR; 145 | } 146 | 147 | x = RULONG(src); 148 | for (shift = 28; shift != 0; shift -= 4) { 149 | t = (x >> shift) & 0xf; 150 | if (i | t) buf[i++] = NIBBLE_TO_CHR; 151 | } 152 | t = x & 0xf; 153 | buf[i++] = NIBBLE_TO_CHR; 154 | 155 | s->length += i + 2; 156 | buf[i] = '\0'; 157 | } 158 | 159 | #ifdef SUPPORT_64BIT_OFFSET 160 | void _FASTCALL_ str_off64(_WString* s, OFFSET_INTEGER x) 161 | { 162 | int8_t* buf; 163 | int i = 0, shift = 0; 164 | OFFSET_INTEGER t = 0; 165 | 166 | buf = (int8_t*)&s->p[s->length]; 167 | 168 | buf[0] = '0'; 169 | buf[1] = 'x'; 170 | buf += 2; 171 | 172 | for (shift = 60; shift != 0; shift -= 4) { 173 | t = (x >> shift) & 0xf; 174 | if (i | t) buf[i++] = NIBBLE_TO_CHR; 175 | } 176 | t = x & 0xf; 177 | buf[i++] = NIBBLE_TO_CHR; 178 | 179 | s->length += i + 2; 180 | buf[i] = '\0'; 181 | } 182 | #endif /* SUPPORT_64BIT_OFFSET */ 183 | 184 | #endif /* DISTORM_LIGHT */ 185 | -------------------------------------------------------------------------------- /kextstat_aslr/distorm.c: -------------------------------------------------------------------------------- 1 | /* 2 | distorm.c 3 | 4 | diStorm3 C Library Interface 5 | diStorm3 - Powerful disassembler for X86/AMD64 6 | http://ragestorm.net/distorm/ 7 | distorm at gmail dot com 8 | Copyright (C) 2003-2012 Gil Dabah 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see 22 | */ 23 | 24 | 25 | #include "distorm.h" 26 | #include "config.h" 27 | #include "decoder.h" 28 | #include "x86defs.h" 29 | #include "textdefs.h" 30 | #include "wstring.h" 31 | #include "mnemonics.h" 32 | 33 | /* C DLL EXPORTS */ 34 | #ifdef SUPPORT_64BIT_OFFSET 35 | _DLLEXPORT_ _DecodeResult distorm_decompose64(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) 36 | #else 37 | _DLLEXPORT_ _DecodeResult distorm_decompose32(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) 38 | #endif 39 | { 40 | if (usedInstructionsCount == NULL) { 41 | return DECRES_SUCCESS; 42 | } 43 | 44 | /* DECRES_SUCCESS still may indicate we may have something in the result, so zero it first thing. */ 45 | *usedInstructionsCount = 0; 46 | 47 | if ((ci == NULL) || 48 | (ci->codeLen < 0) || 49 | ((ci->dt != Decode16Bits) && (ci->dt != Decode32Bits) && (ci->dt != Decode64Bits)) || 50 | (ci->code == NULL) || 51 | (result == NULL) || 52 | ((ci->features & (DF_MAXIMUM_ADDR16 | DF_MAXIMUM_ADDR32)) == (DF_MAXIMUM_ADDR16 | DF_MAXIMUM_ADDR32))) 53 | { 54 | return DECRES_INPUTERR; 55 | } 56 | 57 | /* Assume length=0 is success. */ 58 | if (ci->codeLen == 0) { 59 | return DECRES_SUCCESS; 60 | } 61 | 62 | return decode_internal(ci, FALSE, result, maxInstructions, usedInstructionsCount); 63 | } 64 | 65 | #ifndef DISTORM_LIGHT 66 | 67 | /* Helper function to concat an explicit size when it's unknown from the operands. */ 68 | static void distorm_format_size(_WString* str, const _DInst* di, int opNum) 69 | { 70 | /* 71 | * We only have to output the size explicitly if it's not clear from the operands. 72 | * For example: 73 | * mov al, [0x1234] -> The size is 8, we know it from the AL register operand. 74 | * mov [0x1234], 0x11 -> Now we don't know the size. Pam pam pam 75 | * 76 | * If given operand number is higher than 2, then output the size anyways. 77 | */ 78 | if (((opNum >= 2) || ((di->ops[0].type != O_REG) && (di->ops[1].type != O_REG))) || 79 | /* 80 | * INS/OUTS are exception, because DX is a port specifier and not a real src/dst register. 81 | * MOVZX is also an exception, because the source operand can be a memory indirection: 82 | * MOVZX EBX, [ECX], but which size from ECX was read? 83 | */ 84 | ((di->opcode == I_INS) || (di->opcode == I_OUTS) || (di->opcode == I_MOVZX))) { 85 | switch (di->ops[opNum].size) 86 | { 87 | case 0: break; /* OT_MEM's unknown size. */ 88 | case 8: strcat_WSN(str, "BYTE "); break; 89 | case 16: strcat_WSN(str, "WORD "); break; 90 | case 32: strcat_WSN(str, "DWORD "); break; 91 | case 64: strcat_WSN(str, "QWORD "); break; 92 | case 80: strcat_WSN(str, "TBYTE "); break; 93 | case 128: strcat_WSN(str, "DQWORD "); break; 94 | case 256: strcat_WSN(str, "YWORD "); break; 95 | default: /* Big oh uh if it gets here. */ break; 96 | } 97 | } 98 | } 99 | 100 | static void distorm_format_signed_disp(_WString* str, const _DInst* di, uint64_t addrMask) 101 | { 102 | int64_t tmpDisp64; 103 | 104 | if (di->dispSize) { 105 | chrcat_WS(str, ((int64_t)di->disp < 0) ? MINUS_DISP_CHR : PLUS_DISP_CHR); 106 | if ((int64_t)di->disp < 0) tmpDisp64 = -(int64_t)di->disp; 107 | else tmpDisp64 = di->disp; 108 | tmpDisp64 &= addrMask; 109 | str_code_hqw(str, (uint8_t*)&tmpDisp64); 110 | } 111 | } 112 | 113 | #ifdef SUPPORT_64BIT_OFFSET 114 | _DLLEXPORT_ void distorm_format64(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result) 115 | #else 116 | _DLLEXPORT_ void distorm_format32(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result) 117 | #endif 118 | { 119 | _WString* str; 120 | unsigned int i, isDefault; 121 | int64_t tmpDisp64; 122 | uint64_t addrMask = (uint64_t)-1; 123 | uint8_t segment; 124 | const _WMnemonic* mnemonic; 125 | 126 | /* Set address mask, when default is for 64bits addresses. */ 127 | if (ci->features & DF_MAXIMUM_ADDR32) addrMask = 0xffffffff; 128 | else if (ci->features & DF_MAXIMUM_ADDR16) addrMask = 0xffff; 129 | 130 | /* Copy other fields. */ 131 | result->size = di->size; 132 | result->offset = di->addr & addrMask; 133 | 134 | if (di->flags == FLAG_NOT_DECODABLE) { 135 | str = &result->mnemonic; 136 | strclear_WS(&result->operands); 137 | strcpy_WSN(str, "DB "); 138 | str_code_hb(str, di->imm.byte); 139 | strclear_WS(&result->instructionHex); 140 | str_hex_b(&result->instructionHex, di->imm.byte); 141 | return; /* Skip to next instruction. */ 142 | } 143 | 144 | str = &result->instructionHex; 145 | strclear_WS(str); 146 | for (i = 0; i < di->size; i++) 147 | str_hex_b(str, ci->code[(unsigned int)(di->addr - ci->codeOffset + i)]); 148 | 149 | str = &result->mnemonic; 150 | switch (FLAG_GET_PREFIX(di->flags)) 151 | { 152 | case FLAG_LOCK: 153 | strcpy_WSN(str, "LOCK "); 154 | break; 155 | case FLAG_REP: 156 | strcpy_WSN(str, "REP "); 157 | break; 158 | case FLAG_REPNZ: 159 | strcpy_WSN(str, "REPNZ "); 160 | break; 161 | default: 162 | /* Init mnemonic string, cause next touch is concatenation. */ 163 | strclear_WS(str); 164 | break; 165 | } 166 | 167 | mnemonic = (const _WMnemonic*)&_MNEMONICS[di->opcode]; 168 | memcpy((int8_t*)&str->p[str->length], mnemonic->p, mnemonic->length + 1); 169 | str->length += mnemonic->length; 170 | 171 | /* Format operands: */ 172 | str = &result->operands; 173 | strclear_WS(str); 174 | 175 | /* Special treatment for String instructions. */ 176 | if ((META_GET_ISC(di->meta) == ISC_INTEGER) && 177 | ((di->opcode == I_MOVS) || 178 | (di->opcode == I_CMPS) || 179 | (di->opcode == I_STOS) || 180 | (di->opcode == I_LODS) || 181 | (di->opcode == I_SCAS))) 182 | { 183 | /* 184 | * No operands are needed if the address size is the default one, 185 | * and no segment is overridden, so add the suffix letter, 186 | * to indicate size of operation and continue to next instruction. 187 | */ 188 | if ((FLAG_GET_ADDRSIZE(di->flags) == ci->dt) && (SEGMENT_IS_DEFAULT(di->segment))) { 189 | str = &result->mnemonic; 190 | switch (di->ops[0].size) 191 | { 192 | case 8: chrcat_WS(str, 'B'); break; 193 | case 16: chrcat_WS(str, 'W'); break; 194 | case 32: chrcat_WS(str, 'D'); break; 195 | case 64: chrcat_WS(str, 'Q'); break; 196 | } 197 | return; 198 | } 199 | } 200 | 201 | for (i = 0; ((i < OPERANDS_NO) && (di->ops[i].type != O_NONE)); i++) { 202 | if (i > 0) strcat_WSN(str, ", "); 203 | switch (di->ops[i].type) 204 | { 205 | case O_REG: 206 | strcat_WS(str, (const _WString*)&_REGISTERS[di->ops[i].index]); 207 | break; 208 | case O_IMM: 209 | /* If the instruction is 'push', show explicit size (except byte imm). */ 210 | if (di->opcode == I_PUSH && di->ops[i].size != 8) distorm_format_size(str, di, i); 211 | /* Special fix for negative sign extended immediates. */ 212 | if ((di->flags & FLAG_IMM_SIGNED) && (di->ops[i].size == 8)) { 213 | if (di->imm.sbyte < 0) { 214 | chrcat_WS(str, MINUS_DISP_CHR); 215 | str_code_hb(str, -di->imm.sbyte); 216 | break; 217 | } 218 | } 219 | if (di->ops[i].size == 64) str_code_hqw(str, (uint8_t*)&di->imm.qword); 220 | else str_code_hdw(str, di->imm.dword); 221 | break; 222 | case O_IMM1: 223 | str_code_hdw(str, di->imm.ex.i1); 224 | break; 225 | case O_IMM2: 226 | str_code_hdw(str, di->imm.ex.i2); 227 | break; 228 | case O_DISP: 229 | distorm_format_size(str, di, i); 230 | chrcat_WS(str, OPEN_CHR); 231 | if ((SEGMENT_GET(di->segment) != R_NONE) && !SEGMENT_IS_DEFAULT(di->segment)) { 232 | strcat_WS(str, (const _WString*)&_REGISTERS[SEGMENT_GET(di->segment)]); 233 | chrcat_WS(str, SEG_OFF_CHR); 234 | } 235 | tmpDisp64 = di->disp & addrMask; 236 | str_code_hqw(str, (uint8_t*)&tmpDisp64); 237 | chrcat_WS(str, CLOSE_CHR); 238 | break; 239 | case O_SMEM: 240 | distorm_format_size(str, di, i); 241 | chrcat_WS(str, OPEN_CHR); 242 | 243 | /* 244 | * This is where we need to take special care for String instructions. 245 | * If we got here, it means we need to explicitly show their operands. 246 | * The problem with CMPS and MOVS is that they have two(!) memory operands. 247 | * So we have to complete it ourselves, since the structure supplies only the segment that can be overridden. 248 | * And make the rest of the String operations explicit. 249 | */ 250 | segment = SEGMENT_GET(di->segment); 251 | isDefault = SEGMENT_IS_DEFAULT(di->segment); 252 | switch (di->opcode) 253 | { 254 | case I_MOVS: 255 | isDefault = FALSE; 256 | if (i == 0) segment = R_ES; 257 | break; 258 | case I_CMPS: 259 | isDefault = FALSE; 260 | if (i == 1) segment = R_ES; 261 | break; 262 | case I_INS: 263 | case I_LODS: 264 | case I_STOS: 265 | case I_SCAS: isDefault = FALSE; break; 266 | } 267 | if (!isDefault && (segment != R_NONE)) { 268 | strcat_WS(str, (const _WString*)&_REGISTERS[segment]); 269 | chrcat_WS(str, SEG_OFF_CHR); 270 | } 271 | 272 | strcat_WS(str, (const _WString*)&_REGISTERS[di->ops[i].index]); 273 | 274 | distorm_format_signed_disp(str, di, addrMask); 275 | chrcat_WS(str, CLOSE_CHR); 276 | break; 277 | case O_MEM: 278 | distorm_format_size(str, di, i); 279 | chrcat_WS(str, OPEN_CHR); 280 | if ((SEGMENT_GET(di->segment) != R_NONE) && !SEGMENT_IS_DEFAULT(di->segment)) { 281 | strcat_WS(str, (const _WString*)&_REGISTERS[SEGMENT_GET(di->segment)]); 282 | chrcat_WS(str, SEG_OFF_CHR); 283 | } 284 | if (di->base != R_NONE) { 285 | strcat_WS(str, (const _WString*)&_REGISTERS[di->base]); 286 | chrcat_WS(str, PLUS_DISP_CHR); 287 | } 288 | strcat_WS(str, (const _WString*)&_REGISTERS[di->ops[i].index]); 289 | if (di->scale != 0) { 290 | chrcat_WS(str, '*'); 291 | if (di->scale == 2) chrcat_WS(str, '2'); 292 | else if (di->scale == 4) chrcat_WS(str, '4'); 293 | else /* if (di->scale == 8) */ chrcat_WS(str, '8'); 294 | } 295 | 296 | distorm_format_signed_disp(str, di, addrMask); 297 | chrcat_WS(str, CLOSE_CHR); 298 | break; 299 | case O_PC: 300 | #ifdef SUPPORT_64BIT_OFFSET 301 | str_off64(str, (di->imm.sqword + di->addr + di->size) & addrMask); 302 | #else 303 | str_code_hdw(str, ((_OffsetType)di->imm.sdword + di->addr + di->size) & (uint32_t)addrMask); 304 | #endif 305 | break; 306 | case O_PTR: 307 | str_code_hdw(str, di->imm.ptr.seg); 308 | chrcat_WS(str, SEG_OFF_CHR); 309 | str_code_hdw(str, di->imm.ptr.off); 310 | break; 311 | } 312 | } 313 | 314 | if (di->flags & FLAG_HINT_TAKEN) strcat_WSN(str, " ;TAKEN"); 315 | else if (di->flags & FLAG_HINT_NOT_TAKEN) strcat_WSN(str, " ;NOT TAKEN"); 316 | } 317 | 318 | #ifdef SUPPORT_64BIT_OFFSET 319 | _DLLEXPORT_ _DecodeResult distorm_decode64(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) 320 | #else 321 | _DLLEXPORT_ _DecodeResult distorm_decode32(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) 322 | #endif 323 | { 324 | _DecodeResult res; 325 | _DInst di; 326 | _CodeInfo ci; 327 | unsigned int instsCount = 0, i; 328 | 329 | *usedInstructionsCount = 0; 330 | 331 | /* I use codeLen as a signed variable in order to ease detection of underflow... and besides - */ 332 | if (codeLen < 0) { 333 | return DECRES_INPUTERR; 334 | } 335 | 336 | if ((dt != Decode16Bits) && (dt != Decode32Bits) && (dt != Decode64Bits)) { 337 | return DECRES_INPUTERR; 338 | } 339 | 340 | if (code == NULL || result == NULL) { 341 | return DECRES_INPUTERR; 342 | } 343 | 344 | /* Assume length=0 is success. */ 345 | if (codeLen == 0) { 346 | return DECRES_SUCCESS; 347 | } 348 | 349 | /* 350 | * We have to format the result into text. But the interal decoder works with the new structure of _DInst. 351 | * Therefore, we will pass the result array(!) from the caller and the interal decoder will fill it in with _DInst's. 352 | * Then we will copy each result to a temporary structure, and use it to reformat that specific result. 353 | * 354 | * This is all done to save memory allocation and to work on the same result array in-place!!! 355 | * It's a bit ugly, I have to admit, but worth it. 356 | */ 357 | 358 | ci.codeOffset = codeOffset; 359 | ci.code = code; 360 | ci.codeLen = codeLen; 361 | ci.dt = dt; 362 | ci.features = DF_NONE; 363 | if (dt == Decode16Bits) ci.features = DF_MAXIMUM_ADDR16; 364 | else if (dt == Decode32Bits) ci.features = DF_MAXIMUM_ADDR32; 365 | 366 | res = decode_internal(&ci, TRUE, (_DInst*)result, maxInstructions, &instsCount); 367 | for (i = 0; i < instsCount; i++) { 368 | if ((*usedInstructionsCount + i) >= maxInstructions) return DECRES_MEMORYERR; 369 | 370 | /* Copy the current decomposed result to a temp structure, so we can override the result with text. */ 371 | memcpy(&di, (char*)result + (i * sizeof(_DecodedInst)), sizeof(_DInst)); 372 | #ifdef SUPPORT_64BIT_OFFSET 373 | distorm_format64(&ci, &di, &result[i]); 374 | #else 375 | distorm_format32(&ci, &di, &result[i]); 376 | #endif 377 | } 378 | 379 | *usedInstructionsCount = instsCount; 380 | return res; 381 | } 382 | 383 | #endif /* DISTORM_LIGHT */ 384 | 385 | _DLLEXPORT_ unsigned int distorm_version() 386 | { 387 | return __DISTORMV__; 388 | } 389 | -------------------------------------------------------------------------------- /kextstat_aslr.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7B6CDE6A1659CE3B00893578 /* System.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B6CDE691659CE3B00893578 /* System.framework */; }; 11 | 7B80CD94165880F100127A39 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B80CD93165880F100127A39 /* main.c */; }; 12 | 7BDD3EF516FA20BA002ADD4A /* decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BDD3EE216FA20BA002ADD4A /* decoder.c */; }; 13 | 7BDD3EF616FA20BA002ADD4A /* distorm.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BDD3EE416FA20BA002ADD4A /* distorm.c */; }; 14 | 7BDD3EF716FA20BA002ADD4A /* instructions.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BDD3EE616FA20BA002ADD4A /* instructions.c */; }; 15 | 7BDD3EF816FA20BA002ADD4A /* insts.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BDD3EE816FA20BA002ADD4A /* insts.c */; }; 16 | 7BDD3EF916FA20BA002ADD4A /* mnemonics.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BDD3EEA16FA20BA002ADD4A /* mnemonics.c */; }; 17 | 7BDD3EFA16FA20BA002ADD4A /* operands.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BDD3EEC16FA20BA002ADD4A /* operands.c */; }; 18 | 7BDD3EFB16FA20BA002ADD4A /* prefix.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BDD3EEE16FA20BA002ADD4A /* prefix.c */; }; 19 | 7BDD3EFC16FA20BA002ADD4A /* textdefs.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BDD3EF016FA20BA002ADD4A /* textdefs.c */; }; 20 | 7BDD3EFD16FA20BA002ADD4A /* wstring.c in Sources */ = {isa = PBXBuildFile; fileRef = 7BDD3EF216FA20BA002ADD4A /* wstring.c */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXCopyFilesBuildPhase section */ 24 | 7B80CD8D165880F100127A39 /* CopyFiles */ = { 25 | isa = PBXCopyFilesBuildPhase; 26 | buildActionMask = 2147483647; 27 | dstPath = /usr/share/man/man1/; 28 | dstSubfolderSpec = 0; 29 | files = ( 30 | ); 31 | runOnlyForDeploymentPostprocessing = 1; 32 | }; 33 | /* End PBXCopyFilesBuildPhase section */ 34 | 35 | /* Begin PBXFileReference section */ 36 | 7B6CDE691659CE3B00893578 /* System.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = System.framework; path = ../../../../System/Library/Frameworks/System.framework; sourceTree = ""; }; 37 | 7B80CD8F165880F100127A39 /* kextstat_aslr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = kextstat_aslr; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 7B80CD93165880F100127A39 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; 39 | 7BDD3EE116FA20BA002ADD4A /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config.h; path = kextstat_aslr/config.h; sourceTree = ""; }; 40 | 7BDD3EE216FA20BA002ADD4A /* decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = decoder.c; path = kextstat_aslr/decoder.c; sourceTree = ""; }; 41 | 7BDD3EE316FA20BA002ADD4A /* decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = decoder.h; path = kextstat_aslr/decoder.h; sourceTree = ""; }; 42 | 7BDD3EE416FA20BA002ADD4A /* distorm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = distorm.c; path = kextstat_aslr/distorm.c; sourceTree = ""; }; 43 | 7BDD3EE516FA20BA002ADD4A /* distorm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = distorm.h; path = kextstat_aslr/distorm.h; sourceTree = ""; }; 44 | 7BDD3EE616FA20BA002ADD4A /* instructions.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = instructions.c; path = kextstat_aslr/instructions.c; sourceTree = ""; }; 45 | 7BDD3EE716FA20BA002ADD4A /* instructions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = instructions.h; path = kextstat_aslr/instructions.h; sourceTree = ""; }; 46 | 7BDD3EE816FA20BA002ADD4A /* insts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = insts.c; path = kextstat_aslr/insts.c; sourceTree = ""; }; 47 | 7BDD3EE916FA20BA002ADD4A /* insts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = insts.h; path = kextstat_aslr/insts.h; sourceTree = ""; }; 48 | 7BDD3EEA16FA20BA002ADD4A /* mnemonics.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mnemonics.c; path = kextstat_aslr/mnemonics.c; sourceTree = ""; }; 49 | 7BDD3EEB16FA20BA002ADD4A /* mnemonics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mnemonics.h; path = kextstat_aslr/mnemonics.h; sourceTree = ""; }; 50 | 7BDD3EEC16FA20BA002ADD4A /* operands.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = operands.c; path = kextstat_aslr/operands.c; sourceTree = ""; }; 51 | 7BDD3EED16FA20BA002ADD4A /* operands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = operands.h; path = kextstat_aslr/operands.h; sourceTree = ""; }; 52 | 7BDD3EEE16FA20BA002ADD4A /* prefix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = prefix.c; path = kextstat_aslr/prefix.c; sourceTree = ""; }; 53 | 7BDD3EEF16FA20BA002ADD4A /* prefix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = prefix.h; path = kextstat_aslr/prefix.h; sourceTree = ""; }; 54 | 7BDD3EF016FA20BA002ADD4A /* textdefs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = textdefs.c; path = kextstat_aslr/textdefs.c; sourceTree = ""; }; 55 | 7BDD3EF116FA20BA002ADD4A /* textdefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = textdefs.h; path = kextstat_aslr/textdefs.h; sourceTree = ""; }; 56 | 7BDD3EF216FA20BA002ADD4A /* wstring.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = wstring.c; path = kextstat_aslr/wstring.c; sourceTree = ""; }; 57 | 7BDD3EF316FA20BA002ADD4A /* wstring.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = wstring.h; path = kextstat_aslr/wstring.h; sourceTree = ""; }; 58 | 7BDD3EF416FA20BA002ADD4A /* x86defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = x86defs.h; path = kextstat_aslr/x86defs.h; sourceTree = ""; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | 7B80CD8C165880F100127A39 /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | 7B6CDE6A1659CE3B00893578 /* System.framework in Frameworks */, 67 | ); 68 | runOnlyForDeploymentPostprocessing = 0; 69 | }; 70 | /* End PBXFrameworksBuildPhase section */ 71 | 72 | /* Begin PBXGroup section */ 73 | 7B1593C116F7210400140560 /* distorm */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 7BDD3EE116FA20BA002ADD4A /* config.h */, 77 | 7BDD3EE216FA20BA002ADD4A /* decoder.c */, 78 | 7BDD3EE316FA20BA002ADD4A /* decoder.h */, 79 | 7BDD3EE416FA20BA002ADD4A /* distorm.c */, 80 | 7BDD3EE516FA20BA002ADD4A /* distorm.h */, 81 | 7BDD3EE616FA20BA002ADD4A /* instructions.c */, 82 | 7BDD3EE716FA20BA002ADD4A /* instructions.h */, 83 | 7BDD3EE816FA20BA002ADD4A /* insts.c */, 84 | 7BDD3EE916FA20BA002ADD4A /* insts.h */, 85 | 7BDD3EEA16FA20BA002ADD4A /* mnemonics.c */, 86 | 7BDD3EEB16FA20BA002ADD4A /* mnemonics.h */, 87 | 7BDD3EEC16FA20BA002ADD4A /* operands.c */, 88 | 7BDD3EED16FA20BA002ADD4A /* operands.h */, 89 | 7BDD3EEE16FA20BA002ADD4A /* prefix.c */, 90 | 7BDD3EEF16FA20BA002ADD4A /* prefix.h */, 91 | 7BDD3EF016FA20BA002ADD4A /* textdefs.c */, 92 | 7BDD3EF116FA20BA002ADD4A /* textdefs.h */, 93 | 7BDD3EF216FA20BA002ADD4A /* wstring.c */, 94 | 7BDD3EF316FA20BA002ADD4A /* wstring.h */, 95 | 7BDD3EF416FA20BA002ADD4A /* x86defs.h */, 96 | ); 97 | name = distorm; 98 | path = ..; 99 | sourceTree = ""; 100 | }; 101 | 7B80CD84165880F100127A39 = { 102 | isa = PBXGroup; 103 | children = ( 104 | 7B6CDE691659CE3B00893578 /* System.framework */, 105 | 7B80CD92165880F100127A39 /* kextstat_aslr */, 106 | 7B80CD90165880F100127A39 /* Products */, 107 | ); 108 | sourceTree = ""; 109 | }; 110 | 7B80CD90165880F100127A39 /* Products */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 7B80CD8F165880F100127A39 /* kextstat_aslr */, 114 | ); 115 | name = Products; 116 | sourceTree = ""; 117 | }; 118 | 7B80CD92165880F100127A39 /* kextstat_aslr */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 7B80CD93165880F100127A39 /* main.c */, 122 | 7B1593C116F7210400140560 /* distorm */, 123 | ); 124 | path = kextstat_aslr; 125 | sourceTree = ""; 126 | }; 127 | /* End PBXGroup section */ 128 | 129 | /* Begin PBXNativeTarget section */ 130 | 7B80CD8E165880F100127A39 /* kextstat_aslr */ = { 131 | isa = PBXNativeTarget; 132 | buildConfigurationList = 7B80CD99165880F100127A39 /* Build configuration list for PBXNativeTarget "kextstat_aslr" */; 133 | buildPhases = ( 134 | 7B80CD8B165880F100127A39 /* Sources */, 135 | 7B80CD8C165880F100127A39 /* Frameworks */, 136 | 7B80CD8D165880F100127A39 /* CopyFiles */, 137 | ); 138 | buildRules = ( 139 | ); 140 | dependencies = ( 141 | ); 142 | name = kextstat_aslr; 143 | productName = kextstat_aslr; 144 | productReference = 7B80CD8F165880F100127A39 /* kextstat_aslr */; 145 | productType = "com.apple.product-type.tool"; 146 | }; 147 | /* End PBXNativeTarget section */ 148 | 149 | /* Begin PBXProject section */ 150 | 7B80CD86165880F100127A39 /* Project object */ = { 151 | isa = PBXProject; 152 | attributes = { 153 | LastUpgradeCheck = 0450; 154 | ORGANIZATIONNAME = reverser; 155 | }; 156 | buildConfigurationList = 7B80CD89165880F100127A39 /* Build configuration list for PBXProject "kextstat_aslr" */; 157 | compatibilityVersion = "Xcode 3.2"; 158 | developmentRegion = English; 159 | hasScannedForEncodings = 0; 160 | knownRegions = ( 161 | en, 162 | ); 163 | mainGroup = 7B80CD84165880F100127A39; 164 | productRefGroup = 7B80CD90165880F100127A39 /* Products */; 165 | projectDirPath = ""; 166 | projectRoot = ""; 167 | targets = ( 168 | 7B80CD8E165880F100127A39 /* kextstat_aslr */, 169 | ); 170 | }; 171 | /* End PBXProject section */ 172 | 173 | /* Begin PBXSourcesBuildPhase section */ 174 | 7B80CD8B165880F100127A39 /* Sources */ = { 175 | isa = PBXSourcesBuildPhase; 176 | buildActionMask = 2147483647; 177 | files = ( 178 | 7B80CD94165880F100127A39 /* main.c in Sources */, 179 | 7BDD3EF516FA20BA002ADD4A /* decoder.c in Sources */, 180 | 7BDD3EF616FA20BA002ADD4A /* distorm.c in Sources */, 181 | 7BDD3EF716FA20BA002ADD4A /* instructions.c in Sources */, 182 | 7BDD3EF816FA20BA002ADD4A /* insts.c in Sources */, 183 | 7BDD3EF916FA20BA002ADD4A /* mnemonics.c in Sources */, 184 | 7BDD3EFA16FA20BA002ADD4A /* operands.c in Sources */, 185 | 7BDD3EFB16FA20BA002ADD4A /* prefix.c in Sources */, 186 | 7BDD3EFC16FA20BA002ADD4A /* textdefs.c in Sources */, 187 | 7BDD3EFD16FA20BA002ADD4A /* wstring.c in Sources */, 188 | ); 189 | runOnlyForDeploymentPostprocessing = 0; 190 | }; 191 | /* End PBXSourcesBuildPhase section */ 192 | 193 | /* Begin XCBuildConfiguration section */ 194 | 7B80CD97165880F100127A39 /* Debug */ = { 195 | isa = XCBuildConfiguration; 196 | buildSettings = { 197 | ALWAYS_SEARCH_USER_PATHS = NO; 198 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 199 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 200 | CLANG_CXX_LIBRARY = "libc++"; 201 | CLANG_WARN_EMPTY_BODY = YES; 202 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 203 | COPY_PHASE_STRIP = NO; 204 | GCC_C_LANGUAGE_STANDARD = gnu99; 205 | GCC_DYNAMIC_NO_PIC = NO; 206 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 207 | GCC_OPTIMIZATION_LEVEL = 0; 208 | GCC_PREPROCESSOR_DEFINITIONS = ( 209 | "DEBUG=1", 210 | "$(inherited)", 211 | ); 212 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 213 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 214 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 215 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 216 | GCC_WARN_UNUSED_VARIABLE = YES; 217 | MACOSX_DEPLOYMENT_TARGET = 10.8; 218 | ONLY_ACTIVE_ARCH = YES; 219 | OTHER_CFLAGS = ""; 220 | SDKROOT = macosx; 221 | }; 222 | name = Debug; 223 | }; 224 | 7B80CD98165880F100127A39 /* Release */ = { 225 | isa = XCBuildConfiguration; 226 | buildSettings = { 227 | ALWAYS_SEARCH_USER_PATHS = NO; 228 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 229 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 230 | CLANG_CXX_LIBRARY = "libc++"; 231 | CLANG_WARN_EMPTY_BODY = YES; 232 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 233 | COPY_PHASE_STRIP = YES; 234 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 235 | GCC_C_LANGUAGE_STANDARD = gnu99; 236 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 237 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 238 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 239 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 240 | GCC_WARN_UNUSED_VARIABLE = YES; 241 | MACOSX_DEPLOYMENT_TARGET = 10.8; 242 | OTHER_CFLAGS = ""; 243 | SDKROOT = macosx; 244 | }; 245 | name = Release; 246 | }; 247 | 7B80CD9A165880F100127A39 /* Debug */ = { 248 | isa = XCBuildConfiguration; 249 | buildSettings = { 250 | LIBRARY_SEARCH_PATHS = ( 251 | "$(inherited)", 252 | "\"$(SDKROOT)/usr/lib/system\"", 253 | ); 254 | PRODUCT_NAME = "$(TARGET_NAME)"; 255 | VALID_ARCHS = x86_64; 256 | }; 257 | name = Debug; 258 | }; 259 | 7B80CD9B165880F100127A39 /* Release */ = { 260 | isa = XCBuildConfiguration; 261 | buildSettings = { 262 | LIBRARY_SEARCH_PATHS = ( 263 | "$(inherited)", 264 | "\"$(SDKROOT)/usr/lib/system\"", 265 | ); 266 | PRODUCT_NAME = "$(TARGET_NAME)"; 267 | VALID_ARCHS = x86_64; 268 | }; 269 | name = Release; 270 | }; 271 | /* End XCBuildConfiguration section */ 272 | 273 | /* Begin XCConfigurationList section */ 274 | 7B80CD89165880F100127A39 /* Build configuration list for PBXProject "kextstat_aslr" */ = { 275 | isa = XCConfigurationList; 276 | buildConfigurations = ( 277 | 7B80CD97165880F100127A39 /* Debug */, 278 | 7B80CD98165880F100127A39 /* Release */, 279 | ); 280 | defaultConfigurationIsVisible = 0; 281 | defaultConfigurationName = Release; 282 | }; 283 | 7B80CD99165880F100127A39 /* Build configuration list for PBXNativeTarget "kextstat_aslr" */ = { 284 | isa = XCConfigurationList; 285 | buildConfigurations = ( 286 | 7B80CD9A165880F100127A39 /* Debug */, 287 | 7B80CD9B165880F100127A39 /* Release */, 288 | ); 289 | defaultConfigurationIsVisible = 0; 290 | defaultConfigurationName = Release; 291 | }; 292 | /* End XCConfigurationList section */ 293 | }; 294 | rootObject = 7B80CD86165880F100127A39 /* Project object */; 295 | } 296 | -------------------------------------------------------------------------------- /kextstat_aslr/instructions.h: -------------------------------------------------------------------------------- 1 | /* 2 | instructions.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef INSTRUCTIONS_H 25 | #define INSTRUCTIONS_H 26 | 27 | #include "config.h" 28 | #include "prefix.h" 29 | 30 | 31 | /* 32 | * Operand type possibilities: 33 | * Note "_FULL" suffix indicates to decode the operand as 16 bits or 32 bits depends on DecodeType - 34 | * actually, it depends on the decoding mode, unless there's an operand/address size prefix. 35 | * For example, the code: 33 c0 could be decoded/executed as XOR AX, AX or XOR EAX, EAX. 36 | */ 37 | typedef enum OpType { 38 | /* No operand is set */ 39 | OT_NONE = 0, 40 | 41 | /* Read a byte(8 bits) immediate */ 42 | OT_IMM8, 43 | /* Force a read of a word(16 bits) immediate, used by ret only */ 44 | OT_IMM16, 45 | /* Read a word/dword immediate */ 46 | OT_IMM_FULL, 47 | /* Read a double-word(32 bits) immediate */ 48 | OT_IMM32, 49 | 50 | /* Read a signed extended byte(8 bits) immediate */ 51 | OT_SEIMM8, 52 | 53 | /* 54 | * Special immediates for instructions which have more than one immediate, 55 | * which is an exception from standard instruction format. 56 | * As to version v1.0: ENTER, INSERTQ, EXTRQ are the only problematic ones. 57 | */ 58 | /* 16 bits immediate using the first imm-slot */ 59 | OT_IMM16_1, 60 | /* 8 bits immediate using the first imm-slot */ 61 | OT_IMM8_1, 62 | /* 8 bits immediate using the second imm-slot */ 63 | OT_IMM8_2, 64 | 65 | /* Use a 8bit register */ 66 | OT_REG8, 67 | /* Use a 16bit register */ 68 | OT_REG16, 69 | /* Use a 16/32/64bit register */ 70 | OT_REG_FULL, 71 | /* Use a 32bit register */ 72 | OT_REG32, 73 | /* 74 | * If used with REX the reg operand size becomes 64 bits, otherwise 32 bits. 75 | * VMX instructions are promoted automatically without a REX prefix. 76 | */ 77 | OT_REG32_64, 78 | /* Used only by MOV CR/DR(n). Promoted with REX onlly. */ 79 | OT_FREG32_64_RM, 80 | 81 | /* Use or read (indirection) a 8bit register or immediate byte */ 82 | OT_RM8, 83 | /* Some instructions force 16 bits (mov sreg, rm16) */ 84 | OT_RM16, 85 | /* Use or read a 16/32/64bit register or immediate word/dword/qword */ 86 | OT_RM_FULL, 87 | /* 88 | * 32 or 64 bits (with REX) operand size indirection memory operand. 89 | * Some instructions are promoted automatically without a REX prefix. 90 | */ 91 | OT_RM32_64, 92 | /* 16 or 32 bits RM. This is used only with MOVZXD instruction in 64bits. */ 93 | OT_RM16_32, 94 | /* Same as OT_RMXX but POINTS to 16 bits [cannot use GENERAL-PURPOSE REG!] */ 95 | OT_FPUM16, 96 | /* Same as OT_RMXX but POINTS to 32 bits (single precision) [cannot use GENERAL-PURPOSE REG!] */ 97 | OT_FPUM32, 98 | /* Same as OT_RMXX but POINTS to 64 bits (double precision) [cannot use GENERAL-PURPOSE REG!] */ 99 | OT_FPUM64, 100 | /* Same as OT_RMXX but POINTS to 80 bits (extended precision) [cannot use GENERAL-PURPOSE REG!] */ 101 | OT_FPUM80, 102 | 103 | /* 104 | * Special operand type for SSE4 where the ModR/M might 105 | * be a 32 bits register or 8 bits memory indirection operand. 106 | */ 107 | OT_R32_M8, 108 | /* 109 | * Special ModR/M for PINSRW, which need a 16 bits memory operand or 32 bits register. 110 | * In 16 bits decoding mode R32 becomes R16, operand size cannot affect this. 111 | */ 112 | OT_R32_M16, 113 | /* 114 | * Special type for SSE4, ModR/M might be a 32 bits or 64 bits (with REX) register or 115 | * a 8 bits memory indirection operand. 116 | */ 117 | OT_R32_64_M8, 118 | /* 119 | * Special type for SSE4, ModR/M might be a 32 bits or 64 bits (with REX) register or 120 | * a 16 bits memory indirection operand. 121 | */ 122 | OT_R32_64_M16, 123 | /* 124 | * Special operand type for MOV reg16/32/64/mem16, segReg 8C /r. and SMSW. 125 | * It supports all decoding modes, but if used as a memory indirection it's a 16 bit ModR/M indirection. 126 | */ 127 | OT_RFULL_M16, 128 | 129 | /* Use a control register */ 130 | OT_CREG, 131 | /* Use a debug register */ 132 | OT_DREG, 133 | /* Use a segment register */ 134 | OT_SREG, 135 | /* 136 | * SEG is encoded in the flags of the opcode itself! 137 | * This is used for specific "push SS" where SS is a segment where 138 | * each "push SS" has an absolutely different opcode byte. 139 | * We need this to detect whether an operand size prefix is used. 140 | */ 141 | OT_SEG, 142 | 143 | /* Use AL */ 144 | OT_ACC8, 145 | /* Use AX (FSTSW) */ 146 | OT_ACC16, 147 | /* Use AX/EAX/RAX */ 148 | OT_ACC_FULL, 149 | /* Use AX/EAX, no REX is possible for RAX, used only with IN/OUT which don't support 64 bit registers */ 150 | OT_ACC_FULL_NOT64, 151 | 152 | /* 153 | * Read one word (seg), and a word/dword/qword (depends on operand size) from memory. 154 | * JMP FAR [EBX] means EBX point to 16:32 ptr. 155 | */ 156 | OT_MEM16_FULL, 157 | /* Read one word (seg) and a word/dword/qword (depends on operand size), usually SEG:OFF, JMP 1234:1234 */ 158 | OT_PTR16_FULL, 159 | /* Read one word (limit) and a dword/qword (limit) (depends on operand size), used by SGDT, SIDT, LGDT, LIDT. */ 160 | OT_MEM16_3264, 161 | 162 | /* Read a byte(8 bits) immediate and calculate it relatively to the current offset of the instruction being decoded */ 163 | OT_RELCB, 164 | /* Read a word/dword immediate and calculate it relatively to the current offset of the instruction being decoded */ 165 | OT_RELC_FULL, 166 | 167 | /* Use general memory indirection, with varying sizes: */ 168 | OT_MEM, 169 | /* Used when a memory indirection is required, but if the mod field is 11, this operand will be ignored. */ 170 | OT_MEM_OPT, 171 | OT_MEM32, 172 | /* Memory dereference for MOVNTI, either 32 or 64 bits (with REX). */ 173 | OT_MEM32_64, 174 | OT_MEM64, 175 | OT_MEM128, 176 | /* Used for cmpxchg8b/16b. */ 177 | OT_MEM64_128, 178 | 179 | /* Read an immediate as an absolute address, size is known by instruction, used by MOV (memory offset) only */ 180 | OT_MOFFS8, 181 | OT_MOFFS_FULL, 182 | /* Use an immediate of 1, as for SHR R/M, 1 */ 183 | OT_CONST1, 184 | /* Use CL, as for SHR R/M, CL */ 185 | OT_REGCL, 186 | 187 | /* 188 | * Instruction-Block for one byte long instructions, used by INC/DEC/PUSH/POP/XCHG, 189 | * REG is extracted from the value of opcode 190 | * Use a 8bit register 191 | */ 192 | OT_IB_RB, 193 | /* Use a 16/32/64bit register */ 194 | OT_IB_R_FULL, 195 | 196 | /* Use [(r)SI] as INDIRECTION, for repeatable instructions */ 197 | OT_REGI_ESI, 198 | /* Use [(r)DI] as INDIRECTION, for repeatable instructions */ 199 | OT_REGI_EDI, 200 | /* Use [(r)BX + AL] as INDIRECTIOM, used by XLAT only */ 201 | OT_REGI_EBXAL, 202 | /* Use [(r)AX] as INDIRECTION, used by AMD's SVM instructions */ 203 | OT_REGI_EAX, 204 | /* Use DX, as for OUTS DX, BYTE [SI] */ 205 | OT_REGDX, 206 | /* Use ECX in INVLPGA instruction */ 207 | OT_REGECX, 208 | 209 | /* FPU registers: */ 210 | OT_FPU_SI, /* ST(i) */ 211 | OT_FPU_SSI, /* ST(0), ST(i) */ 212 | OT_FPU_SIS, /* ST(i), ST(0) */ 213 | 214 | /* MMX registers: */ 215 | OT_MM, 216 | /* Extract the MMX register from the RM bits this time (used when the REG bits are used for opcode extension) */ 217 | OT_MM_RM, 218 | /* ModR/M points to 32 bits MMX variable */ 219 | OT_MM32, 220 | /* ModR/M points to 32 bits MMX variable */ 221 | OT_MM64, 222 | 223 | /* SSE registers: */ 224 | OT_XMM, 225 | /* Extract the SSE register from the RM bits this time (used when the REG bits are used for opcode extension) */ 226 | OT_XMM_RM, 227 | /* ModR/M points to 16 bits SSE variable */ 228 | OT_XMM16, 229 | /* ModR/M points to 32 bits SSE variable */ 230 | OT_XMM32, 231 | /* ModR/M points to 64 bits SSE variable */ 232 | OT_XMM64, 233 | /* ModR/M points to 128 bits SSE variable */ 234 | OT_XMM128, 235 | /* Implied XMM0 register as operand, used in SSE4. */ 236 | OT_REGXMM0, 237 | 238 | /* AVX operands: */ 239 | 240 | /* ModR/M for 32 bits. */ 241 | OT_RM32, 242 | /* Reg32/Reg64 (prefix width) or Mem8. */ 243 | OT_REG32_64_M8, 244 | /* Reg32/Reg64 (prefix width) or Mem16. */ 245 | OT_REG32_64_M16, 246 | /* Reg32/Reg 64 depends on prefix width only. */ 247 | OT_WREG32_64, 248 | /* RM32/RM64 depends on prefix width only. */ 249 | OT_WRM32_64, 250 | /* XMM or Mem32/Mem64 depends on perfix width only. */ 251 | OT_WXMM32_64, 252 | /* XMM is encoded in VEX.VVVV. */ 253 | OT_VXMM, 254 | /* XMM is encoded in the high nibble of an immediate byte. */ 255 | OT_XMM_IMM, 256 | /* YMM/XMM is dependent on VEX.L. */ 257 | OT_YXMM, 258 | /* YMM/XMM (depends on prefix length) is encoded in the high nibble of an immediate byte. */ 259 | OT_YXMM_IMM, 260 | /* YMM is encoded in reg. */ 261 | OT_YMM, 262 | /* YMM or Mem256. */ 263 | OT_YMM256, 264 | /* YMM is encoded in VEX.VVVV. */ 265 | OT_VYMM, 266 | /* YMM/XMM is dependent on VEX.L, and encoded in VEX.VVVV. */ 267 | OT_VYXMM, 268 | /* YMM/XMM or Mem64/Mem256 is dependent on VEX.L. */ 269 | OT_YXMM64_256, 270 | /* YMM/XMM or Mem128/Mem256 is dependent on VEX.L. */ 271 | OT_YXMM128_256, 272 | /* XMM or Mem64/Mem256 is dependent on VEX.L. */ 273 | OT_LXMM64_128, 274 | /* Mem128/Mem256 is dependent on VEX.L. */ 275 | OT_LMEM128_256 276 | } _OpType; 277 | 278 | /* Flags for instruction: */ 279 | 280 | /* Empty flags indicator: */ 281 | #define INST_FLAGS_NONE (0) 282 | /* The instruction we are going to decode requires ModR/M encoding. */ 283 | #define INST_MODRM_REQUIRED (1) 284 | /* Special treatment for instructions which are in the divided-category but still needs the whole byte for ModR/M... */ 285 | #define INST_NOT_DIVIDED (1 << 1) 286 | /* 287 | * Used explicitly in repeatable instructions, 288 | * which needs a suffix letter in their mnemonic to specify operation-size (depend on operands). 289 | */ 290 | #define INST_16BITS (1 << 2) 291 | /* If the opcode is supported by 80286 and upper models (16/32 bits). */ 292 | #define INST_32BITS (1 << 3) 293 | /* 294 | * Prefix flags (6 types: lock/rep, seg override, addr-size, oper-size, REX, VEX) 295 | * There are several specific instructions that can follow LOCK prefix, 296 | * note that they must be using a memory operand form, otherwise they generate an exception. 297 | */ 298 | #define INST_PRE_LOCK (1 << 4) 299 | /* REPNZ prefix for string instructions only - means an instruction can follow it. */ 300 | #define INST_PRE_REPNZ (1 << 5) 301 | /* REP prefix for string instructions only - means an instruction can follow it. */ 302 | #define INST_PRE_REP (1 << 6) 303 | /* CS override prefix. */ 304 | #define INST_PRE_CS (1 << 7) 305 | /* SS override prefix. */ 306 | #define INST_PRE_SS (1 << 8) 307 | /* DS override prefix. */ 308 | #define INST_PRE_DS (1 << 9) 309 | /* ES override prefix. */ 310 | #define INST_PRE_ES (1 << 10) 311 | /* FS override prefix. Funky Segment :) */ 312 | #define INST_PRE_FS (1 << 11) 313 | /* GS override prefix. Groovy Segment, of course not, duh ! */ 314 | #define INST_PRE_GS (1 << 12) 315 | /* Switch operand size from 32 to 16 and vice versa. */ 316 | #define INST_PRE_OP_SIZE (1 << 13) 317 | /* Switch address size from 32 to 16 and vice versa. */ 318 | #define INST_PRE_ADDR_SIZE (1 << 14) 319 | /* Native instructions which needs suffix letter to indicate their operation-size (and don't depend on operands). */ 320 | #define INST_NATIVE (1 << 15) 321 | /* Use extended mnemonic, means it's an _InstInfoEx structure, which contains another mnemonic for 32 bits specifically. */ 322 | #define INST_USE_EXMNEMONIC (1 << 16) 323 | /* Use third operand, means it's an _InstInfoEx structure, which contains another operand for special instructions. */ 324 | #define INST_USE_OP3 (1 << 17) 325 | /* Use fourth operand, means it's an _InstInfoEx structure, which contains another operand for special instructions. */ 326 | #define INST_USE_OP4 (1 << 18) 327 | /* The instruction's mnemonic depends on the mod value of the ModR/M byte (mod=11, mod!=11). */ 328 | #define INST_MNEMONIC_MODRM_BASED (1 << 19) 329 | /* The instruction uses a ModR/M byte which the MOD must be 11 (for registers operands only). */ 330 | #define INST_MODRR_REQUIRED (1 << 20) 331 | /* The way of 3DNow! instructions are built, we have to handle their locating specially. Suffix imm8 tells which instruction it is. */ 332 | #define INST_3DNOW_FETCH (1 << 21) 333 | /* The instruction needs two suffixes, one for the comparison type (imm8) and the second for its operation size indication (second mnemonic). */ 334 | #define INST_PSEUDO_OPCODE (1 << 22) 335 | /* Invalid instruction at 64 bits decoding mode. */ 336 | #define INST_INVALID_64BITS (1 << 23) 337 | /* Specific instruction can be promoted to 64 bits (without REX, it is promoted automatically). */ 338 | #define INST_64BITS (1 << 24) 339 | /* Indicates the instruction must be REX prefixed in order to use 64 bits operands. */ 340 | #define INST_PRE_REX (1 << 25) 341 | /* Third mnemonic is set. */ 342 | #define INST_USE_EXMNEMONIC2 (1 << 26) 343 | /* Instruction is only valid in 64 bits decoding mode. */ 344 | #define INST_64BITS_FETCH (1 << 27) 345 | /* Forces that the ModRM-REG/Opcode field will be 0. (For EXTRQ). */ 346 | #define INST_FORCE_REG0 (1 << 28) 347 | /* Indicates that instruction is encoded with a VEX prefix. */ 348 | #define INST_PRE_VEX (1 << 29) 349 | /* Indicates that the instruction is encoded with a ModRM byte (REG field specifically). */ 350 | #define INST_MODRM_INCLUDED (1 << 30) 351 | /* Indicates that the first (/destination) operand of the instruction is writable. */ 352 | #define INST_DST_WR (1 << 31) 353 | 354 | #define INST_PRE_REPS (INST_PRE_REPNZ | INST_PRE_REP) 355 | #define INST_PRE_LOKREP_MASK (INST_PRE_LOCK | INST_PRE_REPNZ | INST_PRE_REP) 356 | #define INST_PRE_SEGOVRD_MASK32 (INST_PRE_CS | INST_PRE_SS | INST_PRE_DS | INST_PRE_ES) 357 | #define INST_PRE_SEGOVRD_MASK64 (INST_PRE_FS | INST_PRE_GS) 358 | #define INST_PRE_SEGOVRD_MASK (INST_PRE_SEGOVRD_MASK32 | INST_PRE_SEGOVRD_MASK64) 359 | 360 | /* Extended flags for VEX: */ 361 | /* Indicates that the instruction might have VEX.L encoded. */ 362 | #define INST_VEX_L (1) 363 | /* Indicates that the instruction might have VEX.W encoded. */ 364 | #define INST_VEX_W (1 << 1) 365 | /* Indicates that the mnemonic of the instruction is based on the VEX.W bit. */ 366 | #define INST_MNEMONIC_VEXW_BASED (1 << 2) 367 | /* Indicates that the mnemonic of the instruction is based on the VEX.L bit. */ 368 | #define INST_MNEMONIC_VEXL_BASED (1 << 3) 369 | /* Forces the instruction to be encoded with VEX.L, otherwise it's undefined. */ 370 | #define INST_FORCE_VEXL (1 << 4) 371 | /* 372 | * Indicates that the instruction is based on the MOD field of the ModRM byte. 373 | * (MOD==11: got the right instruction, else skip +4 in prefixed table for the correct instruction). 374 | */ 375 | #define INST_MODRR_BASED (1 << 5) 376 | /* Indicates that the instruction doesn't use the VVVV field of the VEX prefix, if it does then it's undecodable. */ 377 | #define INST_VEX_V_UNUSED (1 << 6) 378 | 379 | /* 380 | * Indicates which operand is being decoded. 381 | * Destination (1st), Source (2nd), op3 (3rd), op4 (4th). 382 | * Used to set the operands' fields in the _DInst structure! 383 | */ 384 | typedef enum {ONT_NONE = -1, ONT_1 = 0, ONT_2 = 1, ONT_3 = 2, ONT_4 = 3} _OperandNumberType; 385 | 386 | /* 387 | * In order to save more space for storing the DB statically, 388 | * I came up with another level of shared info. 389 | * Because I saw that most of the information that instructions use repeats itself. 390 | * 391 | * Info about the instruction, source/dest types, meta and flags. 392 | * _InstInfo points to a table of _InstSharedInfo. 393 | */ 394 | typedef struct { 395 | uint8_t flagsIndex; /* An index into FlagsTables */ 396 | uint8_t s, d; /* OpType. */ 397 | uint8_t meta; /* Hi 5 bits = Instruction set class | Lo 3 bits = flow control flags. */ 398 | /* The following are CPU flag masks that the instruction changes. */ 399 | uint8_t modifiedFlags; 400 | uint8_t testedFlags; 401 | uint8_t undefinedFlags; 402 | } _InstSharedInfo; 403 | 404 | /* 405 | * This structure is used for the instructions DB and NOT for the disassembled result code! 406 | * This is the BASE structure, there are extentions to this structure below. 407 | */ 408 | typedef struct { 409 | uint16_t sharedIndex; /* An index into the SharedInfoTable. */ 410 | uint16_t opcodeId; /* The opcodeId is really a byte-offset into the mnemonics table. */ 411 | } _InstInfo; 412 | 413 | /* 414 | * There are merely few instructions which need a second mnemonic for 32 bits. 415 | * Or a third for 64 bits. Therefore sometimes the second mnemonic is empty but not the third. 416 | * In all decoding modes the first mnemonic is the default. 417 | * A flag will indicate it uses another mnemonic. 418 | * 419 | * There are a couple of (SSE4) instructions in the whole DB which need both op3 and 3rd mnemonic for 64bits, 420 | * therefore, I decided to make the extended structure contain all extra info in the same structure. 421 | * There are a few instructions (SHLD/SHRD/IMUL and SSE too) which use third operand (or a fourth). 422 | * A flag will indicate it uses a third/fourth operand. 423 | */ 424 | typedef struct { 425 | /* Base structure (doesn't get accessed directly from code). */ 426 | _InstInfo BASE; 427 | 428 | /* Extended starts here. */ 429 | uint8_t flagsEx; /* 8 bits are enough, in the future we might make it a bigger integer. */ 430 | uint8_t op3, op4; /* OpType. */ 431 | uint16_t opcodeId2, opcodeId3; 432 | } _InstInfoEx; 433 | 434 | /* Trie data structure node type: */ 435 | typedef enum { 436 | INT_NOTEXISTS = 0, /* Not exists. */ 437 | INT_INFO = 1, /* It's an instruction info. */ 438 | INT_INFOEX, 439 | INT_LIST_GROUP, 440 | INT_LIST_FULL, 441 | INT_LIST_DIVIDED, 442 | INT_LIST_PREFIXED 443 | } _InstNodeType; 444 | 445 | /* Used to check instType < INT_INFOS, means we got an inst-info. Cause it has to be only one of them. */ 446 | #define INT_INFOS (INT_LIST_GROUP) 447 | 448 | /* Instruction node is treated as { int index:13; int type:3; } */ 449 | typedef uint16_t _InstNode; 450 | 451 | _InstInfo* inst_lookup(_CodeInfo* ci, _PrefixState* ps); 452 | _InstInfo* inst_lookup_3dnow(_CodeInfo* ci); 453 | 454 | #endif /* INSTRUCTIONS_H */ 455 | -------------------------------------------------------------------------------- /kextstat_aslr/distorm.h: -------------------------------------------------------------------------------- 1 | /* diStorm3 3.3 */ 2 | 3 | /* 4 | distorm.h 5 | 6 | diStorm3 - Powerful disassembler for X86/AMD64 7 | http://ragestorm.net/distorm/ 8 | distorm at gmail dot com 9 | Copyright (C) 2003-2012 Gil Dabah 10 | 11 | This program is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program. If not, see 23 | */ 24 | 25 | 26 | #ifndef DISTORM_H 27 | #define DISTORM_H 28 | 29 | /* 30 | * 64 bit offsets support: 31 | * If the diStorm library you use was compiled with 64 bits offsets, 32 | * make sure you compile your own code with the following macro set: 33 | * SUPPORT_64BIT_OFFSET 34 | * Otherwise comment it out, or you will get a linker error of an unresolved symbol... 35 | * Turned on by default! 36 | */ 37 | 38 | #if !(defined(DISTORM_STATIC) || defined(DISTORM_DYNAMIC)) 39 | /* Define this macro for outer projects by default. */ 40 | #define SUPPORT_64BIT_OFFSET 41 | #endif 42 | 43 | /* TINYC has a problem with some 64bits library functions, so ignore 64 bit offsets. */ 44 | #ifdef __TINYC__ 45 | #undef SUPPORT_64BIT_OFFSET 46 | #endif 47 | 48 | /* If your compiler doesn't support stdint.h, define your own 64 bits type. */ 49 | #ifdef SUPPORT_64BIT_OFFSET 50 | #ifdef _MSC_VER 51 | #define OFFSET_INTEGER unsigned __int64 52 | #else 53 | #include 54 | #define OFFSET_INTEGER uint64_t 55 | #endif 56 | #else 57 | /* 32 bit offsets are used. */ 58 | #define OFFSET_INTEGER unsigned long 59 | #endif 60 | 61 | #ifdef _MSC_VER 62 | /* Since MSVC isn't shipped with stdint.h, we will have our own: */ 63 | typedef signed __int64 int64_t; 64 | typedef unsigned __int64 uint64_t; 65 | typedef signed __int32 int32_t; 66 | typedef unsigned __int32 uint32_t; 67 | typedef signed __int16 int16_t; 68 | typedef unsigned __int16 uint16_t; 69 | typedef signed __int8 int8_t; 70 | typedef unsigned __int8 uint8_t; 71 | #endif 72 | 73 | /* Support C++ compilers */ 74 | #ifdef __cplusplus 75 | extern "C" { 76 | #endif 77 | 78 | 79 | /* *** Helper Macros *** */ 80 | 81 | /* Get the ISC of the instruction, used with the definitions below. */ 82 | #define META_GET_ISC(meta) (((meta) >> 3) & 0x1f) 83 | #define META_SET_ISC(di, isc) (((di)->meta) |= ((isc) << 3)) 84 | /* Get the flow control flags of the instruction, see 'features for decompose' below. */ 85 | #define META_GET_FC(meta) ((meta) & 0x7) 86 | 87 | /* Get the target address of a branching instruction. O_PC operand type. */ 88 | #define INSTRUCTION_GET_TARGET(di) ((_OffsetType)(((di)->addr + (di)->imm.addr + (di)->size))) 89 | /* Get the target address of a RIP-relative memory indirection. */ 90 | #define INSTRUCTION_GET_RIP_TARGET(di) ((_OffsetType)(((di)->addr + (di)->disp + (di)->size))) 91 | 92 | /* 93 | * Operand Size or Adderss size are stored inside the flags: 94 | * 0 - 16 bits 95 | * 1 - 32 bits 96 | * 2 - 64 bits 97 | * 3 - reserved 98 | * 99 | * If you call these set-macros more than once, you will have to clean the bits before doing so. 100 | */ 101 | #define FLAG_SET_OPSIZE(di, size) ((di->flags) |= (((size) & 3) << 8)) 102 | #define FLAG_SET_ADDRSIZE(di, size) ((di->flags) |= (((size) & 3) << 10)) 103 | #define FLAG_GET_OPSIZE(flags) (((flags) >> 8) & 3) 104 | #define FLAG_GET_ADDRSIZE(flags) (((flags) >> 10) & 3) 105 | /* To get the LOCK/REPNZ/REP prefixes. */ 106 | #define FLAG_GET_PREFIX(flags) ((flags) & 7) 107 | 108 | /* 109 | * Macros to extract segment registers from 'segment': 110 | */ 111 | #define SEGMENT_DEFAULT 0x80 112 | #define SEGMENT_SET(di, seg) ((di->segment) |= seg) 113 | #define SEGMENT_GET(segment) (((segment) == R_NONE) ? R_NONE : ((segment) & 0x7f)) 114 | #define SEGMENT_IS_DEFAULT(segment) (((segment) & SEGMENT_DEFAULT) == SEGMENT_DEFAULT) 115 | 116 | 117 | /* Decodes modes of the disassembler, 16 bits or 32 bits or 64 bits for AMD64, x86-64. */ 118 | typedef enum { Decode16Bits = 0, Decode32Bits = 1, Decode64Bits = 2 } _DecodeType; 119 | 120 | typedef OFFSET_INTEGER _OffsetType; 121 | 122 | typedef struct { 123 | _OffsetType codeOffset, nextOffset; /* nextOffset is OUT only. */ 124 | const uint8_t* code; 125 | int codeLen; /* Using signed integer makes it easier to detect an underflow. */ 126 | _DecodeType dt; 127 | unsigned int features; 128 | } _CodeInfo; 129 | 130 | typedef enum { O_NONE, O_REG, O_IMM, O_IMM1, O_IMM2, O_DISP, O_SMEM, O_MEM, O_PC, O_PTR } _OperandType; 131 | 132 | typedef union { 133 | /* Used by O_IMM: */ 134 | int8_t sbyte; 135 | uint8_t byte; 136 | int16_t sword; 137 | uint16_t word; 138 | int32_t sdword; 139 | uint32_t dword; 140 | int64_t sqword; /* All immediates are SIGN-EXTENDED to 64 bits! */ 141 | uint64_t qword; 142 | 143 | /* Used by O_PC: (Use GET_TARGET_ADDR).*/ 144 | _OffsetType addr; /* It's a relative offset as for now. */ 145 | 146 | /* Used by O_PTR: */ 147 | struct { 148 | uint16_t seg; 149 | /* Can be 16 or 32 bits, size is in ops[n].size. */ 150 | uint32_t off; 151 | } ptr; 152 | 153 | /* Used by O_IMM1 (i1) and O_IMM2 (i2). ENTER instruction only. */ 154 | struct { 155 | uint32_t i1; 156 | uint32_t i2; 157 | } ex; 158 | } _Value; 159 | 160 | typedef struct { 161 | /* Type of operand: 162 | O_NONE: operand is to be ignored. 163 | O_REG: index holds global register index. 164 | O_IMM: instruction.imm. 165 | O_IMM1: instruction.imm.ex.i1. 166 | O_IMM2: instruction.imm.ex.i2. 167 | O_DISP: memory dereference with displacement only, instruction.disp. 168 | O_SMEM: simple memory dereference with optional displacement (a single register memory dereference). 169 | O_MEM: complex memory dereference (optional fields: s/i/b/disp). 170 | O_PC: the relative address of a branch instruction (instruction.imm.addr). 171 | O_PTR: the absolute target address of a far branch instruction (instruction.imm.ptr.seg/off). 172 | */ 173 | uint8_t type; /* _OperandType */ 174 | 175 | /* Index of: 176 | O_REG: holds global register index 177 | O_SMEM: holds the 'base' register. E.G: [ECX], [EBX+0x1234] are both in operand.index. 178 | O_MEM: holds the 'index' register. E.G: [EAX*4] is in operand.index. 179 | */ 180 | uint8_t index; 181 | 182 | /* Size of: 183 | O_REG: register 184 | O_IMM: instruction.imm 185 | O_IMM1: instruction.imm.ex.i1 186 | O_IMM2: instruction.imm.ex.i2 187 | O_DISP: instruction.disp 188 | O_SMEM: size of indirection. 189 | O_MEM: size of indirection. 190 | O_PC: size of the relative offset 191 | O_PTR: size of instruction.imm.ptr.off (16 or 32) 192 | */ 193 | uint16_t size; 194 | } _Operand; 195 | 196 | #define OPCODE_ID_NONE 0 197 | /* Instruction could not be disassembled. */ 198 | #define FLAG_NOT_DECODABLE ((uint16_t)-1) 199 | /* The instruction locks memory access. */ 200 | #define FLAG_LOCK (1 << 0) 201 | /* The instruction is prefixed with a REPNZ. */ 202 | #define FLAG_REPNZ (1 << 1) 203 | /* The instruction is prefixed with a REP, this can be a REPZ, it depends on the specific instruction. */ 204 | #define FLAG_REP (1 << 2) 205 | /* Indicates there is a hint taken for Jcc instructions only. */ 206 | #define FLAG_HINT_TAKEN (1 << 3) 207 | /* Indicates there is a hint non-taken for Jcc instructions only. */ 208 | #define FLAG_HINT_NOT_TAKEN (1 << 4) 209 | /* The Imm value is signed extended. */ 210 | #define FLAG_IMM_SIGNED (1 << 5) 211 | /* The destination operand is writable. */ 212 | #define FLAG_DST_WR (1 << 6) 213 | /* The instruction uses RIP-relative indirection. */ 214 | #define FLAG_RIP_RELATIVE (1 << 7) 215 | 216 | /* No register was defined. */ 217 | #define R_NONE ((uint8_t)-1) 218 | 219 | #define REGS64_BASE 0 220 | #define REGS32_BASE 16 221 | #define REGS16_BASE 32 222 | #define REGS8_BASE 48 223 | #define REGS8_REX_BASE 64 224 | #define SREGS_BASE 68 225 | #define FPUREGS_BASE 75 226 | #define MMXREGS_BASE 83 227 | #define SSEREGS_BASE 91 228 | #define AVXREGS_BASE 107 229 | #define CREGS_BASE 123 230 | #define DREGS_BASE 132 231 | 232 | #define OPERANDS_NO (4) 233 | 234 | typedef struct { 235 | /* Used by ops[n].type == O_IMM/O_IMM1&O_IMM2/O_PTR/O_PC. Its size is ops[n].size. */ 236 | _Value imm; 237 | /* Used by ops[n].type == O_SMEM/O_MEM/O_DISP. Its size is dispSize. */ 238 | uint64_t disp; 239 | /* Virtual address of first byte of instruction. */ 240 | _OffsetType addr; 241 | /* General flags of instruction, holds prefixes and more, if FLAG_NOT_DECODABLE, instruction is invalid. */ 242 | uint16_t flags; 243 | /* Unused prefixes mask, for each bit that is set that prefix is not used (LSB is byte [addr + 0]). */ 244 | uint16_t unusedPrefixesMask; 245 | /* Mask of registers that were used in the operands, only used for quick look up, in order to know *some* operand uses that register class. */ 246 | uint16_t usedRegistersMask; 247 | /* ID of opcode in the global opcode table. Use for mnemonic look up. */ 248 | uint16_t opcode; 249 | /* Up to four operands per instruction, ignored if ops[n].type == O_NONE. */ 250 | _Operand ops[OPERANDS_NO]; 251 | /* Size of the whole instruction. */ 252 | uint8_t size; 253 | /* Segment information of memory indirection, default segment, or overriden one, can be -1. Use SEGMENT macros. */ 254 | uint8_t segment; 255 | /* Used by ops[n].type == O_MEM. Base global register index (might be R_NONE), scale size (2/4/8), ignored for 0 or 1. */ 256 | uint8_t base, scale; 257 | uint8_t dispSize; 258 | /* Meta defines the instruction set class, and the flow control flags. Use META macros. */ 259 | uint8_t meta; 260 | /* The CPU flags that the instruction operates upon. */ 261 | uint8_t modifiedFlagsMask, testedFlagsMask, undefinedFlagsMask; 262 | } _DInst; 263 | 264 | #ifndef DISTORM_LIGHT 265 | 266 | /* Static size of strings. Do not change this value. Keep Python wrapper in sync. */ 267 | #define MAX_TEXT_SIZE (48) 268 | typedef struct { 269 | unsigned int length; 270 | unsigned char p[MAX_TEXT_SIZE]; /* p is a null terminated string. */ 271 | } _WString; 272 | 273 | /* 274 | * Old decoded instruction structure in text format. 275 | * Used only for backward compatibility with diStorm64. 276 | * This structure holds all information the disassembler generates per instruction. 277 | */ 278 | typedef struct { 279 | _WString mnemonic; /* Mnemonic of decoded instruction, prefixed if required by REP, LOCK etc. */ 280 | _WString operands; /* Operands of the decoded instruction, up to 3 operands, comma-seperated. */ 281 | _WString instructionHex; /* Hex dump - little endian, including prefixes. */ 282 | unsigned int size; /* Size of decoded instruction. */ 283 | _OffsetType offset; /* Start offset of the decoded instruction. */ 284 | } _DecodedInst; 285 | 286 | #endif /* DISTORM_LIGHT */ 287 | 288 | /* Register masks for quick look up, each mask indicates one of a register-class that is being used in some operand. */ 289 | #define RM_AX 1 /* AL, AH, AX, EAX, RAX */ 290 | #define RM_CX 2 /* CL, CH, CX, ECX, RCX */ 291 | #define RM_DX 4 /* DL, DH, DX, EDX, RDX */ 292 | #define RM_BX 8 /* BL, BH, BX, EBX, RBX */ 293 | #define RM_SP 0x10 /* SPL, SP, ESP, RSP */ 294 | #define RM_BP 0x20 /* BPL, BP, EBP, RBP */ 295 | #define RM_SI 0x40 /* SIL, SI, ESI, RSI */ 296 | #define RM_DI 0x80 /* DIL, DI, EDI, RDI */ 297 | #define RM_FPU 0x100 /* ST(0) - ST(7) */ 298 | #define RM_MMX 0x200 /* MM0 - MM7 */ 299 | #define RM_SSE 0x400 /* XMM0 - XMM15 */ 300 | #define RM_AVX 0x800 /* YMM0 - YMM15 */ 301 | #define RM_CR 0x1000 /* CR0, CR2, CR3, CR4, CR8 */ 302 | #define RM_DR 0x2000 /* DR0, DR1, DR2, DR3, DR6, DR7 */ 303 | /* RIP should be checked using the 'flags' field and FLAG_RIP_RELATIVE. 304 | * Segments should be checked using the segment macros. 305 | * For now R8 - R15 are not supported and non general purpose registers map into same RM. 306 | */ 307 | 308 | /* CPU Flags that instructions modify, test or undefine. */ 309 | #define D_ZF 1 /* Zero */ 310 | #define D_SF 2 /* Sign */ 311 | #define D_CF 4 /* Carry */ 312 | #define D_OF 8 /* Overflow */ 313 | #define D_PF 0x10 /* Parity */ 314 | #define D_AF 0x20 /* Auxilary */ 315 | #define D_DF 0x40 /* Direction */ 316 | #define D_IF 0x80 /* Interrupt */ 317 | 318 | /* 319 | * Instructions Set classes: 320 | * if you want a better understanding of the available classes, look at disOps project, file: x86sets.py. 321 | */ 322 | /* Indicates the instruction belongs to the General Integer set. */ 323 | #define ISC_INTEGER 1 324 | /* Indicates the instruction belongs to the 387 FPU set. */ 325 | #define ISC_FPU 2 326 | /* Indicates the instruction belongs to the P6 set. */ 327 | #define ISC_P6 3 328 | /* Indicates the instruction belongs to the MMX set. */ 329 | #define ISC_MMX 4 330 | /* Indicates the instruction belongs to the SSE set. */ 331 | #define ISC_SSE 5 332 | /* Indicates the instruction belongs to the SSE2 set. */ 333 | #define ISC_SSE2 6 334 | /* Indicates the instruction belongs to the SSE3 set. */ 335 | #define ISC_SSE3 7 336 | /* Indicates the instruction belongs to the SSSE3 set. */ 337 | #define ISC_SSSE3 8 338 | /* Indicates the instruction belongs to the SSE4.1 set. */ 339 | #define ISC_SSE4_1 9 340 | /* Indicates the instruction belongs to the SSE4.2 set. */ 341 | #define ISC_SSE4_2 10 342 | /* Indicates the instruction belongs to the AMD's SSE4.A set. */ 343 | #define ISC_SSE4_A 11 344 | /* Indicates the instruction belongs to the 3DNow! set. */ 345 | #define ISC_3DNOW 12 346 | /* Indicates the instruction belongs to the 3DNow! Extensions set. */ 347 | #define ISC_3DNOWEXT 13 348 | /* Indicates the instruction belongs to the VMX (Intel) set. */ 349 | #define ISC_VMX 14 350 | /* Indicates the instruction belongs to the SVM (AMD) set. */ 351 | #define ISC_SVM 15 352 | /* Indicates the instruction belongs to the AVX (Intel) set. */ 353 | #define ISC_AVX 16 354 | /* Indicates the instruction belongs to the FMA (Intel) set. */ 355 | #define ISC_FMA 17 356 | /* Indicates the instruction belongs to the AES/AVX (Intel) set. */ 357 | #define ISC_AES 18 358 | /* Indicates the instruction belongs to the CLMUL (Intel) set. */ 359 | #define ISC_CLMUL 19 360 | 361 | /* Features for decompose: */ 362 | #define DF_NONE 0 363 | /* The decoder will limit addresses to a maximum of 16 bits. */ 364 | #define DF_MAXIMUM_ADDR16 1 365 | /* The decoder will limit addresses to a maximum of 32 bits. */ 366 | #define DF_MAXIMUM_ADDR32 2 367 | /* The decoder will return only flow control instructions (and filter the others internally). */ 368 | #define DF_RETURN_FC_ONLY 4 369 | /* The decoder will stop and return to the caller when the instruction 'CALL' (near and far) was decoded. */ 370 | #define DF_STOP_ON_CALL 8 371 | /* The decoder will stop and return to the caller when the instruction 'RET' (near and far) was decoded. */ 372 | #define DF_STOP_ON_RET 0x10 373 | /* The decoder will stop and return to the caller when the instruction system-call/ret was decoded. */ 374 | #define DF_STOP_ON_SYS 0x20 375 | /* The decoder will stop and return to the caller when any of the branch 'JMP', (near and far) instructions were decoded. */ 376 | #define DF_STOP_ON_UNC_BRANCH 0x40 377 | /* The decoder will stop and return to the caller when any of the conditional branch instruction were decoded. */ 378 | #define DF_STOP_ON_CND_BRANCH 0x80 379 | /* The decoder will stop and return to the caller when the instruction 'INT' (INT, INT1, INTO, INT 3) was decoded. */ 380 | #define DF_STOP_ON_INT 0x100 381 | /* The decoder will stop and return to the caller when any of the 'CMOVxx' instruction was decoded. */ 382 | #define DF_STOP_ON_CMOV 0x200 383 | /* The decoder will stop and return to the caller when any flow control instruction was decoded. */ 384 | #define DF_STOP_ON_FLOW_CONTROL (DF_STOP_ON_CALL | DF_STOP_ON_RET | DF_STOP_ON_SYS | DF_STOP_ON_UNC_BRANCH | DF_STOP_ON_CND_BRANCH | DF_STOP_ON_INT | DF_STOP_ON_CMOV) 385 | 386 | /* Indicates the instruction is not a flow-control instruction. */ 387 | #define FC_NONE 0 388 | /* Indicates the instruction is one of: CALL, CALL FAR. */ 389 | #define FC_CALL 1 390 | /* Indicates the instruction is one of: RET, IRET, RETF. */ 391 | #define FC_RET 2 392 | /* Indicates the instruction is one of: SYSCALL, SYSRET, SYSENTER, SYSEXIT. */ 393 | #define FC_SYS 3 394 | /* Indicates the instruction is one of: JMP, JMP FAR. */ 395 | #define FC_UNC_BRANCH 4 396 | /* 397 | * Indicates the instruction is one of: 398 | * JCXZ, JO, JNO, JB, JAE, JZ, JNZ, JBE, JA, JS, JNS, JP, JNP, JL, JGE, JLE, JG, LOOP, LOOPZ, LOOPNZ. 399 | */ 400 | #define FC_CND_BRANCH 5 401 | /* Indiciates the instruction is one of: INT, INT1, INT 3, INTO, UD2. */ 402 | #define FC_INT 6 403 | /* Indicates the instruction is one of: CMOVxx. */ 404 | #define FC_CMOV 7 405 | 406 | /* Return code of the decoding function. */ 407 | typedef enum { DECRES_NONE, DECRES_SUCCESS, DECRES_MEMORYERR, DECRES_INPUTERR, DECRES_FILTERED } _DecodeResult; 408 | 409 | /* Define the following interface functions only for outer projects. */ 410 | #if !(defined(DISTORM_STATIC) || defined(DISTORM_DYNAMIC)) 411 | 412 | /* distorm_decode 413 | * Input: 414 | * offset - Origin of the given code (virtual address that is), NOT an offset in code. 415 | * code - Pointer to the code buffer to be disassembled. 416 | * length - Amount of bytes that should be decoded from the code buffer. 417 | * dt - Decoding mode, 16 bits (Decode16Bits), 32 bits (Decode32Bits) or AMD64 (Decode64Bits). 418 | * result - Array of type _DecodeInst which will be used by this function in order to return the disassembled instructions. 419 | * maxInstructions - The maximum number of entries in the result array that you pass to this function, so it won't exceed its bound. 420 | * usedInstructionsCount - Number of the instruction that successfully were disassembled and written to the result array. 421 | * Output: usedInstructionsCount will hold the number of entries used in the result array 422 | * and the result array itself will be filled with the disassembled instructions. 423 | * Return: DECRES_SUCCESS on success (no more to disassemble), DECRES_INPUTERR on input error (null code buffer, invalid decoding mode, etc...), 424 | * DECRES_MEMORYERR when there are not enough entries to use in the result array, BUT YOU STILL have to check for usedInstructionsCount! 425 | * Side-Effects: Even if the return code is DECRES_MEMORYERR, there might STILL be data in the 426 | * array you passed, this function will try to use as much entries as possible! 427 | * Notes: 1)The minimal size of maxInstructions is 15. 428 | * 2)You will have to synchronize the offset,code and length by yourself if you pass code fragments and not a complete code block! 429 | */ 430 | #ifdef SUPPORT_64BIT_OFFSET 431 | 432 | _DecodeResult distorm_decompose64(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); 433 | #define distorm_decompose distorm_decompose64 434 | 435 | #ifndef DISTORM_LIGHT 436 | /* If distorm-light is defined, we won't export these text-formatting functionality. */ 437 | _DecodeResult distorm_decode64(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); 438 | void distorm_format64(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result); 439 | #define distorm_decode distorm_decode64 440 | #define distorm_format distorm_format64 441 | #endif /*DISTORM_LIGHT*/ 442 | 443 | #else /*SUPPORT_64BIT_OFFSET*/ 444 | 445 | _DecodeResult distorm_decompose32(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); 446 | #define distorm_decompose distorm_decompose32 447 | 448 | #ifndef DISTORM_LIGHT 449 | /* If distorm-light is defined, we won't export these text-formatting functionality. */ 450 | _DecodeResult distorm_decode32(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); 451 | void distorm_format32(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result); 452 | #define distorm_decode distorm_decode32 453 | #define distorm_format distorm_format32 454 | #endif /*DISTORM_LIGHT*/ 455 | 456 | #endif 457 | 458 | /* 459 | * distorm_version 460 | * Input: 461 | * none 462 | * 463 | * Output: unsigned int - version of compiled library. 464 | */ 465 | unsigned int distorm_version(); 466 | 467 | #endif /* DISTORM_STATIC */ 468 | 469 | #ifdef __cplusplus 470 | } /* End Of Extern */ 471 | #endif 472 | 473 | #endif /* DISTORM_H */ 474 | -------------------------------------------------------------------------------- /kextstat_aslr/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * _____ _____ 3 | * __| __ |__ ______ __ __ __ __|_ |__ ______ ____ _____ 4 | * | |/ / || ___| \ ` / _| |_ | \ || ___|| | | | 5 | * | \ || ___| / \|_ _|| \ | `-.`-. | |_ | \ 6 | * |__|\__\ __||______|/__/\_\ |__| |__|\__\ __||______||______||__|\__\ 7 | * |_____| |_____| 8 | * 9 | * Kextstat ASLR 10 | * 11 | * A small util to list kernel extensions with true address in Mountain Lion due to KASLR 12 | * 13 | * (c) fG!, 2012, 2013, 2014 - reverser@put.as - http://reverse.put.as 14 | * 15 | * Note: This requires kmem/mem devices to be enabled 16 | * Edit /Library/Preferences/SystemConfiguration/com.apple.Boot.plist 17 | * add kmem=1 parameter, and reboot! 18 | * 19 | * v0.1 - Initial version 20 | * v0.2 - Retrieve kaslr slide via kas_info() syscall. Thanks to posixninja for the tip :-) 21 | * v0.3 - Cleanups 22 | * v1.0 - Use diStorm to find sLoadedKexts so everything is dynamic 23 | * The only dependency is on OSArray class, since we are using fixed offsets 24 | * v1.1 - Try to use processor_set_tasks() vulnerability to read kernel memory 25 | * before trying to use /dev/kmem 26 | * 27 | * You will need to supply sLoadedKexts symbol, which is not exported. 28 | * Disassemble the kernel and go to this method OSKext::lookupKextWithLoadTag 29 | * The pointer address to sLoadedKexts is moved to RDI after the call to IORecursiveLockLock 30 | * 31 | * This program is free software: you can redistribute it and/or modify 32 | * it under the terms of the GNU General Public License as published by 33 | * the Free Software Foundation, either version 3 of the License, or 34 | * (at your option) any later version. 35 | * 36 | * This program is distributed in the hope that it will be useful, 37 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 38 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 39 | * GNU General Public License for more details. 40 | * 41 | * You should have received a copy of the GNU General Public License 42 | * along with this program. If not, see 43 | * 44 | */ 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | 67 | #include "distorm.h" 68 | #include "mnemonics.h" 69 | 70 | #define VERSION "1.1" 71 | 72 | #define LOOKUPKEXTWITHLOADTAG "__ZN6OSKext21lookupKextWithLoadTagEj" // OSKext::lookupKextWithLoadTag symbol 73 | #define KMOD_MAX_NAME 64 74 | #define DISASM_SIZE 1024 75 | 76 | #define ERROR_MSG(fmt, ...) fprintf(stderr, "[ERROR] " fmt " \n", ## __VA_ARGS__) 77 | #define OUTPUT_MSG(fmt, ...) fprintf(stdout, fmt " \n", ## __VA_ARGS__) 78 | #if DEBUG == 0 79 | # define DEBUG_MSG(fmt, ...) do {} while (0) 80 | #else 81 | # define DEBUG_MSG(fmt, ...) fprintf(stdout, "[DEBUG] " fmt "\n", ## __VA_ARGS__) 82 | #endif 83 | 84 | struct kernel_info 85 | { 86 | uint64_t linkedit_fileoff; 87 | uint64_t linkedit_size; 88 | uint32_t symboltable_fileoff; 89 | uint32_t symboltable_nr_symbols; 90 | uint32_t stringtable_fileoff; 91 | uint32_t stringtable_size; 92 | void *linkedit_buf; // pointer to __LINKEDIT area 93 | uint64_t kaslr_slide; 94 | }; 95 | 96 | struct mem_source 97 | { 98 | int fd; 99 | mach_port_t kernel_port; 100 | } g_kmem_source; 101 | 102 | // from xnu/bsd/sys/kas_info.h 103 | #define KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR (0) /* returns uint64_t */ 104 | #define KAS_INFO_MAX_SELECTOR (1) 105 | int kas_info(int selector, void *value, size_t *size); 106 | 107 | // prototypes 108 | void header(void); 109 | void usage(void); 110 | static int readkmem(void *buffer, const uint64_t offset, const size_t size); 111 | static kern_return_t process_kernel_mach_header(const void *kernel_buffer, struct kernel_info *kinfo); 112 | static uint64_t read_target(uint8_t **targetBuffer, const char *target); 113 | static mach_vm_address_t find_sloadedkexts(uint8_t *buffer, int32_t buffer_size, mach_vm_address_t offset_addr, mach_vm_address_t iorecursivelocklock); 114 | 115 | #pragma mark Functions to read from kernel memory and file system 116 | 117 | static int 118 | readkmem(void *buffer, const uint64_t target_addr, const size_t size) 119 | { 120 | if (g_kmem_source.kernel_port != 0) 121 | { 122 | mach_vm_size_t outsize = 0; 123 | kern_return_t kr = mach_vm_read_overwrite(g_kmem_source.kernel_port, target_addr, size, (mach_vm_address_t)buffer, &outsize); 124 | if (kr != KERN_SUCCESS) 125 | { 126 | ERROR_MSG("mach_vm_read_overwrite failed: %d.", kr); 127 | return -2; 128 | } 129 | } 130 | else if (g_kmem_source.fd != 0) 131 | { 132 | if(lseek(g_kmem_source.fd, target_addr, SEEK_SET) != (off_t)target_addr) 133 | { 134 | ERROR_MSG("Error in lseek. Are you root?"); 135 | return -1; 136 | } 137 | 138 | ssize_t bytes_read = read(g_kmem_source.fd, buffer, size); 139 | if(bytes_read != size) 140 | { 141 | ERROR_MSG("Error while trying to read from kmem. Asked %ld bytes from offset %llx, returned %ld.", size, target_addr, bytes_read); 142 | return -2; 143 | } 144 | } 145 | return 0; 146 | } 147 | 148 | /* 149 | * read the target file into a buffer 150 | */ 151 | static uint64_t 152 | read_target(uint8_t **targetBuffer, const char *target) 153 | { 154 | FILE *in_file = NULL; 155 | 156 | in_file = fopen(target, "r"); 157 | if (!in_file) 158 | { 159 | ERROR_MSG("Could not open target file %s!", target); 160 | exit(-1); 161 | } 162 | if (fseek(in_file, 0, SEEK_END)) 163 | { 164 | ERROR_MSG("Fseek failed at %s", target); 165 | exit(-1); 166 | } 167 | 168 | long fileSize = ftell(in_file); 169 | 170 | if (fseek(in_file, 0, SEEK_SET)) 171 | { 172 | ERROR_MSG("Fseek failed at %s", target); 173 | exit(-1); 174 | } 175 | 176 | *targetBuffer = malloc(fileSize * sizeof(uint8_t)); 177 | 178 | if (*targetBuffer == NULL) 179 | { 180 | ERROR_MSG("Malloc failed!"); 181 | exit(-1); 182 | } 183 | 184 | fread(*targetBuffer, fileSize, 1, in_file); 185 | if (ferror(in_file)) 186 | { 187 | ERROR_MSG("fread failed at %s", target); 188 | free(*targetBuffer); 189 | exit(-1); 190 | } 191 | fclose(in_file); 192 | return(fileSize); 193 | } 194 | 195 | #pragma mark Header and help functions 196 | 197 | void 198 | usage(void) 199 | { 200 | OUTPUT_MSG("kextstat_aslr"); 201 | exit(-1); 202 | } 203 | 204 | void 205 | header(void) 206 | { 207 | OUTPUT_MSG(" _____ _ _____ _"); 208 | OUTPUT_MSG("| | |___ _ _| |_| _ |___| |___"); 209 | OUTPUT_MSG("| -| -_|_'_| _| |_ -| | _|"); 210 | OUTPUT_MSG("|__|__|___|_,_|_| |__|__|___|_|_|"); 211 | OUTPUT_MSG(" KextASLR v%s - (c) fG!",VERSION); 212 | OUTPUT_MSG("-----------------------------------"); 213 | } 214 | 215 | 216 | /* 217 | * lame inline asm to use the kas_info() syscall. beware the difference if we want 64bits syscalls! 218 | */ 219 | void 220 | get_kaslr_slide(size_t *size, uint64_t *slide) 221 | { 222 | // this is needed for 64bits syscalls!!! 223 | // good post about it http://thexploit.com/secdev/mac-os-x-64-bit-assembly-system-calls/ 224 | #define SYSCALL_CLASS_SHIFT 24 225 | #define SYSCALL_CLASS_MASK (0xFF << SYSCALL_CLASS_SHIFT) 226 | #define SYSCALL_NUMBER_MASK (~SYSCALL_CLASS_MASK) 227 | #define SYSCALL_CLASS_UNIX 2 228 | #define SYSCALL_CONSTRUCT_UNIX(syscall_number) \ 229 | ((SYSCALL_CLASS_UNIX << SYSCALL_CLASS_SHIFT) | \ 230 | (SYSCALL_NUMBER_MASK & (syscall_number))) 231 | 232 | uint64_t syscallnr = SYSCALL_CONSTRUCT_UNIX(SYS_kas_info); 233 | uint64_t selector = KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR; 234 | int result = 0; 235 | __asm__ ("movq %1, %%rdi\n\t" 236 | "movq %2, %%rsi\n\t" 237 | "movq %3, %%rdx\n\t" 238 | "movq %4, %%rax\n\t" 239 | "syscall" 240 | : "=a" (result) 241 | : "r" (selector), "m" (slide), "m" (size), "a" (syscallnr) 242 | : "rdi", "rsi", "rdx", "rax" 243 | ); 244 | } 245 | 246 | #pragma mark Mach-O header and symbol related functions 247 | 248 | /* 249 | * retrieve necessary mach-o header information from the kernel buffer 250 | * results stored in kernel_info structure 251 | */ 252 | static kern_return_t 253 | process_kernel_mach_header(const void *kernel_buffer, struct kernel_info *kinfo) 254 | { 255 | struct mach_header_64 *mh = (struct mach_header_64*)kernel_buffer; 256 | // test if it's a valid mach-o header (or appears to be) 257 | if (mh->magic != MH_MAGIC_64) return KERN_FAILURE; 258 | 259 | struct load_command *load_cmd = NULL; 260 | // point to the first load command 261 | char *load_cmd_addr = (char*)kernel_buffer + sizeof(struct mach_header_64); 262 | // iterate over all load cmds and retrieve required info to solve symbols 263 | // __LINKEDIT location and symbol/string table location 264 | for (uint32_t i = 0; i < mh->ncmds; i++) 265 | { 266 | load_cmd = (struct load_command*)load_cmd_addr; 267 | if (load_cmd->cmd == LC_SEGMENT_64) 268 | { 269 | struct segment_command_64 *seg_cmd = (struct segment_command_64*)load_cmd; 270 | if (strncmp(seg_cmd->segname, "__LINKEDIT", 16) == 0) 271 | { 272 | kinfo->linkedit_fileoff = seg_cmd->fileoff; 273 | kinfo->linkedit_size = seg_cmd->filesize; 274 | } 275 | } 276 | // table information available at LC_SYMTAB command 277 | else if (load_cmd->cmd == LC_SYMTAB) 278 | { 279 | struct symtab_command *symtab_cmd = (struct symtab_command*)load_cmd; 280 | kinfo->symboltable_fileoff = symtab_cmd->symoff; 281 | kinfo->symboltable_nr_symbols = symtab_cmd->nsyms; 282 | kinfo->stringtable_fileoff = symtab_cmd->stroff; 283 | kinfo->stringtable_size = symtab_cmd->strsize; 284 | } 285 | load_cmd_addr += load_cmd->cmdsize; 286 | } 287 | return KERN_SUCCESS; 288 | } 289 | 290 | /* 291 | * function to solve a kernel symbol 292 | */ 293 | mach_vm_address_t 294 | solve_kernel_symbol(struct kernel_info *kinfo, char *symbol_to_solve) 295 | { 296 | struct nlist_64 *nlist = NULL; 297 | 298 | if (kinfo == NULL || kinfo->linkedit_buf == NULL) return 0; 299 | 300 | for (uint32_t i = 0; i < kinfo->symboltable_nr_symbols; i++) 301 | { 302 | // symbols and strings offsets into LINKEDIT 303 | mach_vm_address_t symbol_off = kinfo->symboltable_fileoff - kinfo->linkedit_fileoff; 304 | mach_vm_address_t string_off = kinfo->stringtable_fileoff - kinfo->linkedit_fileoff; 305 | 306 | nlist = (struct nlist_64*)((char*)kinfo->linkedit_buf + symbol_off + i * sizeof(struct nlist_64)); 307 | char *symbol_string = ((char*)kinfo->linkedit_buf + string_off + nlist->n_un.n_strx); 308 | // find if symbol matches 309 | if (strncmp(symbol_to_solve, symbol_string, strlen(symbol_to_solve)) == 0) 310 | { 311 | OUTPUT_MSG("[INFO] found symbol %s at %p (with ASLR: %p)", symbol_to_solve, (void*)nlist->n_value, (void*)(nlist->n_value + kinfo->kaslr_slide)); 312 | // the symbols are without kernel ASLR so we need to add it 313 | return (nlist->n_value + kinfo->kaslr_slide); 314 | } 315 | } 316 | // failure 317 | return 0; 318 | } 319 | 320 | /* 321 | * disassemble the function and lookup for sLoadedKexts 322 | * the format is like this: 323 | __text:FFFFFF80005F7090 55 push rbp 324 | __text:FFFFFF80005F7091 48 89 E5 mov rbp, rsp 325 | __text:FFFFFF80005F7094 41 57 push r15 326 | __text:FFFFFF80005F7096 41 56 push r14 327 | __text:FFFFFF80005F7098 41 55 push r13 328 | __text:FFFFFF80005F709A 41 54 push r12 329 | __text:FFFFFF80005F709C 53 push rbx 330 | __text:FFFFFF80005F709D 50 push rax 331 | __text:FFFFFF80005F709E 89 FB mov ebx, edi 332 | __text:FFFFFF80005F70A0 48 8B 3D 59 61 2B 00 mov rdi, cs:qword_FFFFFF80008AD200 333 | __text:FFFFFF80005F70A7 E8 24 CA 02 00 call _IORecursiveLockLock 334 | __text:FFFFFF80005F70AC 48 8B 3D 75 61 2B 00 mov rdi, cs:sLoadedKexts 335 | */ 336 | static mach_vm_address_t 337 | find_sloadedkexts(uint8_t *buffer, int32_t buffer_size, mach_vm_address_t offset_addr, mach_vm_address_t iorecursivelocklock) 338 | { 339 | #define MAX_INSTRUCTIONS 8192 340 | // allocate space for disassembly output 341 | _DInst *decodedInstructions = malloc(sizeof(_DInst) * MAX_INSTRUCTIONS); 342 | if (decodedInstructions == NULL) 343 | { 344 | ERROR_MSG("Decoded instructions allocation failed!"); 345 | return 0; 346 | } 347 | unsigned int decodedInstructionsCount = 0; 348 | _DecodeResult res = 0; 349 | _CodeInfo ci; 350 | ci.dt = Decode64Bits; 351 | ci.features = DF_NONE; 352 | ci.codeLen = (int)buffer_size; 353 | ci.code = buffer; 354 | ci.codeOffset = offset_addr; // offset to function to be disassembled so diStorm gets addresses correct 355 | mach_vm_address_t next; 356 | while (1) 357 | { 358 | res = distorm_decompose(&ci, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount); 359 | if (res == DECRES_INPUTERR) 360 | { 361 | // Error handling... 362 | ERROR_MSG("Distorm failed to disassemble!"); 363 | goto failure; 364 | } 365 | // iterate over the disassembly and lookup for CALL instructions 366 | for (int i = 0; i < decodedInstructionsCount; i++) 367 | { 368 | if (decodedInstructions[i].opcode == I_CALL) 369 | { 370 | // retrieve the target address and see if it matches the symbol we are looking for 371 | mach_vm_address_t rip_address = INSTRUCTION_GET_TARGET(&decodedInstructions[i]); 372 | if (rip_address == iorecursivelocklock) 373 | { 374 | // get the sLoadedKexts from next instruction 375 | mach_vm_address_t sloadedkexts = INSTRUCTION_GET_RIP_TARGET(&decodedInstructions[i+1]); 376 | OUTPUT_MSG("[INFO] sLoadedKexts at %p", (void*)sloadedkexts); 377 | return sloadedkexts; 378 | } 379 | } 380 | } 381 | if (res == DECRES_SUCCESS) break; // All instructions were decoded. 382 | else if (decodedInstructionsCount == 0) break; 383 | // sync the disassembly 384 | // the total number of bytes disassembly to previous last instruction 385 | next = decodedInstructions[decodedInstructionsCount-1].addr - ci.codeOffset; 386 | // add points to the first byte so add instruction size to it 387 | next += decodedInstructions[decodedInstructionsCount-1].size; 388 | // update the CodeInfo struct with the synced data 389 | ci.code += next; 390 | ci.codeOffset += next; 391 | ci.codeLen -= next; 392 | } 393 | failure: 394 | free(decodedInstructions); 395 | return 0; 396 | } 397 | 398 | #pragma mark Main! 399 | 400 | /* 401 | * where all the fun begins 402 | */ 403 | int main(int argc, char ** argv) 404 | { 405 | 406 | header(); 407 | 408 | // we need to run this as root 409 | if (getuid() != 0) 410 | { 411 | ERROR_MSG("Please run me as root!"); 412 | exit(-1); 413 | } 414 | 415 | /* test if we can read kernel memory using processor_set_tasks() vulnerability */ 416 | /* vulnerability presented at BlackHat Asia 2014 by Ming-chieh Pan, Sung-ting Tsai. */ 417 | /* also described in Mac OS X and iOS Internals, page 387 */ 418 | host_t host_port = mach_host_self(); 419 | mach_port_t proc_set_default = 0; 420 | mach_port_t proc_set_default_control = 0; 421 | task_array_t all_tasks = NULL; 422 | mach_msg_type_number_t all_tasks_cnt = 0; 423 | kern_return_t kr = 0; 424 | int valid_kernel_port = 0; 425 | 426 | kr = processor_set_default(host_port, &proc_set_default); 427 | if (kr == KERN_SUCCESS) 428 | { 429 | kr = host_processor_set_priv(host_port, proc_set_default, &proc_set_default_control); 430 | if (kr == KERN_SUCCESS) 431 | { 432 | kr = processor_set_tasks(proc_set_default_control, &all_tasks, &all_tasks_cnt); 433 | if (kr == KERN_SUCCESS) 434 | { 435 | OUTPUT_MSG("Found valid kernel port using processor_set_tasks() vulnerability!"); 436 | g_kmem_source.kernel_port = all_tasks[0]; 437 | valid_kernel_port = 1; 438 | } 439 | } 440 | } 441 | 442 | /* kernel not vulnerable, try to use /dev/kmem */ 443 | if (valid_kernel_port == 0) 444 | { 445 | if((g_kmem_source.fd = open("/dev/kmem",O_RDWR)) == -1) 446 | { 447 | ERROR_MSG("Error while opening /dev/kmem. Is /dev/kmem enabled?"); 448 | ERROR_MSG("Add parameter kmem=1 to /Library/Preferences/SystemConfiguration/com.apple.Boot.plist."); 449 | exit(-1); 450 | } 451 | } 452 | 453 | // retrieve kernel aslr slide using kas_info() syscall 454 | // this is a private kernel syscall but we can access it in Mountain Lion if we link against System.framework 455 | // or we can use my lame asm function get_kaslr_slide() :-) 456 | size_t kaslr_size = 0; 457 | uint64_t kaslr_slide = 0; 458 | kaslr_size = sizeof(kaslr_slide); 459 | int ret = kas_info(KAS_INFO_KERNEL_TEXT_SLIDE_SELECTOR, &kaslr_slide, &kaslr_size); 460 | if (ret != 0) 461 | { 462 | ERROR_MSG("Could not get kernel ASLR slide info from kas_info(). Errno: %d.", errno); 463 | exit(-1); 464 | } 465 | OUTPUT_MSG("[INFO] Kernel ASLR slide is 0x%llx", kaslr_slide); 466 | 467 | // get info from the kernel at disk 468 | uint8_t *kernel_buffer = NULL; 469 | read_target(&kernel_buffer, "/mach_kernel"); 470 | // get info we need to solve symbols from Mach-O header 471 | struct kernel_info kinfo = { 0 }; 472 | if (process_kernel_mach_header((void*)kernel_buffer, &kinfo)) 473 | { 474 | ERROR_MSG("Kernel Mach-O header processing failed!"); 475 | exit(-1); 476 | } 477 | // set a pointer to __LINKEDIT location in the kernel buffer 478 | kinfo.linkedit_buf = (void*)((char*)kernel_buffer + kinfo.linkedit_fileoff); 479 | kinfo.kaslr_slide = kaslr_slide; 480 | // solve the OSKext::lookupKextWithLoadTag symbol 481 | // and _IORecursiveLockLock, because sLoadedKexts is right after 482 | mach_vm_address_t loadtag_symbol = solve_kernel_symbol(&kinfo, LOOKUPKEXTWITHLOADTAG); 483 | mach_vm_address_t iorecursivelocklock = solve_kernel_symbol(&kinfo, "_IORecursiveLockLock"); 484 | // disassemble and find the address of sLoadedKexts 485 | // it's easier to read it from memory than disk 486 | uint8_t loadtag_buffer[DISASM_SIZE] = {0}; 487 | /* XXX: we might have problems reading out of bounds using the vuln so reduce size to 1024 */ 488 | /* fix should be check if size will go out of kernel memory */ 489 | if (readkmem(loadtag_buffer, loadtag_symbol, DISASM_SIZE) != 0) 490 | { 491 | ERROR_MSG("Unable to read OSKext::lookupKextWithLoadTag from kernel memory!"); 492 | exit(-1); 493 | } 494 | mach_vm_address_t sLoadedKexts = find_sloadedkexts(loadtag_buffer, DISASM_SIZE, loadtag_symbol, iorecursivelocklock); 495 | if (sLoadedKexts == 0) 496 | { 497 | ERROR_MSG("sLoadedKexts not found!"); 498 | exit(-1); 499 | } 500 | mach_vm_address_t sLoadedKexts_object = 0; 501 | // read where sLoadedKexts is pointing to so we can get the OSArray object 502 | readkmem(&sLoadedKexts_object, sLoadedKexts, 8); 503 | OUTPUT_MSG("[INFO] sLoadedKexts OSArray object located at 0x%llx", sLoadedKexts_object); 504 | uint32_t kexts_count = 0; 505 | readkmem(&kexts_count, sLoadedKexts_object+0x20, sizeof(unsigned int)); 506 | if (kexts_count == 0) 507 | { 508 | ERROR_MSG("Could not retrieve number of loaded kexts!"); 509 | exit(-1); 510 | } 511 | OUTPUT_MSG("[INFO] Total kexts loaded %d", kexts_count); 512 | mach_vm_address_t array_ptr = 0; 513 | readkmem(&array_ptr, sLoadedKexts_object+0x18, sizeof(mach_vm_address_t)); 514 | OUTPUT_MSG("[INFO] Array of OSKext starts at 0x%llx", array_ptr); 515 | size_t OSKext_object_len = kexts_count * sizeof(mach_vm_address_t); 516 | mach_vm_address_t *OSKext_object = malloc(OSKext_object_len); 517 | if (readkmem(OSKext_object, array_ptr, OSKext_object_len) != 0) 518 | { 519 | ERROR_MSG("Failed to read OSKext array!"); 520 | exit(-1); 521 | } 522 | 523 | OUTPUT_MSG("Index Refs Address Size Name (Version)"); 524 | for (unsigned int i = 0; i < kexts_count; i++) 525 | { 526 | mach_vm_address_t kmod_info_ptr = 0; 527 | readkmem(&kmod_info_ptr, OSKext_object[i]+0x48, sizeof(kmod_info_ptr)); 528 | kmod_info_t kmod_info = { 0 }; 529 | readkmem(&kmod_info, kmod_info_ptr, sizeof(kmod_info_t)); 530 | char name[KMOD_MAX_NAME]; 531 | readkmem(&name, kmod_info_ptr+0x10, sizeof(name)); 532 | OUTPUT_MSG("%5d %4d 0x%016llx 0x%-8lx %s (%s)", i, kmod_info.reference_count, (uint64_t)kmod_info.address, kmod_info.size, kmod_info.name, kmod_info.version); 533 | } 534 | end: 535 | free(OSKext_object); 536 | free(kernel_buffer); 537 | return 0; 538 | } 539 | -------------------------------------------------------------------------------- /kextstat_aslr/mnemonics.h: -------------------------------------------------------------------------------- 1 | /* 2 | mnemonics.h 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #ifndef MNEMONICS_H 25 | #define MNEMONICS_H 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | #ifndef DISTORM_LIGHT 32 | 33 | typedef struct WMnemonic { 34 | unsigned char length; 35 | unsigned char p[1]; /* p is a null terminated string, which contains 'length' characters. */ 36 | } _WMnemonic; 37 | 38 | typedef struct WRegister { 39 | unsigned int length; 40 | unsigned char p[6]; /* p is a null terminated string. */ 41 | } _WRegister; 42 | 43 | extern const unsigned char _MNEMONICS[]; 44 | extern const _WRegister _REGISTERS[]; 45 | 46 | #endif /* DISTORM_LIGHT */ 47 | 48 | #ifdef __cplusplus 49 | } /* End Of Extern */ 50 | #endif 51 | 52 | #define GET_REGISTER_NAME(r) (unsigned char*)_REGISTERS[(r)].p 53 | #define GET_MNEMONIC_NAME(m) ((_WMnemonic*)&_MNEMONICS[(m)])->p 54 | 55 | typedef enum { 56 | I_UNDEFINED = 0, I_AAA = 66, I_AAD = 389, I_AAM = 384, I_AAS = 76, I_ADC = 31, I_ADD = 11, I_ADDPD = 3110, 57 | I_ADDPS = 3103, I_ADDSD = 3124, I_ADDSS = 3117, I_ADDSUBPD = 6394, I_ADDSUBPS = 6404, 58 | I_AESDEC = 9209, I_AESDECLAST = 9226, I_AESENC = 9167, I_AESENCLAST = 9184, 59 | I_AESIMC = 9150, I_AESKEYGENASSIST = 9795, I_AND = 41, I_ANDNPD = 3021, I_ANDNPS = 3013, 60 | I_ANDPD = 2990, I_ANDPS = 2983, I_ARPL = 111, I_BLENDPD = 9372, I_BLENDPS = 9353, 61 | I_BLENDVPD = 7619, I_BLENDVPS = 7609, I_BOUND = 104, I_BSF = 4346, I_BSR = 4358, 62 | I_BSWAP = 960, I_BT = 872, I_BTC = 934, I_BTR = 912, I_BTS = 887, I_CALL = 456, 63 | I_CALL_FAR = 260, I_CBW = 228, I_CDQ = 250, I_CDQE = 239, I_CLC = 492, I_CLD = 512, 64 | I_CLFLUSH = 4329, I_CLGI = 1833, I_CLI = 502, I_CLTS = 541, I_CMC = 487, I_CMOVA = 694, 65 | I_CMOVAE = 663, I_CMOVB = 656, I_CMOVBE = 686, I_CMOVG = 754, I_CMOVGE = 738, 66 | I_CMOVL = 731, I_CMOVLE = 746, I_CMOVNO = 648, I_CMOVNP = 723, I_CMOVNS = 708, 67 | I_CMOVNZ = 678, I_CMOVO = 641, I_CMOVP = 716, I_CMOVS = 701, I_CMOVZ = 671, 68 | I_CMP = 71, I_CMPEQPD = 4449, I_CMPEQPS = 4370, I_CMPEQSD = 4607, I_CMPEQSS = 4528, 69 | I_CMPLEPD = 4467, I_CMPLEPS = 4388, I_CMPLESD = 4625, I_CMPLESS = 4546, I_CMPLTPD = 4458, 70 | I_CMPLTPS = 4379, I_CMPLTSD = 4616, I_CMPLTSS = 4537, I_CMPNEQPD = 4488, I_CMPNEQPS = 4409, 71 | I_CMPNEQSD = 4646, I_CMPNEQSS = 4567, I_CMPNLEPD = 4508, I_CMPNLEPS = 4429, 72 | I_CMPNLESD = 4666, I_CMPNLESS = 4587, I_CMPNLTPD = 4498, I_CMPNLTPS = 4419, 73 | I_CMPNLTSD = 4656, I_CMPNLTSS = 4577, I_CMPORDPD = 4518, I_CMPORDPS = 4439, 74 | I_CMPORDSD = 4676, I_CMPORDSS = 4597, I_CMPS = 301, I_CMPUNORDPD = 4476, I_CMPUNORDPS = 4397, 75 | I_CMPUNORDSD = 4634, I_CMPUNORDSS = 4555, I_CMPXCHG = 898, I_CMPXCHG16B = 6373, 76 | I_CMPXCHG8B = 6362, I_COMISD = 2779, I_COMISS = 2771, I_CPUID = 865, I_CQO = 255, 77 | I_CRC32 = 9258, I_CVTDQ2PD = 6787, I_CVTDQ2PS = 3307, I_CVTPD2DQ = 6797, I_CVTPD2PI = 2681, 78 | I_CVTPD2PS = 3233, I_CVTPH2PS = 4161, I_CVTPI2PD = 2495, I_CVTPI2PS = 2485, 79 | I_CVTPS2DQ = 3317, I_CVTPS2PD = 3223, I_CVTPS2PH = 4171, I_CVTPS2PI = 2671, 80 | I_CVTSD2SI = 2701, I_CVTSD2SS = 3253, I_CVTSI2SD = 2515, I_CVTSI2SS = 2505, 81 | I_CVTSS2SD = 3243, I_CVTSS2SI = 2691, I_CVTTPD2DQ = 6776, I_CVTTPD2PI = 2614, 82 | I_CVTTPS2DQ = 3327, I_CVTTPS2PI = 2603, I_CVTTSD2SI = 2636, I_CVTTSS2SI = 2625, 83 | I_CWD = 245, I_CWDE = 233, I_DAA = 46, I_DAS = 56, I_DEC = 86, I_DIV = 1630, 84 | I_DIVPD = 3499, I_DIVPS = 3492, I_DIVSD = 3513, I_DIVSS = 3506, I_DPPD = 9615, 85 | I_DPPS = 9602, I_EMMS = 4100, I_ENTER = 340, I_EXTRACTPS = 9480, I_EXTRQ = 4136, 86 | I_F2XM1 = 1176, I_FABS = 1107, I_FADD = 1007, I_FADDP = 1533, I_FBLD = 1585, 87 | I_FBSTP = 1591, I_FCHS = 1101, I_FCLEX = 7289, I_FCMOVB = 1360, I_FCMOVBE = 1376, 88 | I_FCMOVE = 1368, I_FCMOVNB = 1429, I_FCMOVNBE = 1447, I_FCMOVNE = 1438, I_FCMOVNU = 1457, 89 | I_FCMOVU = 1385, I_FCOM = 1019, I_FCOMI = 1496, I_FCOMIP = 1607, I_FCOMP = 1025, 90 | I_FCOMPP = 1547, I_FCOS = 1295, I_FDECSTP = 1222, I_FDIV = 1045, I_FDIVP = 1578, 91 | I_FDIVR = 1051, I_FDIVRP = 1570, I_FEDISI = 1472, I_FEMMS = 574, I_FENI = 1466, 92 | I_FFREE = 1511, I_FIADD = 1301, I_FICOM = 1315, I_FICOMP = 1322, I_FIDIV = 1345, 93 | I_FIDIVR = 1352, I_FILD = 1402, I_FIMUL = 1308, I_FINCSTP = 1231, I_FINIT = 7304, 94 | I_FIST = 1416, I_FISTP = 1422, I_FISTTP = 1408, I_FISUB = 1330, I_FISUBR = 1337, 95 | I_FLD = 1058, I_FLD1 = 1125, I_FLDCW = 1082, I_FLDENV = 1074, I_FLDL2E = 1139, 96 | I_FLDL2T = 1131, I_FLDLG2 = 1154, I_FLDLN2 = 1162, I_FLDPI = 1147, I_FLDZ = 1170, 97 | I_FMUL = 1013, I_FMULP = 1540, I_FNCLEX = 7281, I_FNINIT = 7296, I_FNOP = 1095, 98 | I_FNSAVE = 7311, I_FNSTCW = 7266, I_FNSTENV = 7249, I_FNSTSW = 7326, I_FPATAN = 1197, 99 | I_FPREM = 1240, I_FPREM1 = 1214, I_FPTAN = 1190, I_FRNDINT = 1272, I_FRSTOR = 1503, 100 | I_FSAVE = 7319, I_FSCALE = 1281, I_FSETPM = 1480, I_FSIN = 1289, I_FSINCOS = 1263, 101 | I_FSQRT = 1256, I_FST = 1063, I_FSTCW = 7274, I_FSTENV = 7258, I_FSTP = 1068, 102 | I_FSTSW = 7334, I_FSUB = 1032, I_FSUBP = 1563, I_FSUBR = 1038, I_FSUBRP = 1555, 103 | I_FTST = 1113, I_FUCOM = 1518, I_FUCOMI = 1488, I_FUCOMIP = 1598, I_FUCOMP = 1525, 104 | I_FUCOMPP = 1393, I_FXAM = 1119, I_FXCH = 1089, I_FXRSTOR = 9892, I_FXRSTOR64 = 9901, 105 | I_FXSAVE = 9864, I_FXSAVE64 = 9872, I_FXTRACT = 1205, I_FYL2X = 1183, I_FYL2XP1 = 1247, 106 | I_GETSEC = 633, I_HADDPD = 4181, I_HADDPS = 4189, I_HLT = 482, I_HSUBPD = 4215, 107 | I_HSUBPS = 4223, I_IDIV = 1635, I_IMUL = 117, I_IN = 447, I_INC = 81, I_INS = 123, 108 | I_INSERTPS = 9547, I_INSERTQ = 4143, I_INT = 367, I_INT_3 = 360, I_INT1 = 476, 109 | I_INTO = 372, I_INVD = 555, I_INVEPT = 8284, I_INVLPG = 1711, I_INVLPGA = 1847, 110 | I_INVPCID = 8301, I_INVVPID = 8292, I_IRET = 378, I_JA = 166, I_JAE = 147, 111 | I_JB = 143, I_JBE = 161, I_JCXZ = 427, I_JECXZ = 433, I_JG = 202, I_JGE = 192, 112 | I_JL = 188, I_JLE = 197, I_JMP = 462, I_JMP_FAR = 467, I_JNO = 138, I_JNP = 183, 113 | I_JNS = 174, I_JNZ = 156, I_JO = 134, I_JP = 179, I_JRCXZ = 440, I_JS = 170, 114 | I_JZ = 152, I_LAHF = 289, I_LAR = 522, I_LDDQU = 6994, I_LDMXCSR = 9922, I_LDS = 335, 115 | I_LEA = 223, I_LEAVE = 347, I_LES = 330, I_LFENCE = 4265, I_LFS = 917, I_LGDT = 1687, 116 | I_LGS = 922, I_LIDT = 1693, I_LLDT = 1652, I_LMSW = 1705, I_LODS = 313, I_LOOP = 421, 117 | I_LOOPNZ = 406, I_LOOPZ = 414, I_LSL = 527, I_LSS = 907, I_LTR = 1658, I_LZCNT = 4363, 118 | I_MASKMOVDQU = 7119, I_MASKMOVQ = 7109, I_MAXPD = 3559, I_MAXPS = 3552, I_MAXSD = 3573, 119 | I_MAXSS = 3566, I_MFENCE = 4291, I_MINPD = 3439, I_MINPS = 3432, I_MINSD = 3453, 120 | I_MINSS = 3446, I_MONITOR = 1755, I_MOV = 218, I_MOVAPD = 2459, I_MOVAPS = 2451, 121 | I_MOVBE = 9251, I_MOVD = 3920, I_MOVDDUP = 2186, I_MOVDQ2Q = 6522, I_MOVDQA = 3946, 122 | I_MOVDQU = 3954, I_MOVHLPS = 2151, I_MOVHPD = 2345, I_MOVHPS = 2337, I_MOVLHPS = 2328, 123 | I_MOVLPD = 2168, I_MOVLPS = 2160, I_MOVMSKPD = 2815, I_MOVMSKPS = 2805, I_MOVNTDQ = 6849, 124 | I_MOVNTDQA = 7895, I_MOVNTI = 952, I_MOVNTPD = 2556, I_MOVNTPS = 2547, I_MOVNTQ = 6841, 125 | I_MOVNTSD = 2574, I_MOVNTSS = 2565, I_MOVQ = 3926, I_MOVQ2DQ = 6513, I_MOVS = 295, 126 | I_MOVSD = 2110, I_MOVSHDUP = 2353, I_MOVSLDUP = 2176, I_MOVSS = 2103, I_MOVSX = 939, 127 | I_MOVSXD = 10013, I_MOVUPD = 2095, I_MOVUPS = 2087, I_MOVZX = 927, I_MPSADBW = 9628, 128 | I_MUL = 1625, I_MULPD = 3170, I_MULPS = 3163, I_MULSD = 3184, I_MULSS = 3177, 129 | I_MWAIT = 1764, I_NEG = 1620, I_NOP = 581, I_NOT = 1615, I_OR = 27, I_ORPD = 3053, 130 | I_ORPS = 3047, I_OUT = 451, I_OUTS = 128, I_PABSB = 7688, I_PABSD = 7718, I_PABSW = 7703, 131 | I_PACKSSDW = 3849, I_PACKSSWB = 3681, I_PACKUSDW = 7916, I_PACKUSWB = 3759, 132 | I_PADDB = 7204, I_PADDD = 7234, I_PADDQ = 6481, I_PADDSB = 6930, I_PADDSW = 6947, 133 | I_PADDUSB = 6620, I_PADDUSW = 6639, I_PADDW = 7219, I_PALIGNR = 9410, I_PAND = 6607, 134 | I_PANDN = 6665, I_PAUSE = 10021, I_PAVGB = 6680, I_PAVGUSB = 2078, I_PAVGW = 6725, 135 | I_PBLENDVB = 7599, I_PBLENDW = 9391, I_PCLMULQDQ = 9647, I_PCMPEQB = 4043, 136 | I_PCMPEQD = 4081, I_PCMPEQQ = 7876, I_PCMPEQW = 4062, I_PCMPESTRI = 9726, 137 | I_PCMPESTRM = 9703, I_PCMPGTB = 3702, I_PCMPGTD = 3740, I_PCMPGTQ = 8087, 138 | I_PCMPGTW = 3721, I_PCMPISTRI = 9772, I_PCMPISTRM = 9749, I_PEXTRB = 9429, 139 | I_PEXTRD = 9446, I_PEXTRQ = 9454, I_PEXTRW = 6311, I_PF2ID = 1914, I_PF2IW = 1907, 140 | I_PFACC = 2028, I_PFADD = 1977, I_PFCMPEQ = 2035, I_PFCMPGE = 1938, I_PFCMPGT = 1984, 141 | I_PFMAX = 1993, I_PFMIN = 1947, I_PFMUL = 2044, I_PFNACC = 1921, I_PFPNACC = 1929, 142 | I_PFRCP = 1954, I_PFRCPIT1 = 2000, I_PFRCPIT2 = 2051, I_PFRSQIT1 = 2010, I_PFRSQRT = 1961, 143 | I_PFSUB = 1970, I_PFSUBR = 2020, I_PHADDD = 7375, I_PHADDSW = 7392, I_PHADDW = 7358, 144 | I_PHMINPOSUW = 8259, I_PHSUBD = 7451, I_PHSUBSW = 7468, I_PHSUBW = 7434, I_PI2FD = 1900, 145 | I_PI2FW = 1893, I_PINSRB = 9530, I_PINSRD = 9568, I_PINSRQ = 9576, I_PINSRW = 6294, 146 | I_PMADDUBSW = 7411, I_PMADDWD = 7073, I_PMAXSB = 8174, I_PMAXSD = 8191, I_PMAXSW = 6964, 147 | I_PMAXUB = 6648, I_PMAXUD = 8225, I_PMAXUW = 8208, I_PMINSB = 8106, I_PMINSD = 8123, 148 | I_PMINSW = 6902, I_PMINUB = 6590, I_PMINUD = 8157, I_PMINUW = 8140, I_PMOVMSKB = 6531, 149 | I_PMOVSXBD = 7754, I_PMOVSXBQ = 7775, I_PMOVSXBW = 7733, I_PMOVSXDQ = 7838, 150 | I_PMOVSXWD = 7796, I_PMOVSXWQ = 7817, I_PMOVZXBD = 7982, I_PMOVZXBQ = 8003, 151 | I_PMOVZXBW = 7961, I_PMOVZXDQ = 8066, I_PMOVZXWD = 8024, I_PMOVZXWQ = 8045, 152 | I_PMULDQ = 7859, I_PMULHRSW = 7538, I_PMULHRW = 2061, I_PMULHUW = 6740, I_PMULHW = 6759, 153 | I_PMULLD = 8242, I_PMULLW = 6496, I_PMULUDQ = 7054, I_POP = 22, I_POPA = 98, 154 | I_POPCNT = 4338, I_POPF = 277, I_POR = 6919, I_PREFETCH = 1872, I_PREFETCHNTA = 2402, 155 | I_PREFETCHT0 = 2415, I_PREFETCHT1 = 2427, I_PREFETCHT2 = 2439, I_PREFETCHW = 1882, 156 | I_PSADBW = 7092, I_PSHUFB = 7341, I_PSHUFD = 3988, I_PSHUFHW = 3996, I_PSHUFLW = 4005, 157 | I_PSHUFW = 3980, I_PSIGNB = 7487, I_PSIGND = 7521, I_PSIGNW = 7504, I_PSLLD = 7024, 158 | I_PSLLDQ = 9847, I_PSLLQ = 7039, I_PSLLW = 7009, I_PSRAD = 6710, I_PSRAW = 6695, 159 | I_PSRLD = 6451, I_PSRLDQ = 9830, I_PSRLQ = 6466, I_PSRLW = 6436, I_PSUBB = 7144, 160 | I_PSUBD = 7174, I_PSUBQ = 7189, I_PSUBSB = 6868, I_PSUBSW = 6885, I_PSUBUSB = 6552, 161 | I_PSUBUSW = 6571, I_PSUBW = 7159, I_PSWAPD = 2070, I_PTEST = 7629, I_PUNPCKHBW = 3780, 162 | I_PUNPCKHDQ = 3826, I_PUNPCKHQDQ = 3895, I_PUNPCKHWD = 3803, I_PUNPCKLBW = 3612, 163 | I_PUNPCKLDQ = 3658, I_PUNPCKLQDQ = 3870, I_PUNPCKLWD = 3635, I_PUSH = 16, 164 | I_PUSHA = 91, I_PUSHF = 270, I_PXOR = 6981, I_RCL = 977, I_RCPPS = 2953, I_RCPSS = 2960, 165 | I_RCR = 982, I_RDFSBASE = 9882, I_RDGSBASE = 9912, I_RDMSR = 600, I_RDPMC = 607, 166 | I_RDRAND = 9980, I_RDTSC = 593, I_RDTSCP = 1864, I_RET = 325, I_RETF = 354, 167 | I_ROL = 967, I_ROR = 972, I_ROUNDPD = 9296, I_ROUNDPS = 9277, I_ROUNDSD = 9334, 168 | I_ROUNDSS = 9315, I_RSM = 882, I_RSQRTPS = 2915, I_RSQRTSS = 2924, I_SAHF = 283, 169 | I_SAL = 997, I_SALC = 394, I_SAR = 1002, I_SBB = 36, I_SCAS = 319, I_SETA = 807, 170 | I_SETAE = 780, I_SETB = 774, I_SETBE = 800, I_SETG = 859, I_SETGE = 845, I_SETL = 839, 171 | I_SETLE = 852, I_SETNO = 767, I_SETNP = 832, I_SETNS = 819, I_SETNZ = 793, 172 | I_SETO = 761, I_SETP = 826, I_SETS = 813, I_SETZ = 787, I_SFENCE = 4321, I_SGDT = 1675, 173 | I_SHL = 987, I_SHLD = 876, I_SHR = 992, I_SHRD = 892, I_SHUFPD = 6336, I_SHUFPS = 6328, 174 | I_SIDT = 1681, I_SKINIT = 1839, I_SLDT = 1641, I_SMSW = 1699, I_SQRTPD = 2855, 175 | I_SQRTPS = 2847, I_SQRTSD = 2871, I_SQRTSS = 2863, I_STC = 497, I_STD = 517, 176 | I_STGI = 1827, I_STI = 507, I_STMXCSR = 9951, I_STOS = 307, I_STR = 1647, I_SUB = 51, 177 | I_SUBPD = 3379, I_SUBPS = 3372, I_SUBSD = 3393, I_SUBSS = 3386, I_SWAPGS = 1856, 178 | I_SYSCALL = 532, I_SYSENTER = 614, I_SYSEXIT = 624, I_SYSRET = 547, I_TEST = 206, 179 | I_TZCNT = 4351, I_UCOMISD = 2742, I_UCOMISS = 2733, I_UD2 = 569, I_UNPCKHPD = 2296, 180 | I_UNPCKHPS = 2286, I_UNPCKLPD = 2254, I_UNPCKLPS = 2244, I_VADDPD = 3139, 181 | I_VADDPS = 3131, I_VADDSD = 3155, I_VADDSS = 3147, I_VADDSUBPD = 6414, I_VADDSUBPS = 6425, 182 | I_VAESDEC = 9217, I_VAESDECLAST = 9238, I_VAESENC = 9175, I_VAESENCLAST = 9196, 183 | I_VAESIMC = 9158, I_VAESKEYGENASSIST = 9812, I_VANDNPD = 3038, I_VANDNPS = 3029, 184 | I_VANDPD = 3005, I_VANDPS = 2997, I_VBLENDPD = 9381, I_VBLENDPS = 9362, I_VBLENDVPD = 9681, 185 | I_VBLENDVPS = 9670, I_VBROADCASTF128 = 7672, I_VBROADCASTSD = 7658, I_VBROADCASTSS = 7644, 186 | I_VCMPEQPD = 5088, I_VCMPEQPS = 4686, I_VCMPEQSD = 5892, I_VCMPEQSS = 5490, 187 | I_VCMPEQ_OSPD = 5269, I_VCMPEQ_OSPS = 4867, I_VCMPEQ_OSSD = 6073, I_VCMPEQ_OSSS = 5671, 188 | I_VCMPEQ_UQPD = 5175, I_VCMPEQ_UQPS = 4773, I_VCMPEQ_UQSD = 5979, I_VCMPEQ_UQSS = 5577, 189 | I_VCMPEQ_USPD = 5378, I_VCMPEQ_USPS = 4976, I_VCMPEQ_USSD = 6182, I_VCMPEQ_USSS = 5780, 190 | I_VCMPFALSEPD = 5210, I_VCMPFALSEPS = 4808, I_VCMPFALSESD = 6014, I_VCMPFALSESS = 5612, 191 | I_VCMPFALSE_OSPD = 5419, I_VCMPFALSE_OSPS = 5017, I_VCMPFALSE_OSSD = 6223, 192 | I_VCMPFALSE_OSSS = 5821, I_VCMPGEPD = 5237, I_VCMPGEPS = 4835, I_VCMPGESD = 6041, 193 | I_VCMPGESS = 5639, I_VCMPGE_OQPD = 5449, I_VCMPGE_OQPS = 5047, I_VCMPGE_OQSD = 6253, 194 | I_VCMPGE_OQSS = 5851, I_VCMPGTPD = 5247, I_VCMPGTPS = 4845, I_VCMPGTSD = 6051, 195 | I_VCMPGTSS = 5649, I_VCMPGT_OQPD = 5462, I_VCMPGT_OQPS = 5060, I_VCMPGT_OQSD = 6266, 196 | I_VCMPGT_OQSS = 5864, I_VCMPLEPD = 5108, I_VCMPLEPS = 4706, I_VCMPLESD = 5912, 197 | I_VCMPLESS = 5510, I_VCMPLE_OQPD = 5295, I_VCMPLE_OQPS = 4893, I_VCMPLE_OQSD = 6099, 198 | I_VCMPLE_OQSS = 5697, I_VCMPLTPD = 5098, I_VCMPLTPS = 4696, I_VCMPLTSD = 5902, 199 | I_VCMPLTSS = 5500, I_VCMPLT_OQPD = 5282, I_VCMPLT_OQPS = 4880, I_VCMPLT_OQSD = 6086, 200 | I_VCMPLT_OQSS = 5684, I_VCMPNEQPD = 5131, I_VCMPNEQPS = 4729, I_VCMPNEQSD = 5935, 201 | I_VCMPNEQSS = 5533, I_VCMPNEQ_OQPD = 5223, I_VCMPNEQ_OQPS = 4821, I_VCMPNEQ_OQSD = 6027, 202 | I_VCMPNEQ_OQSS = 5625, I_VCMPNEQ_OSPD = 5435, I_VCMPNEQ_OSPS = 5033, I_VCMPNEQ_OSSD = 6239, 203 | I_VCMPNEQ_OSSS = 5837, I_VCMPNEQ_USPD = 5323, I_VCMPNEQ_USPS = 4921, I_VCMPNEQ_USSD = 6127, 204 | I_VCMPNEQ_USSS = 5725, I_VCMPNGEPD = 5188, I_VCMPNGEPS = 4786, I_VCMPNGESD = 5992, 205 | I_VCMPNGESS = 5590, I_VCMPNGE_UQPD = 5391, I_VCMPNGE_UQPS = 4989, I_VCMPNGE_UQSD = 6195, 206 | I_VCMPNGE_UQSS = 5793, I_VCMPNGTPD = 5199, I_VCMPNGTPS = 4797, I_VCMPNGTSD = 6003, 207 | I_VCMPNGTSS = 5601, I_VCMPNGT_UQPD = 5405, I_VCMPNGT_UQPS = 5003, I_VCMPNGT_UQSD = 6209, 208 | I_VCMPNGT_UQSS = 5807, I_VCMPNLEPD = 5153, I_VCMPNLEPS = 4751, I_VCMPNLESD = 5957, 209 | I_VCMPNLESS = 5555, I_VCMPNLE_UQPD = 5351, I_VCMPNLE_UQPS = 4949, I_VCMPNLE_UQSD = 6155, 210 | I_VCMPNLE_UQSS = 5753, I_VCMPNLTPD = 5142, I_VCMPNLTPS = 4740, I_VCMPNLTSD = 5946, 211 | I_VCMPNLTSS = 5544, I_VCMPNLT_UQPD = 5337, I_VCMPNLT_UQPS = 4935, I_VCMPNLT_UQSD = 6141, 212 | I_VCMPNLT_UQSS = 5739, I_VCMPORDPD = 5164, I_VCMPORDPS = 4762, I_VCMPORDSD = 5968, 213 | I_VCMPORDSS = 5566, I_VCMPORD_SPD = 5365, I_VCMPORD_SPS = 4963, I_VCMPORD_SSD = 6169, 214 | I_VCMPORD_SSS = 5767, I_VCMPTRUEPD = 5257, I_VCMPTRUEPS = 4855, I_VCMPTRUESD = 6061, 215 | I_VCMPTRUESS = 5659, I_VCMPTRUE_USPD = 5475, I_VCMPTRUE_USPS = 5073, I_VCMPTRUE_USSD = 6279, 216 | I_VCMPTRUE_USSS = 5877, I_VCMPUNORDPD = 5118, I_VCMPUNORDPS = 4716, I_VCMPUNORDSD = 5922, 217 | I_VCMPUNORDSS = 5520, I_VCMPUNORD_SPD = 5308, I_VCMPUNORD_SPS = 4906, I_VCMPUNORD_SSD = 6112, 218 | I_VCMPUNORD_SSS = 5710, I_VCOMISD = 2796, I_VCOMISS = 2787, I_VCVTDQ2PD = 6819, 219 | I_VCVTDQ2PS = 3338, I_VCVTPD2DQ = 6830, I_VCVTPD2PS = 3274, I_VCVTPS2DQ = 3349, 220 | I_VCVTPS2PD = 3263, I_VCVTSD2SI = 2722, I_VCVTSD2SS = 3296, I_VCVTSI2SD = 2536, 221 | I_VCVTSI2SS = 2525, I_VCVTSS2SD = 3285, I_VCVTSS2SI = 2711, I_VCVTTPD2DQ = 6807, 222 | I_VCVTTPS2DQ = 3360, I_VCVTTSD2SI = 2659, I_VCVTTSS2SI = 2647, I_VDIVPD = 3528, 223 | I_VDIVPS = 3520, I_VDIVSD = 3544, I_VDIVSS = 3536, I_VDPPD = 9621, I_VDPPS = 9608, 224 | I_VERR = 1663, I_VERW = 1669, I_VEXTRACTF128 = 9516, I_VEXTRACTPS = 9491, 225 | I_VFMADD132PD = 8387, I_VFMADD132PS = 8374, I_VFMADD132SD = 8413, I_VFMADD132SS = 8400, 226 | I_VFMADD213PD = 8667, I_VFMADD213PS = 8654, I_VFMADD213SD = 8693, I_VFMADD213SS = 8680, 227 | I_VFMADD231PD = 8947, I_VFMADD231PS = 8934, I_VFMADD231SD = 8973, I_VFMADD231SS = 8960, 228 | I_VFMADDSUB132PD = 8326, I_VFMADDSUB132PS = 8310, I_VFMADDSUB213PD = 8606, 229 | I_VFMADDSUB213PS = 8590, I_VFMADDSUB231PD = 8886, I_VFMADDSUB231PS = 8870, 230 | I_VFMSUB132PD = 8439, I_VFMSUB132PS = 8426, I_VFMSUB132SD = 8465, I_VFMSUB132SS = 8452, 231 | I_VFMSUB213PD = 8719, I_VFMSUB213PS = 8706, I_VFMSUB213SD = 8745, I_VFMSUB213SS = 8732, 232 | I_VFMSUB231PD = 8999, I_VFMSUB231PS = 8986, I_VFMSUB231SD = 9025, I_VFMSUB231SS = 9012, 233 | I_VFMSUBADD132PD = 8358, I_VFMSUBADD132PS = 8342, I_VFMSUBADD213PD = 8638, 234 | I_VFMSUBADD213PS = 8622, I_VFMSUBADD231PD = 8918, I_VFMSUBADD231PS = 8902, 235 | I_VFNMADD132PD = 8492, I_VFNMADD132PS = 8478, I_VFNMADD132SD = 8520, I_VFNMADD132SS = 8506, 236 | I_VFNMADD213PD = 8772, I_VFNMADD213PS = 8758, I_VFNMADD213SD = 8800, I_VFNMADD213SS = 8786, 237 | I_VFNMADD231PD = 9052, I_VFNMADD231PS = 9038, I_VFNMADD231SD = 9080, I_VFNMADD231SS = 9066, 238 | I_VFNMSUB132PD = 8548, I_VFNMSUB132PS = 8534, I_VFNMSUB132SD = 8576, I_VFNMSUB132SS = 8562, 239 | I_VFNMSUB213PD = 8828, I_VFNMSUB213PS = 8814, I_VFNMSUB213SD = 8856, I_VFNMSUB213SS = 8842, 240 | I_VFNMSUB231PD = 9108, I_VFNMSUB231PS = 9094, I_VFNMSUB231SD = 9136, I_VFNMSUB231SS = 9122, 241 | I_VHADDPD = 4197, I_VHADDPS = 4206, I_VHSUBPD = 4231, I_VHSUBPS = 4240, I_VINSERTF128 = 9503, 242 | I_VINSERTPS = 9557, I_VLDDQU = 7001, I_VLDMXCSR = 9941, I_VMASKMOVDQU = 7131, 243 | I_VMASKMOVPD = 7949, I_VMASKMOVPS = 7937, I_VMAXPD = 3588, I_VMAXPS = 3580, 244 | I_VMAXSD = 3604, I_VMAXSS = 3596, I_VMCALL = 1719, I_VMCLEAR = 9997, I_VMFUNC = 1787, 245 | I_VMINPD = 3468, I_VMINPS = 3460, I_VMINSD = 3484, I_VMINSS = 3476, I_VMLAUNCH = 1727, 246 | I_VMLOAD = 1811, I_VMMCALL = 1802, I_VMOVAPD = 2476, I_VMOVAPS = 2467, I_VMOVD = 3932, 247 | I_VMOVDDUP = 2234, I_VMOVDQA = 3962, I_VMOVDQU = 3971, I_VMOVHLPS = 2195, 248 | I_VMOVHPD = 2382, I_VMOVHPS = 2373, I_VMOVLHPS = 2363, I_VMOVLPD = 2214, I_VMOVLPS = 2205, 249 | I_VMOVMSKPD = 2836, I_VMOVMSKPS = 2825, I_VMOVNTDQ = 6858, I_VMOVNTDQA = 7905, 250 | I_VMOVNTPD = 2593, I_VMOVNTPS = 2583, I_VMOVQ = 3939, I_VMOVSD = 2143, I_VMOVSHDUP = 2391, 251 | I_VMOVSLDUP = 2223, I_VMOVSS = 2135, I_VMOVUPD = 2126, I_VMOVUPS = 2117, I_VMPSADBW = 9637, 252 | I_VMPTRLD = 9988, I_VMPTRST = 6385, I_VMREAD = 4128, I_VMRESUME = 1737, I_VMRUN = 1795, 253 | I_VMSAVE = 1819, I_VMULPD = 3199, I_VMULPS = 3191, I_VMULSD = 3215, I_VMULSS = 3207, 254 | I_VMWRITE = 4152, I_VMXOFF = 1747, I_VMXON = 10006, I_VORPD = 3066, I_VORPS = 3059, 255 | I_VPABSB = 7695, I_VPABSD = 7725, I_VPABSW = 7710, I_VPACKSSDW = 3859, I_VPACKSSWB = 3691, 256 | I_VPACKUSDW = 7926, I_VPACKUSWB = 3769, I_VPADDB = 7211, I_VPADDD = 7241, 257 | I_VPADDQ = 6488, I_VPADDSB = 6938, I_VPADDSW = 6955, I_VPADDUSW = 6629, I_VPADDW = 7226, 258 | I_VPALIGNR = 9419, I_VPAND = 6613, I_VPANDN = 6672, I_VPAVGB = 6687, I_VPAVGW = 6732, 259 | I_VPBLENDVB = 9692, I_VPBLENDW = 9400, I_VPCLMULQDQ = 9658, I_VPCMPEQB = 4052, 260 | I_VPCMPEQD = 4090, I_VPCMPEQQ = 7885, I_VPCMPEQW = 4071, I_VPCMPESTRI = 9737, 261 | I_VPCMPESTRM = 9714, I_VPCMPGTB = 3711, I_VPCMPGTD = 3749, I_VPCMPGTQ = 8096, 262 | I_VPCMPGTW = 3730, I_VPCMPISTRI = 9783, I_VPCMPISTRM = 9760, I_VPERM2F128 = 9265, 263 | I_VPERMILPD = 7570, I_VPERMILPS = 7559, I_VPEXTRB = 9437, I_VPEXTRD = 9462, 264 | I_VPEXTRQ = 9471, I_VPEXTRW = 6319, I_VPHADDD = 7383, I_VPHADDSW = 7401, I_VPHADDW = 7366, 265 | I_VPHMINPOSUW = 8271, I_VPHSUBD = 7459, I_VPHSUBSW = 7477, I_VPHSUBW = 7442, 266 | I_VPINSRB = 9538, I_VPINSRD = 9584, I_VPINSRQ = 9593, I_VPINSRW = 6302, I_VPMADDUBSW = 7422, 267 | I_VPMADDWD = 7082, I_VPMAXSB = 8182, I_VPMAXSD = 8199, I_VPMAXSW = 6972, I_VPMAXUB = 6656, 268 | I_VPMAXUD = 8233, I_VPMAXUW = 8216, I_VPMINSB = 8114, I_VPMINSD = 8131, I_VPMINSW = 6910, 269 | I_VPMINUB = 6598, I_VPMINUD = 8165, I_VPMINUW = 8148, I_VPMOVMSKB = 6541, 270 | I_VPMOVSXBD = 7764, I_VPMOVSXBQ = 7785, I_VPMOVSXBW = 7743, I_VPMOVSXDQ = 7848, 271 | I_VPMOVSXWD = 7806, I_VPMOVSXWQ = 7827, I_VPMOVZXBD = 7992, I_VPMOVZXBQ = 8013, 272 | I_VPMOVZXBW = 7971, I_VPMOVZXDQ = 8076, I_VPMOVZXWD = 8034, I_VPMOVZXWQ = 8055, 273 | I_VPMULDQ = 7867, I_VPMULHRSW = 7548, I_VPMULHUW = 6749, I_VPMULHW = 6767, 274 | I_VPMULLD = 8250, I_VPMULLW = 6504, I_VPMULUDQ = 7063, I_VPOR = 6924, I_VPSADBW = 7100, 275 | I_VPSHUFB = 7349, I_VPSHUFD = 4014, I_VPSHUFHW = 4023, I_VPSHUFLW = 4033, 276 | I_VPSIGNB = 7495, I_VPSIGND = 7529, I_VPSIGNW = 7512, I_VPSLLD = 7031, I_VPSLLDQ = 9855, 277 | I_VPSLLQ = 7046, I_VPSLLW = 7016, I_VPSRAD = 6717, I_VPSRAW = 6702, I_VPSRLD = 6458, 278 | I_VPSRLDQ = 9838, I_VPSRLQ = 6473, I_VPSRLW = 6443, I_VPSUBB = 7151, I_VPSUBD = 7181, 279 | I_VPSUBQ = 7196, I_VPSUBSB = 6876, I_VPSUBSW = 6893, I_VPSUBUSB = 6561, I_VPSUBUSW = 6580, 280 | I_VPSUBW = 7166, I_VPTEST = 7636, I_VPUNPCKHBW = 3791, I_VPUNPCKHDQ = 3837, 281 | I_VPUNPCKHQDQ = 3907, I_VPUNPCKHWD = 3814, I_VPUNPCKLBW = 3623, I_VPUNPCKLDQ = 3669, 282 | I_VPUNPCKLQDQ = 3882, I_VPUNPCKLWD = 3646, I_VPXOR = 6987, I_VRCPPS = 2967, 283 | I_VRCPSS = 2975, I_VROUNDPD = 9305, I_VROUNDPS = 9286, I_VROUNDSD = 9343, 284 | I_VROUNDSS = 9324, I_VRSQRTPS = 2933, I_VRSQRTSS = 2943, I_VSHUFPD = 6353, 285 | I_VSHUFPS = 6344, I_VSQRTPD = 2888, I_VSQRTPS = 2879, I_VSQRTSD = 2906, I_VSQRTSS = 2897, 286 | I_VSTMXCSR = 9970, I_VSUBPD = 3408, I_VSUBPS = 3400, I_VSUBSD = 3424, I_VSUBSS = 3416, 287 | I_VTESTPD = 7590, I_VTESTPS = 7581, I_VUCOMISD = 2761, I_VUCOMISS = 2751, 288 | I_VUNPCKHPD = 2317, I_VUNPCKHPS = 2306, I_VUNPCKLPD = 2275, I_VUNPCKLPS = 2264, 289 | I_VXORPD = 3095, I_VXORPS = 3087, I_VZEROALL = 4118, I_VZEROUPPER = 4106, 290 | I_WAIT = 10028, I_WBINVD = 561, I_WRFSBASE = 9931, I_WRGSBASE = 9960, I_WRMSR = 586, 291 | I_XADD = 946, I_XCHG = 212, I_XGETBV = 1771, I_XLAT = 400, I_XOR = 61, I_XORPD = 3080, 292 | I_XORPS = 3073, I_XRSTOR = 4273, I_XRSTOR64 = 4281, I_XSAVE = 4249, I_XSAVE64 = 4256, 293 | I_XSAVEOPT = 4299, I_XSAVEOPT64 = 4309, I_XSETBV = 1779, I__3DNOW = 10034 294 | } _InstructionType; 295 | 296 | typedef enum { 297 | R_RAX, R_RCX, R_RDX, R_RBX, R_RSP, R_RBP, R_RSI, R_RDI, R_R8, R_R9, R_R10, R_R11, R_R12, R_R13, R_R14, R_R15, 298 | R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI, R_R8D, R_R9D, R_R10D, R_R11D, R_R12D, R_R13D, R_R14D, R_R15D, 299 | R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI, R_R8W, R_R9W, R_R10W, R_R11W, R_R12W, R_R13W, R_R14W, R_R15W, 300 | R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH, R_R8B, R_R9B, R_R10B, R_R11B, R_R12B, R_R13B, R_R14B, R_R15B, 301 | R_SPL, R_BPL, R_SIL, R_DIL, 302 | R_ES, R_CS, R_SS, R_DS, R_FS, R_GS, 303 | R_RIP, 304 | R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7, 305 | R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7, 306 | R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7, R_XMM8, R_XMM9, R_XMM10, R_XMM11, R_XMM12, R_XMM13, R_XMM14, R_XMM15, 307 | R_YMM0, R_YMM1, R_YMM2, R_YMM3, R_YMM4, R_YMM5, R_YMM6, R_YMM7, R_YMM8, R_YMM9, R_YMM10, R_YMM11, R_YMM12, R_YMM13, R_YMM14, R_YMM15, 308 | R_CR0, R_UNUSED0, R_CR2, R_CR3, R_CR4, R_UNUSED1, R_UNUSED2, R_UNUSED3, R_CR8, 309 | R_DR0, R_DR1, R_DR2, R_DR3, R_UNUSED4, R_UNUSED5, R_DR6, R_DR7 310 | } _RegisterType; 311 | 312 | #endif /* MNEMONICS_H */ 313 | -------------------------------------------------------------------------------- /kextstat_aslr/mnemonics.c: -------------------------------------------------------------------------------- 1 | /* 2 | mnemonics.c 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #include "mnemonics.h" 25 | 26 | #ifndef DISTORM_LIGHT 27 | 28 | 29 | const unsigned char _MNEMONICS[] = 30 | "\x09" "UNDEFINED\0" "\x03" "ADD\0" "\x04" "PUSH\0" "\x03" "POP\0" "\x02" "OR\0" \ 31 | "\x03" "ADC\0" "\x03" "SBB\0" "\x03" "AND\0" "\x03" "DAA\0" "\x03" "SUB\0" \ 32 | "\x03" "DAS\0" "\x03" "XOR\0" "\x03" "AAA\0" "\x03" "CMP\0" "\x03" "AAS\0" \ 33 | "\x03" "INC\0" "\x03" "DEC\0" "\x05" "PUSHA\0" "\x04" "POPA\0" "\x05" "BOUND\0" \ 34 | "\x04" "ARPL\0" "\x04" "IMUL\0" "\x03" "INS\0" "\x04" "OUTS\0" "\x02" "JO\0" \ 35 | "\x03" "JNO\0" "\x02" "JB\0" "\x03" "JAE\0" "\x02" "JZ\0" "\x03" "JNZ\0" "\x03" "JBE\0" \ 36 | "\x02" "JA\0" "\x02" "JS\0" "\x03" "JNS\0" "\x02" "JP\0" "\x03" "JNP\0" "\x02" "JL\0" \ 37 | "\x03" "JGE\0" "\x03" "JLE\0" "\x02" "JG\0" "\x04" "TEST\0" "\x04" "XCHG\0" \ 38 | "\x03" "MOV\0" "\x03" "LEA\0" "\x03" "CBW\0" "\x04" "CWDE\0" "\x04" "CDQE\0" \ 39 | "\x03" "CWD\0" "\x03" "CDQ\0" "\x03" "CQO\0" "\x08" "CALL FAR\0" "\x05" "PUSHF\0" \ 40 | "\x04" "POPF\0" "\x04" "SAHF\0" "\x04" "LAHF\0" "\x04" "MOVS\0" "\x04" "CMPS\0" \ 41 | "\x04" "STOS\0" "\x04" "LODS\0" "\x04" "SCAS\0" "\x03" "RET\0" "\x03" "LES\0" \ 42 | "\x03" "LDS\0" "\x05" "ENTER\0" "\x05" "LEAVE\0" "\x04" "RETF\0" "\x05" "INT 3\0" \ 43 | "\x03" "INT\0" "\x04" "INTO\0" "\x04" "IRET\0" "\x03" "AAM\0" "\x03" "AAD\0" \ 44 | "\x04" "SALC\0" "\x04" "XLAT\0" "\x06" "LOOPNZ\0" "\x05" "LOOPZ\0" "\x04" "LOOP\0" \ 45 | "\x04" "JCXZ\0" "\x05" "JECXZ\0" "\x05" "JRCXZ\0" "\x02" "IN\0" "\x03" "OUT\0" \ 46 | "\x04" "CALL\0" "\x03" "JMP\0" "\x07" "JMP FAR\0" "\x04" "INT1\0" "\x03" "HLT\0" \ 47 | "\x03" "CMC\0" "\x03" "CLC\0" "\x03" "STC\0" "\x03" "CLI\0" "\x03" "STI\0" \ 48 | "\x03" "CLD\0" "\x03" "STD\0" "\x03" "LAR\0" "\x03" "LSL\0" "\x07" "SYSCALL\0" \ 49 | "\x04" "CLTS\0" "\x06" "SYSRET\0" "\x04" "INVD\0" "\x06" "WBINVD\0" "\x03" "UD2\0" \ 50 | "\x05" "FEMMS\0" "\x03" "NOP\0" "\x05" "WRMSR\0" "\x05" "RDTSC\0" "\x05" "RDMSR\0" \ 51 | "\x05" "RDPMC\0" "\x08" "SYSENTER\0" "\x07" "SYSEXIT\0" "\x06" "GETSEC\0" "\x05" "CMOVO\0" \ 52 | "\x06" "CMOVNO\0" "\x05" "CMOVB\0" "\x06" "CMOVAE\0" "\x05" "CMOVZ\0" "\x06" "CMOVNZ\0" \ 53 | "\x06" "CMOVBE\0" "\x05" "CMOVA\0" "\x05" "CMOVS\0" "\x06" "CMOVNS\0" "\x05" "CMOVP\0" \ 54 | "\x06" "CMOVNP\0" "\x05" "CMOVL\0" "\x06" "CMOVGE\0" "\x06" "CMOVLE\0" "\x05" "CMOVG\0" \ 55 | "\x04" "SETO\0" "\x05" "SETNO\0" "\x04" "SETB\0" "\x05" "SETAE\0" "\x04" "SETZ\0" \ 56 | "\x05" "SETNZ\0" "\x05" "SETBE\0" "\x04" "SETA\0" "\x04" "SETS\0" "\x05" "SETNS\0" \ 57 | "\x04" "SETP\0" "\x05" "SETNP\0" "\x04" "SETL\0" "\x05" "SETGE\0" "\x05" "SETLE\0" \ 58 | "\x04" "SETG\0" "\x05" "CPUID\0" "\x02" "BT\0" "\x04" "SHLD\0" "\x03" "RSM\0" \ 59 | "\x03" "BTS\0" "\x04" "SHRD\0" "\x07" "CMPXCHG\0" "\x03" "LSS\0" "\x03" "BTR\0" \ 60 | "\x03" "LFS\0" "\x03" "LGS\0" "\x05" "MOVZX\0" "\x03" "BTC\0" "\x05" "MOVSX\0" \ 61 | "\x04" "XADD\0" "\x06" "MOVNTI\0" "\x05" "BSWAP\0" "\x03" "ROL\0" "\x03" "ROR\0" \ 62 | "\x03" "RCL\0" "\x03" "RCR\0" "\x03" "SHL\0" "\x03" "SHR\0" "\x03" "SAL\0" \ 63 | "\x03" "SAR\0" "\x04" "FADD\0" "\x04" "FMUL\0" "\x04" "FCOM\0" "\x05" "FCOMP\0" \ 64 | "\x04" "FSUB\0" "\x05" "FSUBR\0" "\x04" "FDIV\0" "\x05" "FDIVR\0" "\x03" "FLD\0" \ 65 | "\x03" "FST\0" "\x04" "FSTP\0" "\x06" "FLDENV\0" "\x05" "FLDCW\0" "\x04" "FXCH\0" \ 66 | "\x04" "FNOP\0" "\x04" "FCHS\0" "\x04" "FABS\0" "\x04" "FTST\0" "\x04" "FXAM\0" \ 67 | "\x04" "FLD1\0" "\x06" "FLDL2T\0" "\x06" "FLDL2E\0" "\x05" "FLDPI\0" "\x06" "FLDLG2\0" \ 68 | "\x06" "FLDLN2\0" "\x04" "FLDZ\0" "\x05" "F2XM1\0" "\x05" "FYL2X\0" "\x05" "FPTAN\0" \ 69 | "\x06" "FPATAN\0" "\x07" "FXTRACT\0" "\x06" "FPREM1\0" "\x07" "FDECSTP\0" "\x07" "FINCSTP\0" \ 70 | "\x05" "FPREM\0" "\x07" "FYL2XP1\0" "\x05" "FSQRT\0" "\x07" "FSINCOS\0" "\x07" "FRNDINT\0" \ 71 | "\x06" "FSCALE\0" "\x04" "FSIN\0" "\x04" "FCOS\0" "\x05" "FIADD\0" "\x05" "FIMUL\0" \ 72 | "\x05" "FICOM\0" "\x06" "FICOMP\0" "\x05" "FISUB\0" "\x06" "FISUBR\0" "\x05" "FIDIV\0" \ 73 | "\x06" "FIDIVR\0" "\x06" "FCMOVB\0" "\x06" "FCMOVE\0" "\x07" "FCMOVBE\0" "\x06" "FCMOVU\0" \ 74 | "\x07" "FUCOMPP\0" "\x04" "FILD\0" "\x06" "FISTTP\0" "\x04" "FIST\0" "\x05" "FISTP\0" \ 75 | "\x07" "FCMOVNB\0" "\x07" "FCMOVNE\0" "\x08" "FCMOVNBE\0" "\x07" "FCMOVNU\0" \ 76 | "\x04" "FENI\0" "\x06" "FEDISI\0" "\x06" "FSETPM\0" "\x06" "FUCOMI\0" "\x05" "FCOMI\0" \ 77 | "\x06" "FRSTOR\0" "\x05" "FFREE\0" "\x05" "FUCOM\0" "\x06" "FUCOMP\0" "\x05" "FADDP\0" \ 78 | "\x05" "FMULP\0" "\x06" "FCOMPP\0" "\x06" "FSUBRP\0" "\x05" "FSUBP\0" "\x06" "FDIVRP\0" \ 79 | "\x05" "FDIVP\0" "\x04" "FBLD\0" "\x05" "FBSTP\0" "\x07" "FUCOMIP\0" "\x06" "FCOMIP\0" \ 80 | "\x03" "NOT\0" "\x03" "NEG\0" "\x03" "MUL\0" "\x03" "DIV\0" "\x04" "IDIV\0" \ 81 | "\x04" "SLDT\0" "\x03" "STR\0" "\x04" "LLDT\0" "\x03" "LTR\0" "\x04" "VERR\0" \ 82 | "\x04" "VERW\0" "\x04" "SGDT\0" "\x04" "SIDT\0" "\x04" "LGDT\0" "\x04" "LIDT\0" \ 83 | "\x04" "SMSW\0" "\x04" "LMSW\0" "\x06" "INVLPG\0" "\x06" "VMCALL\0" "\x08" "VMLAUNCH\0" \ 84 | "\x08" "VMRESUME\0" "\x06" "VMXOFF\0" "\x07" "MONITOR\0" "\x05" "MWAIT\0" "\x06" "XGETBV\0" \ 85 | "\x06" "XSETBV\0" "\x06" "VMFUNC\0" "\x05" "VMRUN\0" "\x07" "VMMCALL\0" "\x06" "VMLOAD\0" \ 86 | "\x06" "VMSAVE\0" "\x04" "STGI\0" "\x04" "CLGI\0" "\x06" "SKINIT\0" "\x07" "INVLPGA\0" \ 87 | "\x06" "SWAPGS\0" "\x06" "RDTSCP\0" "\x08" "PREFETCH\0" "\x09" "PREFETCHW\0" \ 88 | "\x05" "PI2FW\0" "\x05" "PI2FD\0" "\x05" "PF2IW\0" "\x05" "PF2ID\0" "\x06" "PFNACC\0" \ 89 | "\x07" "PFPNACC\0" "\x07" "PFCMPGE\0" "\x05" "PFMIN\0" "\x05" "PFRCP\0" "\x07" "PFRSQRT\0" \ 90 | "\x05" "PFSUB\0" "\x05" "PFADD\0" "\x07" "PFCMPGT\0" "\x05" "PFMAX\0" "\x08" "PFRCPIT1\0" \ 91 | "\x08" "PFRSQIT1\0" "\x06" "PFSUBR\0" "\x05" "PFACC\0" "\x07" "PFCMPEQ\0" "\x05" "PFMUL\0" \ 92 | "\x08" "PFRCPIT2\0" "\x07" "PMULHRW\0" "\x06" "PSWAPD\0" "\x07" "PAVGUSB\0" \ 93 | "\x06" "MOVUPS\0" "\x06" "MOVUPD\0" "\x05" "MOVSS\0" "\x05" "MOVSD\0" "\x07" "VMOVUPS\0" \ 94 | "\x07" "VMOVUPD\0" "\x06" "VMOVSS\0" "\x06" "VMOVSD\0" "\x07" "MOVHLPS\0" "\x06" "MOVLPS\0" \ 95 | "\x06" "MOVLPD\0" "\x08" "MOVSLDUP\0" "\x07" "MOVDDUP\0" "\x08" "VMOVHLPS\0" \ 96 | "\x07" "VMOVLPS\0" "\x07" "VMOVLPD\0" "\x09" "VMOVSLDUP\0" "\x08" "VMOVDDUP\0" \ 97 | "\x08" "UNPCKLPS\0" "\x08" "UNPCKLPD\0" "\x09" "VUNPCKLPS\0" "\x09" "VUNPCKLPD\0" \ 98 | "\x08" "UNPCKHPS\0" "\x08" "UNPCKHPD\0" "\x09" "VUNPCKHPS\0" "\x09" "VUNPCKHPD\0" \ 99 | "\x07" "MOVLHPS\0" "\x06" "MOVHPS\0" "\x06" "MOVHPD\0" "\x08" "MOVSHDUP\0" \ 100 | "\x08" "VMOVLHPS\0" "\x07" "VMOVHPS\0" "\x07" "VMOVHPD\0" "\x09" "VMOVSHDUP\0" \ 101 | "\x0b" "PREFETCHNTA\0" "\x0a" "PREFETCHT0\0" "\x0a" "PREFETCHT1\0" "\x0a" "PREFETCHT2\0" \ 102 | "\x06" "MOVAPS\0" "\x06" "MOVAPD\0" "\x07" "VMOVAPS\0" "\x07" "VMOVAPD\0" "\x08" "CVTPI2PS\0" \ 103 | "\x08" "CVTPI2PD\0" "\x08" "CVTSI2SS\0" "\x08" "CVTSI2SD\0" "\x09" "VCVTSI2SS\0" \ 104 | "\x09" "VCVTSI2SD\0" "\x07" "MOVNTPS\0" "\x07" "MOVNTPD\0" "\x07" "MOVNTSS\0" \ 105 | "\x07" "MOVNTSD\0" "\x08" "VMOVNTPS\0" "\x08" "VMOVNTPD\0" "\x09" "CVTTPS2PI\0" \ 106 | "\x09" "CVTTPD2PI\0" "\x09" "CVTTSS2SI\0" "\x09" "CVTTSD2SI\0" "\x0a" "VCVTTSS2SI\0" \ 107 | "\x0a" "VCVTTSD2SI\0" "\x08" "CVTPS2PI\0" "\x08" "CVTPD2PI\0" "\x08" "CVTSS2SI\0" \ 108 | "\x08" "CVTSD2SI\0" "\x09" "VCVTSS2SI\0" "\x09" "VCVTSD2SI\0" "\x07" "UCOMISS\0" \ 109 | "\x07" "UCOMISD\0" "\x08" "VUCOMISS\0" "\x08" "VUCOMISD\0" "\x06" "COMISS\0" \ 110 | "\x06" "COMISD\0" "\x07" "VCOMISS\0" "\x07" "VCOMISD\0" "\x08" "MOVMSKPS\0" \ 111 | "\x08" "MOVMSKPD\0" "\x09" "VMOVMSKPS\0" "\x09" "VMOVMSKPD\0" "\x06" "SQRTPS\0" \ 112 | "\x06" "SQRTPD\0" "\x06" "SQRTSS\0" "\x06" "SQRTSD\0" "\x07" "VSQRTPS\0" "\x07" "VSQRTPD\0" \ 113 | "\x07" "VSQRTSS\0" "\x07" "VSQRTSD\0" "\x07" "RSQRTPS\0" "\x07" "RSQRTSS\0" \ 114 | "\x08" "VRSQRTPS\0" "\x08" "VRSQRTSS\0" "\x05" "RCPPS\0" "\x05" "RCPSS\0" "\x06" "VRCPPS\0" \ 115 | "\x06" "VRCPSS\0" "\x05" "ANDPS\0" "\x05" "ANDPD\0" "\x06" "VANDPS\0" "\x06" "VANDPD\0" \ 116 | "\x06" "ANDNPS\0" "\x06" "ANDNPD\0" "\x07" "VANDNPS\0" "\x07" "VANDNPD\0" "\x04" "ORPS\0" \ 117 | "\x04" "ORPD\0" "\x05" "VORPS\0" "\x05" "VORPD\0" "\x05" "XORPS\0" "\x05" "XORPD\0" \ 118 | "\x06" "VXORPS\0" "\x06" "VXORPD\0" "\x05" "ADDPS\0" "\x05" "ADDPD\0" "\x05" "ADDSS\0" \ 119 | "\x05" "ADDSD\0" "\x06" "VADDPS\0" "\x06" "VADDPD\0" "\x06" "VADDSS\0" "\x06" "VADDSD\0" \ 120 | "\x05" "MULPS\0" "\x05" "MULPD\0" "\x05" "MULSS\0" "\x05" "MULSD\0" "\x06" "VMULPS\0" \ 121 | "\x06" "VMULPD\0" "\x06" "VMULSS\0" "\x06" "VMULSD\0" "\x08" "CVTPS2PD\0" "\x08" "CVTPD2PS\0" \ 122 | "\x08" "CVTSS2SD\0" "\x08" "CVTSD2SS\0" "\x09" "VCVTPS2PD\0" "\x09" "VCVTPD2PS\0" \ 123 | "\x09" "VCVTSS2SD\0" "\x09" "VCVTSD2SS\0" "\x08" "CVTDQ2PS\0" "\x08" "CVTPS2DQ\0" \ 124 | "\x09" "CVTTPS2DQ\0" "\x09" "VCVTDQ2PS\0" "\x09" "VCVTPS2DQ\0" "\x0a" "VCVTTPS2DQ\0" \ 125 | "\x05" "SUBPS\0" "\x05" "SUBPD\0" "\x05" "SUBSS\0" "\x05" "SUBSD\0" "\x06" "VSUBPS\0" \ 126 | "\x06" "VSUBPD\0" "\x06" "VSUBSS\0" "\x06" "VSUBSD\0" "\x05" "MINPS\0" "\x05" "MINPD\0" \ 127 | "\x05" "MINSS\0" "\x05" "MINSD\0" "\x06" "VMINPS\0" "\x06" "VMINPD\0" "\x06" "VMINSS\0" \ 128 | "\x06" "VMINSD\0" "\x05" "DIVPS\0" "\x05" "DIVPD\0" "\x05" "DIVSS\0" "\x05" "DIVSD\0" \ 129 | "\x06" "VDIVPS\0" "\x06" "VDIVPD\0" "\x06" "VDIVSS\0" "\x06" "VDIVSD\0" "\x05" "MAXPS\0" \ 130 | "\x05" "MAXPD\0" "\x05" "MAXSS\0" "\x05" "MAXSD\0" "\x06" "VMAXPS\0" "\x06" "VMAXPD\0" \ 131 | "\x06" "VMAXSS\0" "\x06" "VMAXSD\0" "\x09" "PUNPCKLBW\0" "\x0a" "VPUNPCKLBW\0" \ 132 | "\x09" "PUNPCKLWD\0" "\x0a" "VPUNPCKLWD\0" "\x09" "PUNPCKLDQ\0" "\x0a" "VPUNPCKLDQ\0" \ 133 | "\x08" "PACKSSWB\0" "\x09" "VPACKSSWB\0" "\x07" "PCMPGTB\0" "\x08" "VPCMPGTB\0" \ 134 | "\x07" "PCMPGTW\0" "\x08" "VPCMPGTW\0" "\x07" "PCMPGTD\0" "\x08" "VPCMPGTD\0" \ 135 | "\x08" "PACKUSWB\0" "\x09" "VPACKUSWB\0" "\x09" "PUNPCKHBW\0" "\x0a" "VPUNPCKHBW\0" \ 136 | "\x09" "PUNPCKHWD\0" "\x0a" "VPUNPCKHWD\0" "\x09" "PUNPCKHDQ\0" "\x0a" "VPUNPCKHDQ\0" \ 137 | "\x08" "PACKSSDW\0" "\x09" "VPACKSSDW\0" "\x0a" "PUNPCKLQDQ\0" "\x0b" "VPUNPCKLQDQ\0" \ 138 | "\x0a" "PUNPCKHQDQ\0" "\x0b" "VPUNPCKHQDQ\0" "\x04" "MOVD\0" "\x04" "MOVQ\0" \ 139 | "\x05" "VMOVD\0" "\x05" "VMOVQ\0" "\x06" "MOVDQA\0" "\x06" "MOVDQU\0" "\x07" "VMOVDQA\0" \ 140 | "\x07" "VMOVDQU\0" "\x06" "PSHUFW\0" "\x06" "PSHUFD\0" "\x07" "PSHUFHW\0" "\x07" "PSHUFLW\0" \ 141 | "\x07" "VPSHUFD\0" "\x08" "VPSHUFHW\0" "\x08" "VPSHUFLW\0" "\x07" "PCMPEQB\0" \ 142 | "\x08" "VPCMPEQB\0" "\x07" "PCMPEQW\0" "\x08" "VPCMPEQW\0" "\x07" "PCMPEQD\0" \ 143 | "\x08" "VPCMPEQD\0" "\x04" "EMMS\0" "\x0a" "VZEROUPPER\0" "\x08" "VZEROALL\0" \ 144 | "\x06" "VMREAD\0" "\x05" "EXTRQ\0" "\x07" "INSERTQ\0" "\x07" "VMWRITE\0" "\x08" "CVTPH2PS\0" \ 145 | "\x08" "CVTPS2PH\0" "\x06" "HADDPD\0" "\x06" "HADDPS\0" "\x07" "VHADDPD\0" \ 146 | "\x07" "VHADDPS\0" "\x06" "HSUBPD\0" "\x06" "HSUBPS\0" "\x07" "VHSUBPD\0" "\x07" "VHSUBPS\0" \ 147 | "\x05" "XSAVE\0" "\x07" "XSAVE64\0" "\x06" "LFENCE\0" "\x06" "XRSTOR\0" "\x08" "XRSTOR64\0" \ 148 | "\x06" "MFENCE\0" "\x08" "XSAVEOPT\0" "\x0a" "XSAVEOPT64\0" "\x06" "SFENCE\0" \ 149 | "\x07" "CLFLUSH\0" "\x06" "POPCNT\0" "\x03" "BSF\0" "\x05" "TZCNT\0" "\x03" "BSR\0" \ 150 | "\x05" "LZCNT\0" "\x07" "CMPEQPS\0" "\x07" "CMPLTPS\0" "\x07" "CMPLEPS\0" "\x0a" "CMPUNORDPS\0" \ 151 | "\x08" "CMPNEQPS\0" "\x08" "CMPNLTPS\0" "\x08" "CMPNLEPS\0" "\x08" "CMPORDPS\0" \ 152 | "\x07" "CMPEQPD\0" "\x07" "CMPLTPD\0" "\x07" "CMPLEPD\0" "\x0a" "CMPUNORDPD\0" \ 153 | "\x08" "CMPNEQPD\0" "\x08" "CMPNLTPD\0" "\x08" "CMPNLEPD\0" "\x08" "CMPORDPD\0" \ 154 | "\x07" "CMPEQSS\0" "\x07" "CMPLTSS\0" "\x07" "CMPLESS\0" "\x0a" "CMPUNORDSS\0" \ 155 | "\x08" "CMPNEQSS\0" "\x08" "CMPNLTSS\0" "\x08" "CMPNLESS\0" "\x08" "CMPORDSS\0" \ 156 | "\x07" "CMPEQSD\0" "\x07" "CMPLTSD\0" "\x07" "CMPLESD\0" "\x0a" "CMPUNORDSD\0" \ 157 | "\x08" "CMPNEQSD\0" "\x08" "CMPNLTSD\0" "\x08" "CMPNLESD\0" "\x08" "CMPORDSD\0" \ 158 | "\x08" "VCMPEQPS\0" "\x08" "VCMPLTPS\0" "\x08" "VCMPLEPS\0" "\x0b" "VCMPUNORDPS\0" \ 159 | "\x09" "VCMPNEQPS\0" "\x09" "VCMPNLTPS\0" "\x09" "VCMPNLEPS\0" "\x09" "VCMPORDPS\0" \ 160 | "\x0b" "VCMPEQ_UQPS\0" "\x09" "VCMPNGEPS\0" "\x09" "VCMPNGTPS\0" "\x0b" "VCMPFALSEPS\0" \ 161 | "\x0c" "VCMPNEQ_OQPS\0" "\x08" "VCMPGEPS\0" "\x08" "VCMPGTPS\0" "\x0a" "VCMPTRUEPS\0" \ 162 | "\x0b" "VCMPEQ_OSPS\0" "\x0b" "VCMPLT_OQPS\0" "\x0b" "VCMPLE_OQPS\0" "\x0d" "VCMPUNORD_SPS\0" \ 163 | "\x0c" "VCMPNEQ_USPS\0" "\x0c" "VCMPNLT_UQPS\0" "\x0c" "VCMPNLE_UQPS\0" "\x0b" "VCMPORD_SPS\0" \ 164 | "\x0b" "VCMPEQ_USPS\0" "\x0c" "VCMPNGE_UQPS\0" "\x0c" "VCMPNGT_UQPS\0" "\x0e" "VCMPFALSE_OSPS\0" \ 165 | "\x0c" "VCMPNEQ_OSPS\0" "\x0b" "VCMPGE_OQPS\0" "\x0b" "VCMPGT_OQPS\0" "\x0d" "VCMPTRUE_USPS\0" \ 166 | "\x08" "VCMPEQPD\0" "\x08" "VCMPLTPD\0" "\x08" "VCMPLEPD\0" "\x0b" "VCMPUNORDPD\0" \ 167 | "\x09" "VCMPNEQPD\0" "\x09" "VCMPNLTPD\0" "\x09" "VCMPNLEPD\0" "\x09" "VCMPORDPD\0" \ 168 | "\x0b" "VCMPEQ_UQPD\0" "\x09" "VCMPNGEPD\0" "\x09" "VCMPNGTPD\0" "\x0b" "VCMPFALSEPD\0" \ 169 | "\x0c" "VCMPNEQ_OQPD\0" "\x08" "VCMPGEPD\0" "\x08" "VCMPGTPD\0" "\x0a" "VCMPTRUEPD\0" \ 170 | "\x0b" "VCMPEQ_OSPD\0" "\x0b" "VCMPLT_OQPD\0" "\x0b" "VCMPLE_OQPD\0" "\x0d" "VCMPUNORD_SPD\0" \ 171 | "\x0c" "VCMPNEQ_USPD\0" "\x0c" "VCMPNLT_UQPD\0" "\x0c" "VCMPNLE_UQPD\0" "\x0b" "VCMPORD_SPD\0" \ 172 | "\x0b" "VCMPEQ_USPD\0" "\x0c" "VCMPNGE_UQPD\0" "\x0c" "VCMPNGT_UQPD\0" "\x0e" "VCMPFALSE_OSPD\0" \ 173 | "\x0c" "VCMPNEQ_OSPD\0" "\x0b" "VCMPGE_OQPD\0" "\x0b" "VCMPGT_OQPD\0" "\x0d" "VCMPTRUE_USPD\0" \ 174 | "\x08" "VCMPEQSS\0" "\x08" "VCMPLTSS\0" "\x08" "VCMPLESS\0" "\x0b" "VCMPUNORDSS\0" \ 175 | "\x09" "VCMPNEQSS\0" "\x09" "VCMPNLTSS\0" "\x09" "VCMPNLESS\0" "\x09" "VCMPORDSS\0" \ 176 | "\x0b" "VCMPEQ_UQSS\0" "\x09" "VCMPNGESS\0" "\x09" "VCMPNGTSS\0" "\x0b" "VCMPFALSESS\0" \ 177 | "\x0c" "VCMPNEQ_OQSS\0" "\x08" "VCMPGESS\0" "\x08" "VCMPGTSS\0" "\x0a" "VCMPTRUESS\0" \ 178 | "\x0b" "VCMPEQ_OSSS\0" "\x0b" "VCMPLT_OQSS\0" "\x0b" "VCMPLE_OQSS\0" "\x0d" "VCMPUNORD_SSS\0" \ 179 | "\x0c" "VCMPNEQ_USSS\0" "\x0c" "VCMPNLT_UQSS\0" "\x0c" "VCMPNLE_UQSS\0" "\x0b" "VCMPORD_SSS\0" \ 180 | "\x0b" "VCMPEQ_USSS\0" "\x0c" "VCMPNGE_UQSS\0" "\x0c" "VCMPNGT_UQSS\0" "\x0e" "VCMPFALSE_OSSS\0" \ 181 | "\x0c" "VCMPNEQ_OSSS\0" "\x0b" "VCMPGE_OQSS\0" "\x0b" "VCMPGT_OQSS\0" "\x0d" "VCMPTRUE_USSS\0" \ 182 | "\x08" "VCMPEQSD\0" "\x08" "VCMPLTSD\0" "\x08" "VCMPLESD\0" "\x0b" "VCMPUNORDSD\0" \ 183 | "\x09" "VCMPNEQSD\0" "\x09" "VCMPNLTSD\0" "\x09" "VCMPNLESD\0" "\x09" "VCMPORDSD\0" \ 184 | "\x0b" "VCMPEQ_UQSD\0" "\x09" "VCMPNGESD\0" "\x09" "VCMPNGTSD\0" "\x0b" "VCMPFALSESD\0" \ 185 | "\x0c" "VCMPNEQ_OQSD\0" "\x08" "VCMPGESD\0" "\x08" "VCMPGTSD\0" "\x0a" "VCMPTRUESD\0" \ 186 | "\x0b" "VCMPEQ_OSSD\0" "\x0b" "VCMPLT_OQSD\0" "\x0b" "VCMPLE_OQSD\0" "\x0d" "VCMPUNORD_SSD\0" \ 187 | "\x0c" "VCMPNEQ_USSD\0" "\x0c" "VCMPNLT_UQSD\0" "\x0c" "VCMPNLE_UQSD\0" "\x0b" "VCMPORD_SSD\0" \ 188 | "\x0b" "VCMPEQ_USSD\0" "\x0c" "VCMPNGE_UQSD\0" "\x0c" "VCMPNGT_UQSD\0" "\x0e" "VCMPFALSE_OSSD\0" \ 189 | "\x0c" "VCMPNEQ_OSSD\0" "\x0b" "VCMPGE_OQSD\0" "\x0b" "VCMPGT_OQSD\0" "\x0d" "VCMPTRUE_USSD\0" \ 190 | "\x06" "PINSRW\0" "\x07" "VPINSRW\0" "\x06" "PEXTRW\0" "\x07" "VPEXTRW\0" "\x06" "SHUFPS\0" \ 191 | "\x06" "SHUFPD\0" "\x07" "VSHUFPS\0" "\x07" "VSHUFPD\0" "\x09" "CMPXCHG8B\0" \ 192 | "\x0a" "CMPXCHG16B\0" "\x07" "VMPTRST\0" "\x08" "ADDSUBPD\0" "\x08" "ADDSUBPS\0" \ 193 | "\x09" "VADDSUBPD\0" "\x09" "VADDSUBPS\0" "\x05" "PSRLW\0" "\x06" "VPSRLW\0" \ 194 | "\x05" "PSRLD\0" "\x06" "VPSRLD\0" "\x05" "PSRLQ\0" "\x06" "VPSRLQ\0" "\x05" "PADDQ\0" \ 195 | "\x06" "VPADDQ\0" "\x06" "PMULLW\0" "\x07" "VPMULLW\0" "\x07" "MOVQ2DQ\0" "\x07" "MOVDQ2Q\0" \ 196 | "\x08" "PMOVMSKB\0" "\x09" "VPMOVMSKB\0" "\x07" "PSUBUSB\0" "\x08" "VPSUBUSB\0" \ 197 | "\x07" "PSUBUSW\0" "\x08" "VPSUBUSW\0" "\x06" "PMINUB\0" "\x07" "VPMINUB\0" \ 198 | "\x04" "PAND\0" "\x05" "VPAND\0" "\x07" "PADDUSB\0" "\x08" "VPADDUSW\0" "\x07" "PADDUSW\0" \ 199 | "\x06" "PMAXUB\0" "\x07" "VPMAXUB\0" "\x05" "PANDN\0" "\x06" "VPANDN\0" "\x05" "PAVGB\0" \ 200 | "\x06" "VPAVGB\0" "\x05" "PSRAW\0" "\x06" "VPSRAW\0" "\x05" "PSRAD\0" "\x06" "VPSRAD\0" \ 201 | "\x05" "PAVGW\0" "\x06" "VPAVGW\0" "\x07" "PMULHUW\0" "\x08" "VPMULHUW\0" "\x06" "PMULHW\0" \ 202 | "\x07" "VPMULHW\0" "\x09" "CVTTPD2DQ\0" "\x08" "CVTDQ2PD\0" "\x08" "CVTPD2DQ\0" \ 203 | "\x0a" "VCVTTPD2DQ\0" "\x09" "VCVTDQ2PD\0" "\x09" "VCVTPD2DQ\0" "\x06" "MOVNTQ\0" \ 204 | "\x07" "MOVNTDQ\0" "\x08" "VMOVNTDQ\0" "\x06" "PSUBSB\0" "\x07" "VPSUBSB\0" \ 205 | "\x06" "PSUBSW\0" "\x07" "VPSUBSW\0" "\x06" "PMINSW\0" "\x07" "VPMINSW\0" "\x03" "POR\0" \ 206 | "\x04" "VPOR\0" "\x06" "PADDSB\0" "\x07" "VPADDSB\0" "\x06" "PADDSW\0" "\x07" "VPADDSW\0" \ 207 | "\x06" "PMAXSW\0" "\x07" "VPMAXSW\0" "\x04" "PXOR\0" "\x05" "VPXOR\0" "\x05" "LDDQU\0" \ 208 | "\x06" "VLDDQU\0" "\x05" "PSLLW\0" "\x06" "VPSLLW\0" "\x05" "PSLLD\0" "\x06" "VPSLLD\0" \ 209 | "\x05" "PSLLQ\0" "\x06" "VPSLLQ\0" "\x07" "PMULUDQ\0" "\x08" "VPMULUDQ\0" "\x07" "PMADDWD\0" \ 210 | "\x08" "VPMADDWD\0" "\x06" "PSADBW\0" "\x07" "VPSADBW\0" "\x08" "MASKMOVQ\0" \ 211 | "\x0a" "MASKMOVDQU\0" "\x0b" "VMASKMOVDQU\0" "\x05" "PSUBB\0" "\x06" "VPSUBB\0" \ 212 | "\x05" "PSUBW\0" "\x06" "VPSUBW\0" "\x05" "PSUBD\0" "\x06" "VPSUBD\0" "\x05" "PSUBQ\0" \ 213 | "\x06" "VPSUBQ\0" "\x05" "PADDB\0" "\x06" "VPADDB\0" "\x05" "PADDW\0" "\x06" "VPADDW\0" \ 214 | "\x05" "PADDD\0" "\x06" "VPADDD\0" "\x07" "FNSTENV\0" "\x06" "FSTENV\0" "\x06" "FNSTCW\0" \ 215 | "\x05" "FSTCW\0" "\x06" "FNCLEX\0" "\x05" "FCLEX\0" "\x06" "FNINIT\0" "\x05" "FINIT\0" \ 216 | "\x06" "FNSAVE\0" "\x05" "FSAVE\0" "\x06" "FNSTSW\0" "\x05" "FSTSW\0" "\x06" "PSHUFB\0" \ 217 | "\x07" "VPSHUFB\0" "\x06" "PHADDW\0" "\x07" "VPHADDW\0" "\x06" "PHADDD\0" "\x07" "VPHADDD\0" \ 218 | "\x07" "PHADDSW\0" "\x08" "VPHADDSW\0" "\x09" "PMADDUBSW\0" "\x0a" "VPMADDUBSW\0" \ 219 | "\x06" "PHSUBW\0" "\x07" "VPHSUBW\0" "\x06" "PHSUBD\0" "\x07" "VPHSUBD\0" "\x07" "PHSUBSW\0" \ 220 | "\x08" "VPHSUBSW\0" "\x06" "PSIGNB\0" "\x07" "VPSIGNB\0" "\x06" "PSIGNW\0" \ 221 | "\x07" "VPSIGNW\0" "\x06" "PSIGND\0" "\x07" "VPSIGND\0" "\x08" "PMULHRSW\0" \ 222 | "\x09" "VPMULHRSW\0" "\x09" "VPERMILPS\0" "\x09" "VPERMILPD\0" "\x07" "VTESTPS\0" \ 223 | "\x07" "VTESTPD\0" "\x08" "PBLENDVB\0" "\x08" "BLENDVPS\0" "\x08" "BLENDVPD\0" \ 224 | "\x05" "PTEST\0" "\x06" "VPTEST\0" "\x0c" "VBROADCASTSS\0" "\x0c" "VBROADCASTSD\0" \ 225 | "\x0e" "VBROADCASTF128\0" "\x05" "PABSB\0" "\x06" "VPABSB\0" "\x05" "PABSW\0" \ 226 | "\x06" "VPABSW\0" "\x05" "PABSD\0" "\x06" "VPABSD\0" "\x08" "PMOVSXBW\0" "\x09" "VPMOVSXBW\0" \ 227 | "\x08" "PMOVSXBD\0" "\x09" "VPMOVSXBD\0" "\x08" "PMOVSXBQ\0" "\x09" "VPMOVSXBQ\0" \ 228 | "\x08" "PMOVSXWD\0" "\x09" "VPMOVSXWD\0" "\x08" "PMOVSXWQ\0" "\x09" "VPMOVSXWQ\0" \ 229 | "\x08" "PMOVSXDQ\0" "\x09" "VPMOVSXDQ\0" "\x06" "PMULDQ\0" "\x07" "VPMULDQ\0" \ 230 | "\x07" "PCMPEQQ\0" "\x08" "VPCMPEQQ\0" "\x08" "MOVNTDQA\0" "\x09" "VMOVNTDQA\0" \ 231 | "\x08" "PACKUSDW\0" "\x09" "VPACKUSDW\0" "\x0a" "VMASKMOVPS\0" "\x0a" "VMASKMOVPD\0" \ 232 | "\x08" "PMOVZXBW\0" "\x09" "VPMOVZXBW\0" "\x08" "PMOVZXBD\0" "\x09" "VPMOVZXBD\0" \ 233 | "\x08" "PMOVZXBQ\0" "\x09" "VPMOVZXBQ\0" "\x08" "PMOVZXWD\0" "\x09" "VPMOVZXWD\0" \ 234 | "\x08" "PMOVZXWQ\0" "\x09" "VPMOVZXWQ\0" "\x08" "PMOVZXDQ\0" "\x09" "VPMOVZXDQ\0" \ 235 | "\x07" "PCMPGTQ\0" "\x08" "VPCMPGTQ\0" "\x06" "PMINSB\0" "\x07" "VPMINSB\0" \ 236 | "\x06" "PMINSD\0" "\x07" "VPMINSD\0" "\x06" "PMINUW\0" "\x07" "VPMINUW\0" "\x06" "PMINUD\0" \ 237 | "\x07" "VPMINUD\0" "\x06" "PMAXSB\0" "\x07" "VPMAXSB\0" "\x06" "PMAXSD\0" "\x07" "VPMAXSD\0" \ 238 | "\x06" "PMAXUW\0" "\x07" "VPMAXUW\0" "\x06" "PMAXUD\0" "\x07" "VPMAXUD\0" "\x06" "PMULLD\0" \ 239 | "\x07" "VPMULLD\0" "\x0a" "PHMINPOSUW\0" "\x0b" "VPHMINPOSUW\0" "\x06" "INVEPT\0" \ 240 | "\x07" "INVVPID\0" "\x07" "INVPCID\0" "\x0e" "VFMADDSUB132PS\0" "\x0e" "VFMADDSUB132PD\0" \ 241 | "\x0e" "VFMSUBADD132PS\0" "\x0e" "VFMSUBADD132PD\0" "\x0b" "VFMADD132PS\0" \ 242 | "\x0b" "VFMADD132PD\0" "\x0b" "VFMADD132SS\0" "\x0b" "VFMADD132SD\0" "\x0b" "VFMSUB132PS\0" \ 243 | "\x0b" "VFMSUB132PD\0" "\x0b" "VFMSUB132SS\0" "\x0b" "VFMSUB132SD\0" "\x0c" "VFNMADD132PS\0" \ 244 | "\x0c" "VFNMADD132PD\0" "\x0c" "VFNMADD132SS\0" "\x0c" "VFNMADD132SD\0" "\x0c" "VFNMSUB132PS\0" \ 245 | "\x0c" "VFNMSUB132PD\0" "\x0c" "VFNMSUB132SS\0" "\x0c" "VFNMSUB132SD\0" "\x0e" "VFMADDSUB213PS\0" \ 246 | "\x0e" "VFMADDSUB213PD\0" "\x0e" "VFMSUBADD213PS\0" "\x0e" "VFMSUBADD213PD\0" \ 247 | "\x0b" "VFMADD213PS\0" "\x0b" "VFMADD213PD\0" "\x0b" "VFMADD213SS\0" "\x0b" "VFMADD213SD\0" \ 248 | "\x0b" "VFMSUB213PS\0" "\x0b" "VFMSUB213PD\0" "\x0b" "VFMSUB213SS\0" "\x0b" "VFMSUB213SD\0" \ 249 | "\x0c" "VFNMADD213PS\0" "\x0c" "VFNMADD213PD\0" "\x0c" "VFNMADD213SS\0" "\x0c" "VFNMADD213SD\0" \ 250 | "\x0c" "VFNMSUB213PS\0" "\x0c" "VFNMSUB213PD\0" "\x0c" "VFNMSUB213SS\0" "\x0c" "VFNMSUB213SD\0" \ 251 | "\x0e" "VFMADDSUB231PS\0" "\x0e" "VFMADDSUB231PD\0" "\x0e" "VFMSUBADD231PS\0" \ 252 | "\x0e" "VFMSUBADD231PD\0" "\x0b" "VFMADD231PS\0" "\x0b" "VFMADD231PD\0" "\x0b" "VFMADD231SS\0" \ 253 | "\x0b" "VFMADD231SD\0" "\x0b" "VFMSUB231PS\0" "\x0b" "VFMSUB231PD\0" "\x0b" "VFMSUB231SS\0" \ 254 | "\x0b" "VFMSUB231SD\0" "\x0c" "VFNMADD231PS\0" "\x0c" "VFNMADD231PD\0" "\x0c" "VFNMADD231SS\0" \ 255 | "\x0c" "VFNMADD231SD\0" "\x0c" "VFNMSUB231PS\0" "\x0c" "VFNMSUB231PD\0" "\x0c" "VFNMSUB231SS\0" \ 256 | "\x0c" "VFNMSUB231SD\0" "\x06" "AESIMC\0" "\x07" "VAESIMC\0" "\x06" "AESENC\0" \ 257 | "\x07" "VAESENC\0" "\x0a" "AESENCLAST\0" "\x0b" "VAESENCLAST\0" "\x06" "AESDEC\0" \ 258 | "\x07" "VAESDEC\0" "\x0a" "AESDECLAST\0" "\x0b" "VAESDECLAST\0" "\x05" "MOVBE\0" \ 259 | "\x05" "CRC32\0" "\x0a" "VPERM2F128\0" "\x07" "ROUNDPS\0" "\x08" "VROUNDPS\0" \ 260 | "\x07" "ROUNDPD\0" "\x08" "VROUNDPD\0" "\x07" "ROUNDSS\0" "\x08" "VROUNDSS\0" \ 261 | "\x07" "ROUNDSD\0" "\x08" "VROUNDSD\0" "\x07" "BLENDPS\0" "\x08" "VBLENDPS\0" \ 262 | "\x07" "BLENDPD\0" "\x08" "VBLENDPD\0" "\x07" "PBLENDW\0" "\x08" "VPBLENDW\0" \ 263 | "\x07" "PALIGNR\0" "\x08" "VPALIGNR\0" "\x06" "PEXTRB\0" "\x07" "VPEXTRB\0" \ 264 | "\x06" "PEXTRD\0" "\x06" "PEXTRQ\0" "\x07" "VPEXTRD\0" "\x07" "VPEXTRQ\0" "\x09" "EXTRACTPS\0" \ 265 | "\x0a" "VEXTRACTPS\0" "\x0b" "VINSERTF128\0" "\x0c" "VEXTRACTF128\0" "\x06" "PINSRB\0" \ 266 | "\x07" "VPINSRB\0" "\x08" "INSERTPS\0" "\x09" "VINSERTPS\0" "\x06" "PINSRD\0" \ 267 | "\x06" "PINSRQ\0" "\x07" "VPINSRD\0" "\x07" "VPINSRQ\0" "\x04" "DPPS\0" "\x05" "VDPPS\0" \ 268 | "\x04" "DPPD\0" "\x05" "VDPPD\0" "\x07" "MPSADBW\0" "\x08" "VMPSADBW\0" "\x09" "PCLMULQDQ\0" \ 269 | "\x0a" "VPCLMULQDQ\0" "\x09" "VBLENDVPS\0" "\x09" "VBLENDVPD\0" "\x09" "VPBLENDVB\0" \ 270 | "\x09" "PCMPESTRM\0" "\x0a" "VPCMPESTRM\0" "\x09" "PCMPESTRI\0" "\x0a" "VPCMPESTRI\0" \ 271 | "\x09" "PCMPISTRM\0" "\x0a" "VPCMPISTRM\0" "\x09" "PCMPISTRI\0" "\x0a" "VPCMPISTRI\0" \ 272 | "\x0f" "AESKEYGENASSIST\0" "\x10" "VAESKEYGENASSIST\0" "\x06" "PSRLDQ\0" "\x07" "VPSRLDQ\0" \ 273 | "\x06" "PSLLDQ\0" "\x07" "VPSLLDQ\0" "\x06" "FXSAVE\0" "\x08" "FXSAVE64\0" \ 274 | "\x08" "RDFSBASE\0" "\x07" "FXRSTOR\0" "\x09" "FXRSTOR64\0" "\x08" "RDGSBASE\0" \ 275 | "\x07" "LDMXCSR\0" "\x08" "WRFSBASE\0" "\x08" "VLDMXCSR\0" "\x07" "STMXCSR\0" \ 276 | "\x08" "WRGSBASE\0" "\x08" "VSTMXCSR\0" "\x06" "RDRAND\0" "\x07" "VMPTRLD\0" \ 277 | "\x07" "VMCLEAR\0" "\x05" "VMXON\0" "\x06" "MOVSXD\0" "\x05" "PAUSE\0" "\x04" "WAIT\0" \ 278 | "\x06" "_3DNOW\0"; 279 | 280 | const _WRegister _REGISTERS[] = { 281 | {3, "RAX"}, {3, "RCX"}, {3, "RDX"}, {3, "RBX"}, {3, "RSP"}, {3, "RBP"}, {3, "RSI"}, {3, "RDI"}, {2, "R8"}, {2, "R9"}, {3, "R10"}, {3, "R11"}, {3, "R12"}, {3, "R13"}, {3, "R14"}, {3, "R15"}, 282 | {3, "EAX"}, {3, "ECX"}, {3, "EDX"}, {3, "EBX"}, {3, "ESP"}, {3, "EBP"}, {3, "ESI"}, {3, "EDI"}, {3, "R8D"}, {3, "R9D"}, {4, "R10D"}, {4, "R11D"}, {4, "R12D"}, {4, "R13D"}, {4, "R14D"}, {4, "R15D"}, 283 | {2, "AX"}, {2, "CX"}, {2, "DX"}, {2, "BX"}, {2, "SP"}, {2, "BP"}, {2, "SI"}, {2, "DI"}, {3, "R8W"}, {3, "R9W"}, {4, "R10W"}, {4, "R11W"}, {4, "R12W"}, {4, "R13W"}, {4, "R14W"}, {4, "R15W"}, 284 | {2, "AL"}, {2, "CL"}, {2, "DL"}, {2, "BL"}, {2, "AH"}, {2, "CH"}, {2, "DH"}, {2, "BH"}, {3, "R8B"}, {3, "R9B"}, {4, "R10B"}, {4, "R11B"}, {4, "R12B"}, {4, "R13B"}, {4, "R14B"}, {4, "R15B"}, 285 | {3, "SPL"}, {3, "BPL"}, {3, "SIL"}, {3, "DIL"}, 286 | {2, "ES"}, {2, "CS"}, {2, "SS"}, {2, "DS"}, {2, "FS"}, {2, "GS"}, 287 | {3, "RIP"}, 288 | {3, "ST0"}, {3, "ST1"}, {3, "ST2"}, {3, "ST3"}, {3, "ST4"}, {3, "ST5"}, {3, "ST6"}, {3, "ST7"}, 289 | {3, "MM0"}, {3, "MM1"}, {3, "MM2"}, {3, "MM3"}, {3, "MM4"}, {3, "MM5"}, {3, "MM6"}, {3, "MM7"}, 290 | {4, "XMM0"}, {4, "XMM1"}, {4, "XMM2"}, {4, "XMM3"}, {4, "XMM4"}, {4, "XMM5"}, {4, "XMM6"}, {4, "XMM7"}, {4, "XMM8"}, {4, "XMM9"}, {5, "XMM10"}, {5, "XMM11"}, {5, "XMM12"}, {5, "XMM13"}, {5, "XMM14"}, {5, "XMM15"}, 291 | {4, "YMM0"}, {4, "YMM1"}, {4, "YMM2"}, {4, "YMM3"}, {4, "YMM4"}, {4, "YMM5"}, {4, "YMM6"}, {4, "YMM7"}, {4, "YMM8"}, {4, "YMM9"}, {5, "YMM10"}, {5, "YMM11"}, {5, "YMM12"}, {5, "YMM13"}, {5, "YMM14"}, {5, "YMM15"}, 292 | {3, "CR0"}, {0, ""}, {3, "CR2"}, {3, "CR3"}, {3, "CR4"}, {0, ""}, {0, ""}, {0, ""}, {3, "CR8"}, 293 | {3, "DR0"}, {3, "DR1"}, {3, "DR2"}, {3, "DR3"}, {0, ""}, {0, ""}, {3, "DR6"}, {3, "DR7"} 294 | }; 295 | 296 | #endif /* DISTORM_LIGHT */ 297 | -------------------------------------------------------------------------------- /kextstat_aslr/instructions.c: -------------------------------------------------------------------------------- 1 | /* 2 | instructions.c 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #include "instructions.h" 25 | 26 | #include "insts.h" 27 | #include "prefix.h" 28 | #include "x86defs.h" 29 | #include "mnemonics.h" 30 | 31 | 32 | /* Helper macros to extract the type or index from an inst-node value. */ 33 | #define INST_NODE_INDEX(n) ((n) & 0x1fff) 34 | #define INST_NODE_TYPE(n) ((n) >> 13) 35 | 36 | /* Helper macro to read the actual flags that are associated with an inst-info. */ 37 | #define INST_INFO_FLAGS(ii) (FlagsTable[InstSharedInfoTable[(ii)->sharedIndex].flagsIndex]) 38 | 39 | /* 40 | I use the trie data structure as I found it most fitting to a disassembler mechanism. 41 | When you read a byte and have to decide if it's enough or you should read more bytes, 'till you get to the instruction information. 42 | It's really fast because you POP the instruction info in top 3 iterates on the DB, because an instruction can be formed from two bytes + 3 bits reg from the ModR/M byte. 43 | For a simple explanation, check this out: 44 | http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Tree/Trie/ 45 | Futher reading: http://en.wikipedia.org/wiki/Trie 46 | 47 | The first GATE (array you read off a trie data structure), as I call them, is statically allocated by the compiler. 48 | The second and third gates if used are being allocated dynamically by the instructions-insertion functionality. 49 | 50 | How would such a thing look in memory, say we support 4 instructions with 3 bytes top (means 2 dynamically allocated gates). 51 | 52 | -> 53 | |-------| 0, 54 | |0| -------------------------------> |-------| 55 | |1|RET | 1, |0|AND | 56 | |2| -----> |-------| |1|XOR | 57 | |3|INT3 | |0|PUSH | |2|OR | 0,3, 58 | |-------| |1|POP | |3| --------->|-------| 59 | |2|PUSHF| |-------| |0|ROR | 60 | |3|POPF | |1|ROL | 61 | |-------| |2|SHR | 62 | |3|SHL | 63 | |-------| 64 | 65 | Of course, this is NOT how Intel instructions set looks!!! 66 | but I just wanted to give a small demonstration. 67 | Now the instructions you get from such a trie DB goes like this: 68 | 69 | 0, 0 - AND 70 | 0, 1 - XOR 71 | 0, 2 - OR 72 | 0, 3, 0, ROR 73 | 0, 3, 1, ROL 74 | 0, 3, 2, SHR 75 | 0, 3, 3, SHL 76 | 1 - RET 77 | 2, 0 - PUSH 78 | 2, 1 - POP 79 | 2, 2 - PUSHF 80 | 2, 3 - POPF 81 | 3 - INT3 82 | 83 | I guess it's clear by now. 84 | So now, if you read 0, you know that you have to enter the second gate(list) with the second byte specifying the index. 85 | But if you read 1, you know that you go to an instruction (in this case, a RET). 86 | That's why there's an Instruction-Node structure, it tells you whether you got to an instruction or another list 87 | so you should keep on reading byte). 88 | 89 | In Intel, you could go through 4 gates at top, because there're instructions which are built from 2 bytes and another smaller list 90 | for the REG part, or newest SSE4 instructions which use 4 bytes for opcode. 91 | Therefore, Intel's first gate is 256 long, and other gates are 256 (/72) or 8 long, yes, it costs pretty much alot of memory 92 | for non-used defined instructions, but I think that it still rocks. 93 | */ 94 | 95 | /* 96 | * A helper function to look up the correct inst-info structure. 97 | * It does one fetch from the index-table, and then another to get the inst-info. 98 | * Note that it takes care about basic inst-info or inst-info-ex. 99 | * The caller should worry about boundary checks and whether it accesses a last-level table. 100 | */ 101 | static _InstInfo* inst_get_info(_InstNode in, int index) 102 | { 103 | int instIndex = 0; 104 | 105 | in = InstructionsTree[INST_NODE_INDEX(in) + index]; 106 | if (in == INT_NOTEXISTS) return NULL; 107 | 108 | instIndex = INST_NODE_INDEX(in); 109 | return INST_NODE_TYPE(in) == INT_INFO ? &InstInfos[instIndex] : (_InstInfo*)&InstInfosEx[instIndex]; 110 | } 111 | 112 | /* 113 | * This function is responsible to return the instruction information of the first found in code. 114 | * It returns the _InstInfo of the found instruction, otherwise NULL. 115 | * code should point to the ModR/M byte upon exit (if used), or after the instruction binary code itself. 116 | * This function is NOT decoding-type dependant, it is up to the caller to see whether the instruction is valid. 117 | * Get the instruction info, using a Trie data structure. 118 | * 119 | * Sometimes normal prefixes become mandatory prefixes, which means they are now part of the instruction opcode bytes. 120 | 121 | * This is a bit tricky now, 122 | * if the first byte is a REP (F3) prefix, we will have to give a chance to an SSE instruction. 123 | * If an instruction doesn't exist, we will make it as a prefix and re-locateinst. 124 | * A case such that a REP prefix is being changed into an instruction byte and also an SSE instruction will not be found can't happen, 125 | * simply because there are no collisions between string instruction and SSE instructions (they are escaped). 126 | 127 | * As for S/SSE2/3, check for F2 and 66 as well. 128 | 129 | * In 64 bits, we have to make sure that we will skip the REX prefix, if it exists. 130 | * There's a specific case, where a 66 is mandatory but it was dropped because REG.W was used, 131 | * but it doesn't behave as an operand size prefix but as a mandatory, so we will have to take it into account. 132 | 133 | * For example (64 bits decoding mode): 134 | * 66 98 CBW 135 | * 48 98 CDQE 136 | * 66 48 98: db 0x66; CDQE 137 | * Shows that operand size is dropped. 138 | 139 | * Now, it's a mandatory prefix and NOT an operand size one. 140 | * 66480f2dc0 db 0x48; CVTPD2PI XMM0, XMM0 141 | * Although this instruction doesn't require a REX.W, it just shows, that even if it did - it doesn't matter. 142 | * REX.W is dropped because it's not requried, but the decode function disabled the operand size even so. 143 | */ 144 | static _InstInfo* inst_lookup_prefixed(_InstNode in, _PrefixState* ps) 145 | { 146 | int checkOpSize = FALSE; 147 | int index = 0; 148 | _InstInfo* ii = NULL; 149 | 150 | /* Check prefixes of current decoded instruction (None, 0x66, 0xf3, 0xf2). */ 151 | switch (ps->decodedPrefixes & (INST_PRE_OP_SIZE | INST_PRE_REPS)) 152 | { 153 | case 0: 154 | /* Non-prefixed, index = 0. */ 155 | index = 0; 156 | break; 157 | case INST_PRE_OP_SIZE: 158 | /* 0x66, index = 1. */ 159 | index = 1; 160 | /* Mark that we used it as a mandatory prefix. */ 161 | ps->isOpSizeMandatory = TRUE; 162 | ps->decodedPrefixes &= ~INST_PRE_OP_SIZE; 163 | break; 164 | case INST_PRE_REP: 165 | /* 0xf3, index = 2. */ 166 | index = 2; 167 | ps->decodedPrefixes &= ~INST_PRE_REP; 168 | break; 169 | case INST_PRE_REPNZ: 170 | /* 0xf2, index = 3. */ 171 | index = 3; 172 | ps->decodedPrefixes &= ~INST_PRE_REPNZ; 173 | break; 174 | default: 175 | /* 176 | * Now we got a problem, since there are a few mandatory prefixes at once. 177 | * There is only one case when it's ok, when the operand size prefix is for real (not mandatory). 178 | * Otherwise we will have to return NULL, since the instruction is illegal. 179 | * Therefore we will start with REPNZ and REP prefixes, 180 | * try to get the instruction and only then check for the operand size prefix. 181 | */ 182 | 183 | /* If both REPNZ and REP are together, it's illegal for sure. */ 184 | if ((ps->decodedPrefixes & INST_PRE_REPS) == INST_PRE_REPS) return NULL; 185 | 186 | /* Now we know it's either REPNZ+OPSIZE or REP+OPSIZE, so examine the instruction. */ 187 | if (ps->decodedPrefixes & INST_PRE_REPNZ) { 188 | index = 3; 189 | ps->decodedPrefixes &= ~INST_PRE_REPNZ; 190 | } else if (ps->decodedPrefixes & INST_PRE_REP) { 191 | index = 2; 192 | ps->decodedPrefixes &= ~INST_PRE_REP; 193 | } 194 | /* Mark to verify the operand-size prefix of the fetched instruction below. */ 195 | checkOpSize = TRUE; 196 | break; 197 | } 198 | 199 | /* Fetch the inst-info from the index. */ 200 | ii = inst_get_info(in, index); 201 | 202 | if (checkOpSize) { 203 | /* If the instruction doesn't support operand size prefix, then it's illegal. */ 204 | if ((ii == NULL) || (~INST_INFO_FLAGS(ii) & INST_PRE_OP_SIZE)) return NULL; 205 | } 206 | 207 | /* If there was a prefix, but the instruction wasn't found. Try to fall back to use the normal instruction. */ 208 | if (ii == NULL) ii = inst_get_info(in, 0); 209 | return ii; 210 | } 211 | 212 | /* A helper function to look up special VEX instructions. 213 | * See if it's a MOD based instruction and fix index if required. 214 | * Only after a first lookup (that was done by caller), we can tell if we need to fix the index. 215 | * Because these are coupled instructions 216 | * (which means that the base instruction hints about the other instruction). 217 | * Note that caller should check if it's a MOD dependent instruction before getting in here. 218 | */ 219 | static _InstInfo* inst_vex_mod_lookup(_CodeInfo* ci, _InstNode in, _InstInfo* ii, unsigned int index) 220 | { 221 | /* Advance to read the MOD from ModRM byte. */ 222 | ci->code += 1; 223 | ci->codeLen -= 1; 224 | if (ci->codeLen < 0) return NULL; 225 | if (*ci->code < INST_DIVIDED_MODRM) { 226 | /* MOD is not 11, therefore change the index to 8 - 12 range in the prefixed table. */ 227 | index += 4; 228 | /* Make a second lookup for this special instruction. */ 229 | return inst_get_info(in, index); 230 | } 231 | /* Return the original one, in case we didn't find a stuited instruction. */ 232 | return ii; 233 | } 234 | 235 | static _InstInfo* inst_vex_lookup(_CodeInfo* ci, _PrefixState* ps) 236 | { 237 | _InstNode in = 0; 238 | unsigned int pp = 0, start = 0; 239 | unsigned int index = 4; /* VEX instructions start at index 4 in the Prefixed table. */ 240 | uint8_t vex = *ps->vexPos, vex2 = 0, v = 0; 241 | int instType = 0, instIndex = 0; 242 | 243 | /* The VEX instruction will #ud if any of 66, f0, f2, f3, REX prefixes precede. */ 244 | _iflags illegal = (INST_PRE_OP_SIZE | INST_PRE_LOCK | INST_PRE_REP | INST_PRE_REPNZ | INST_PRE_REX); 245 | if ((ps->decodedPrefixes & illegal) != 0) return NULL; 246 | 247 | /* Read the some fields from the VEX prefix we need to extract the instruction. */ 248 | if (ps->prefixExtType == PET_VEX2BYTES) { 249 | ps->vexV = v = (~vex >> 3) & 0xf; 250 | pp = vex & 3; 251 | /* Implied leading 0x0f byte by default for 2 bytes VEX prefix. */ 252 | start = 1; 253 | } else { /* PET_VEX3BYTES */ 254 | start = vex & 0x1f; 255 | vex2 = *(ps->vexPos + 1); 256 | ps->vexV = v = (~vex2 >> 3) & 0xf; 257 | pp = vex2 & 3; 258 | } 259 | 260 | /* start can be either 1 (0x0f), 2 (0x0f, 0x038) or 3 (0x0f, 0x3a), otherwise it's illegal. */ 261 | switch (start) 262 | { 263 | case 1: in = Table_0F; break; 264 | case 2: in = Table_0F_38; break; 265 | case 3: in = Table_0F_3A; break; 266 | default: return NULL; 267 | } 268 | 269 | /* pp is actually the implied mandatory prefix, apply it to the index. */ 270 | index += pp; /* (None, 0x66, 0xf3, 0xf2) */ 271 | 272 | /* Read a byte from the stream. */ 273 | ci->codeLen -= 1; 274 | if (ci->codeLen < 0) return NULL; 275 | 276 | in = InstructionsTree[INST_NODE_INDEX(in) + *ci->code]; 277 | if (in == INT_NOTEXISTS) return NULL; 278 | 279 | instType = INST_NODE_TYPE(in); 280 | instIndex = INST_NODE_INDEX(in); 281 | 282 | /* 283 | * If we started with 0f38 or 0f3a so it's a prefixed table, 284 | * therefore it's surely a VEXed instruction (because of a high index). 285 | * However, starting with 0f, could also lead immediately to a prefixed table for some bytes. 286 | * it might return NULL, if the index is invalid. 287 | */ 288 | if (instType == INT_LIST_PREFIXED) { 289 | _InstInfo* ii = inst_get_info(in, index); 290 | /* See if the instruction is dependent on MOD. */ 291 | if ((ii != NULL) && (((_InstInfoEx*)ii)->flagsEx & INST_MODRR_BASED)) { 292 | ii = inst_vex_mod_lookup(ci, in, ii, index); 293 | } 294 | return ii; 295 | } 296 | 297 | /* 298 | * If we reached here, obviously we started with 0f. VEXed instructions must be nodes of a prefixed table. 299 | * But since we found an instruction (or divided one), just return NULL. 300 | * They cannot lead to a VEXed instruction. 301 | */ 302 | if ((instType == INT_INFO) || (instType == INT_INFOEX) || (instType == INT_LIST_DIVIDED)) return NULL; 303 | 304 | /* Now we are left with handling either GROUP or FULL tables, therefore we will read another byte from the stream. */ 305 | ci->code += 1; 306 | ci->codeLen -= 1; 307 | if (ci->codeLen < 0) return NULL; 308 | 309 | if (instType == INT_LIST_GROUP) { 310 | in = InstructionsTree[instIndex + ((*ci->code >> 3) & 7)]; 311 | /* Continue below to check prefixed table. */ 312 | } else if (instType == INT_LIST_FULL) { 313 | in = InstructionsTree[instIndex + *ci->code]; 314 | /* Continue below to check prefixed table. */ 315 | } 316 | 317 | /* Now that we got to the last table in the trie, check for a prefixed table. */ 318 | if (INST_NODE_TYPE(in) == INT_LIST_PREFIXED) { 319 | _InstInfo* ii = inst_get_info(in, index); 320 | /* See if the instruction is dependent on MOD. */ 321 | if ((ii != NULL) && (((_InstInfoEx*)ii)->flagsEx & INST_MODRR_BASED)) { 322 | ii = inst_vex_mod_lookup(ci, in, ii, index); 323 | } 324 | return ii; 325 | } 326 | 327 | /* No VEXed instruction was found. */ 328 | return NULL; 329 | } 330 | 331 | _InstInfo* inst_lookup(_CodeInfo* ci, _PrefixState* ps) 332 | { 333 | unsigned int tmpIndex0 = 0, tmpIndex1 = 0, tmpIndex2 = 0, rex = ps->vrex; 334 | int instType = 0; 335 | _InstNode in = 0; 336 | _InstInfo* ii = NULL; 337 | int isWaitIncluded = FALSE; 338 | 339 | /* See whether we have to handle a VEX prefixed instruction. */ 340 | if (ps->decodedPrefixes & INST_PRE_VEX) { 341 | ii = inst_vex_lookup(ci, ps); 342 | if (ii != NULL) { 343 | /* Make sure that VEX.L exists when forced. */ 344 | if ((((_InstInfoEx*)ii)->flagsEx & INST_FORCE_VEXL) && (~ps->vrex & PREFIX_EX_L)) return NULL; 345 | /* If the instruction doesn't use VEX.vvvv it must be zero. */ 346 | if ((((_InstInfoEx*)ii)->flagsEx & INST_VEX_V_UNUSED) && ps->vexV) return NULL; 347 | } 348 | return ii; 349 | } 350 | 351 | /* Read first byte. */ 352 | ci->codeLen -= 1; 353 | if (ci->codeLen < 0) return NULL; 354 | tmpIndex0 = *ci->code; 355 | 356 | /* Check for special 0x9b, WAIT instruction, which can be part of some instructions(x87). */ 357 | if (tmpIndex0 == INST_WAIT_INDEX) { 358 | /* Only OCST_1dBYTES get a chance to include this byte as part of the opcode. */ 359 | isWaitIncluded = TRUE; 360 | 361 | /* Ignore all prefixes, since they are useless and operate on the WAIT instruction itself. */ 362 | prefixes_ignore_all(ps); 363 | 364 | /* Move to next code byte as a new whole instruction. */ 365 | ci->code += 1; 366 | ci->codeLen -= 1; 367 | if (ci->codeLen < 0) return NULL; /* Faster to return NULL, it will be detected as WAIT later anyway. */ 368 | /* Since we got a WAIT prefix, we re-read the first byte. */ 369 | tmpIndex0 = *ci->code; 370 | } 371 | 372 | /* Walk first byte in InstructionsTree root. */ 373 | in = InstructionsTree[tmpIndex0]; 374 | if (in == INT_NOTEXISTS) return NULL; 375 | instType = INST_NODE_TYPE(in); 376 | 377 | /* Single byte instruction (OCST_1BYTE). */ 378 | if ((instType < INT_INFOS) && (!isWaitIncluded)) { 379 | /* Some single byte instructions need extra treatment. */ 380 | switch (tmpIndex0) 381 | { 382 | case INST_ARPL_INDEX: 383 | /* 384 | * ARPL/MOVSXD share the same opcode, and both have different operands and mnemonics, of course. 385 | * Practically, I couldn't come up with a comfortable way to merge the operands' types of ARPL/MOVSXD. 386 | * And since the DB can't be patched dynamically, because the DB has to be multi-threaded compliant, 387 | * I have no choice but to check for ARPL/MOVSXD right here - "right about now, the funk soul brother, check it out now, the funk soul brother...", fatboy slim 388 | */ 389 | if (ci->dt == Decode64Bits) { 390 | return &II_MOVSXD; 391 | } /* else ARPL will be returned because its defined in the DB already. */ 392 | break; 393 | 394 | case INST_NOP_INDEX: /* Nopnopnop */ 395 | /* Check for Pause, since it's prefixed with 0xf3, which is not a real mandatory prefix. */ 396 | if (ps->decodedPrefixes & INST_PRE_REP) { 397 | /* Flag this prefix as used. */ 398 | ps->usedPrefixes |= INST_PRE_REP; 399 | return &II_PAUSE; 400 | } 401 | 402 | /* 403 | * Treat NOP/XCHG specially. 404 | * If we're not in 64bits restore XCHG to NOP, since in the DB it's XCHG. 405 | * Else if we're in 64bits examine REX, if exists, and decide which instruction should go to output. 406 | * 48 90 XCHG RAX, RAX is a true NOP (eat REX in this case because it's valid). 407 | * 90 XCHG EAX, EAX is a true NOP (and not high dword of RAX = 0 although it should be a 32 bits operation). 408 | * Note that if the REX.B is used, then the register is not RAX anymore but R8, which means it's not a NOP. 409 | */ 410 | if (rex & PREFIX_EX_W) ps->usedPrefixes |= INST_PRE_REX; 411 | if ((ci->dt != Decode64Bits) || (~rex & PREFIX_EX_B)) return &II_NOP; 412 | break; 413 | 414 | case INST_LEA_INDEX: 415 | /* Ignore segment override prefixes for LEA instruction. */ 416 | ps->decodedPrefixes &= ~INST_PRE_SEGOVRD_MASK; 417 | /* Update unused mask for ignoring segment prefix. */ 418 | prefixes_ignore(ps, PFXIDX_SEG); 419 | break; 420 | } 421 | 422 | /* Return the 1 byte instruction we found. */ 423 | return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; 424 | } 425 | 426 | /* Read second byte, still doens't mean all of its bits are used (I.E: ModRM). */ 427 | ci->code += 1; 428 | ci->codeLen -= 1; 429 | if (ci->codeLen < 0) return NULL; 430 | tmpIndex1 = *ci->code; 431 | 432 | /* Try single byte instruction + reg bits (OCST_13BYTES). */ 433 | if ((instType == INT_LIST_GROUP) && (!isWaitIncluded)) return inst_get_info(in, (tmpIndex1 >> 3) & 7); 434 | 435 | /* Try single byte instruction + reg byte OR one whole byte (OCST_1dBYTES). */ 436 | if (instType == INT_LIST_DIVIDED) { 437 | /* OCST_1dBYTES is relatively simple to OCST_2dBYTES, since it's really divided at 0xc0. */ 438 | if (tmpIndex1 < INST_DIVIDED_MODRM) { 439 | /* An instruction which requires a ModR/M byte. Thus it's 1.3 bytes long instruction. */ 440 | tmpIndex1 = (tmpIndex1 >> 3) & 7; /* Isolate the 3 REG/OPCODE bits. */ 441 | } else { /* Normal 2 bytes instruction. */ 442 | /* 443 | * Divided instructions can't be in the range of 0x8-0xc0. 444 | * That's because 0-8 are used for 3 bits group. 445 | * And 0xc0-0xff are used for not-divided instruction. 446 | * So the inbetween range is omitted, thus saving some more place in the tables. 447 | */ 448 | tmpIndex1 -= INST_DIVIDED_MODRM - 8; 449 | } 450 | 451 | in = InstructionsTree[INST_NODE_INDEX(in) + tmpIndex1]; 452 | if (in == INT_NOTEXISTS) return NULL; 453 | instType = INST_NODE_TYPE(in); 454 | 455 | if (instType < INT_INFOS) { 456 | /* If the instruction doesn't support the wait (marked as opsize) as part of the opcode, it's illegal. */ 457 | ii = instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; 458 | if ((~INST_INFO_FLAGS(ii) & INST_PRE_OP_SIZE) && (isWaitIncluded)) return NULL; 459 | return ii; 460 | } 461 | /* 462 | * If we got here the instruction can support the wait prefix, so see if it was part of the stream. 463 | * Examine prefixed table, specially used for 0x9b, since it's optional. 464 | * No Wait: index = 0. 465 | * Wait Exists, index = 1. 466 | */ 467 | return inst_get_info(in, isWaitIncluded); 468 | } 469 | 470 | /* Don't allow to continue if WAIT is part of the opcode, because there are no instructions that include it. */ 471 | if (isWaitIncluded) return NULL; 472 | 473 | /* Try 2 bytes long instruction (doesn't include ModRM byte). */ 474 | if (instType == INT_LIST_FULL) { 475 | in = InstructionsTree[INST_NODE_INDEX(in) + tmpIndex1]; 476 | if (in == INT_NOTEXISTS) return NULL; 477 | instType = INST_NODE_TYPE(in); 478 | 479 | /* This is where we check if we just read two escape bytes in a row, which means it is a 3DNow! instruction. */ 480 | if ((tmpIndex0 == _3DNOW_ESCAPE_BYTE) && (tmpIndex1 == _3DNOW_ESCAPE_BYTE)) return &II_3DNOW; 481 | 482 | /* 2 bytes instruction (OCST_2BYTES). */ 483 | if (instType < INT_INFOS) 484 | return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; 485 | 486 | /* 487 | * 2 bytes + mandatory perfix. 488 | * Mandatory prefixes can be anywhere in the prefixes. 489 | * There cannot be more than one mandatory prefix, unless it's a normal operand size prefix. 490 | */ 491 | if (instType == INT_LIST_PREFIXED) return inst_lookup_prefixed(in, ps); 492 | } 493 | 494 | /* Read third byte, still doens't mean all of its bits are used (I.E: ModRM). */ 495 | ci->code += 1; 496 | ci->codeLen -= 1; 497 | if (ci->codeLen < 0) return NULL; 498 | tmpIndex2 = *ci->code; 499 | 500 | /* Try 2 bytes + reg instruction (OCST_23BYTES). */ 501 | if (instType == INT_LIST_GROUP) { 502 | in = InstructionsTree[INST_NODE_INDEX(in) + ((tmpIndex2 >> 3) & 7)]; 503 | if (in == INT_NOTEXISTS) return NULL; 504 | instType = INST_NODE_TYPE(in); 505 | 506 | if (instType < INT_INFOS) 507 | return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; 508 | 509 | /* It has to be a prefixed table then. */ 510 | return inst_lookup_prefixed(in, ps); 511 | } 512 | 513 | /* Try 2 bytes + divided range (OCST_2dBYTES). */ 514 | if (instType == INT_LIST_DIVIDED) { 515 | _InstNode in2 = InstructionsTree[INST_NODE_INDEX(in) + ((tmpIndex2 >> 3) & 7)]; 516 | /* 517 | * Do NOT check for NULL here, since we do a bit of a guess work, 518 | * hence we don't override 'in', cause we might still need it. 519 | */ 520 | instType = INST_NODE_TYPE(in2); 521 | 522 | if (instType == INT_INFO) ii = &InstInfos[INST_NODE_INDEX(in2)]; 523 | else if (instType == INT_INFOEX) ii = (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in2)]; 524 | 525 | /* 526 | * OCST_2dBYTES is complex, because there are a few instructions which are not divided in some special cases. 527 | * If the instruction wasn't divided (but still it must be a 2.3 because we are in divided category) 528 | * or it was an official 2.3 (because its index was less than 0xc0) - 529 | * Then it means the instruction should be using the REG bits, otherwise give a chance to range 0xc0-0xff. 530 | */ 531 | /* If we found an instruction only by its REG bits, AND it is not divided, then return it. */ 532 | if ((ii != NULL) && (INST_INFO_FLAGS(ii) & INST_NOT_DIVIDED)) return ii; 533 | /* Otherwise, if the range is above 0xc0, try the special divided range (range 0x8-0xc0 is omitted). */ 534 | if (tmpIndex2 >= INST_DIVIDED_MODRM) return inst_get_info(in, tmpIndex2 - INST_DIVIDED_MODRM + 8); 535 | 536 | /* It might be that we got here without touching ii in the above if statements, then it becomes an invalid instruction prolly. */ 537 | return ii; 538 | } 539 | 540 | /* Try 3 full bytes (OCST_3BYTES - no ModRM byte). */ 541 | if (instType == INT_LIST_FULL) { 542 | /* OCST_3BYTES. */ 543 | in = InstructionsTree[INST_NODE_INDEX(in) + tmpIndex2]; 544 | if (in == INT_NOTEXISTS) return NULL; 545 | instType = INST_NODE_TYPE(in); 546 | 547 | if (instType < INT_INFOS) 548 | return instType == INT_INFO ? &InstInfos[INST_NODE_INDEX(in)] : (_InstInfo*)&InstInfosEx[INST_NODE_INDEX(in)]; 549 | 550 | if (instType == INT_LIST_PREFIXED) return inst_lookup_prefixed(in, ps); 551 | } 552 | 553 | /* Kahtchinggg, damn. */ 554 | return NULL; 555 | } 556 | 557 | /* 558 | * 3DNow! instruction handling: 559 | 560 | * This is used when we encounter a 3DNow! instruction. 561 | * We can't really locate a 3DNow! instruction before we see two escaped bytes, 562 | * 0x0f, 0x0f. Then we have to extract operands which are, dest=mmx register, src=mmx register or quadword indirection. 563 | * When we are finished with the extraction of operands we can resume to locate the instruction by reading another byte 564 | * which tells us which 3DNow instruction we really tracked down... 565 | * So in order to tell the extract operands function which operands the 3DNow! instruction require, we need to set up some 566 | * generic instruction info for 3DNow! instructions. 567 | 568 | * In the inst_lookup itself, when we read an OCST_3BYTES which the two first bytes are 0x0f and 0x0f. 569 | * we will return this special generic II for the specific operands we are interested in (MM, MM64). 570 | * Then after extracting the operand, we'll call a completion routine for locating the instruction 571 | * which will be called only for 3DNow! instructions, distinguished by a flag, and it will read the last byte of the 3 bytes. 572 | * 573 | * The id of this opcode should not be used, the following function should change it anyway. 574 | */ 575 | _InstInfo* inst_lookup_3dnow(_CodeInfo* ci) 576 | { 577 | /* Start off from the two escape bytes gates... which is 3DNow! table.*/ 578 | _InstNode in = Table_0F_0F; 579 | 580 | int index; 581 | 582 | /* Make sure we can read a byte off the stream. */ 583 | if (ci->codeLen < 1) return NULL; 584 | 585 | index = *ci->code; 586 | 587 | ci->codeLen -= 1; 588 | ci->code += 1; 589 | return inst_get_info(in, index); 590 | } 591 | -------------------------------------------------------------------------------- /kextstat_aslr/decoder.c: -------------------------------------------------------------------------------- 1 | /* 2 | decoder.c 3 | 4 | diStorm3 - Powerful disassembler for X86/AMD64 5 | http://ragestorm.net/distorm/ 6 | distorm at gmail dot com 7 | Copyright (C) 2003-2012 Gil Dabah 8 | 9 | This program is free software: you can redistribute it and/or modify 10 | it under the terms of the GNU General Public License as published by 11 | the Free Software Foundation, either version 3 of the License, or 12 | (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program. If not, see 21 | */ 22 | 23 | 24 | #include "decoder.h" 25 | #include "instructions.h" 26 | #include "insts.h" 27 | #include "prefix.h" 28 | #include "x86defs.h" 29 | #include "operands.h" 30 | #include "insts.h" 31 | #include "mnemonics.h" 32 | 33 | 34 | /* Instruction Prefixes - Opcode - ModR/M - SIB - Displacement - Immediate */ 35 | 36 | static _DecodeType decode_get_effective_addr_size(_DecodeType dt, _iflags decodedPrefixes) 37 | { 38 | /* 39 | * This table is to map from the current decoding mode to an effective address size: 40 | * Decode16 -> Decode32 41 | * Decode32 -> Decode16 42 | * Decode64 -> Decode32 43 | */ 44 | static _DecodeType AddrSizeTable[] = {Decode32Bits, Decode16Bits, Decode32Bits}; 45 | 46 | /* Switch to non default mode if prefix exists, only for ADDRESS SIZE. */ 47 | if (decodedPrefixes & INST_PRE_ADDR_SIZE) dt = AddrSizeTable[dt]; 48 | return dt; 49 | } 50 | 51 | static _DecodeType decode_get_effective_op_size(_DecodeType dt, _iflags decodedPrefixes, unsigned int rex, _iflags instFlags) 52 | { 53 | /* 54 | * This table is to map from the current decoding mode to an effective operand size: 55 | * Decode16 -> Decode32 56 | * Decode32 -> Decode16 57 | * Decode64 -> Decode16 58 | * Not that in 64bits it's a bit more complicated, because of REX and promoted instructions. 59 | */ 60 | static _DecodeType OpSizeTable[] = {Decode32Bits, Decode16Bits, Decode16Bits}; 61 | 62 | if (decodedPrefixes & INST_PRE_OP_SIZE) return OpSizeTable[dt]; 63 | 64 | if (dt == Decode64Bits) { 65 | /* 66 | * REX Prefix toggles data size to 64 bits. 67 | * Operand size prefix toggles data size to 16. 68 | * Default data size is 32 bits. 69 | * Promoted instructions are 64 bits if they don't require a REX perfix. 70 | * Non promoted instructions are 64 bits if the REX prefix exists. 71 | */ 72 | /* Automatically promoted instructions have only INST_64BITS SET! */ 73 | if (((instFlags & (INST_64BITS | INST_PRE_REX)) == INST_64BITS) || 74 | /* Other instructions in 64 bits can be promoted only with a REX prefix. */ 75 | ((decodedPrefixes & INST_PRE_REX) && (rex & PREFIX_EX_W))) dt = Decode64Bits; 76 | else dt = Decode32Bits; /* Default. */ 77 | } 78 | return dt; 79 | } 80 | 81 | static _DecodeResult decode_inst(_CodeInfo* ci, _PrefixState* ps, _DInst* di) 82 | { 83 | /* The ModR/M byte of the current instruction. */ 84 | unsigned int modrm = 0; 85 | 86 | /* The REX/VEX prefix byte value. */ 87 | unsigned int vrex = ps->vrex; 88 | 89 | /* 90 | * Backup original input, so we can use it later if a problem occurs 91 | * (like not enough data for decoding, invalid opcode, etc). 92 | */ 93 | const uint8_t* startCode = ci->code; 94 | 95 | /* Holds the info about the current found instruction. */ 96 | _InstInfo* ii = NULL; 97 | _InstSharedInfo* isi = NULL; 98 | 99 | /* Used only for special CMP instructions which have pseudo opcodes suffix. */ 100 | unsigned char cmpType = 0; 101 | 102 | /* 103 | * Indicates whether it is right to LOCK the instruction by decoding its first operand. 104 | * Only then you know if it's ok to output the LOCK prefix's text... 105 | * Used for first operand only. 106 | */ 107 | int lockable = FALSE; 108 | 109 | /* Calcualte (and cache) effective-operand-size and effective-address-size only once. */ 110 | _DecodeType effOpSz, effAdrSz; 111 | _iflags instFlags; 112 | 113 | ii = inst_lookup(ci, ps); 114 | if (ii == NULL) goto _Undecodable; 115 | isi = &InstSharedInfoTable[ii->sharedIndex]; 116 | instFlags = FlagsTable[isi->flagsIndex]; 117 | 118 | /* 119 | * If both REX and OpSize are available we will have to disable the OpSize, because REX has precedence. 120 | * However, only if REX.W is set ! 121 | * We had to wait with this test, since the operand size may be a mandatory prefix, 122 | * and we know it only after prefetching. 123 | */ 124 | if ((ps->prefixExtType == PET_REX) && 125 | (ps->decodedPrefixes & INST_PRE_OP_SIZE) && 126 | (!ps->isOpSizeMandatory) && 127 | (vrex & PREFIX_EX_W)) { 128 | ps->decodedPrefixes &= ~INST_PRE_OP_SIZE; 129 | prefixes_ignore(ps, PFXIDX_OP_SIZE); 130 | } 131 | 132 | /* 133 | * In this point we know the instruction we are about to decode and its operands (unless, it's an invalid one!), 134 | * so it makes it the right time for decoding-type suitability testing. 135 | * Which practically means, don't allow 32 bits instructions in 16 bits decoding mode, but do allow 136 | * 16 bits instructions in 32 bits decoding mode, of course... 137 | 138 | * NOTE: Make sure the instruction set for 32 bits has explicitly this specfic flag set. 139 | * NOTE2: Make sure the instruction set for 64 bits has explicitly this specfic flag set. 140 | 141 | * If this is the case, drop what we've got and restart all over after DB'ing that byte. 142 | 143 | * Though, don't drop an instruction which is also supported in 16 and 32 bits. 144 | */ 145 | 146 | /* ! ! ! DISABLED UNTIL FURTHER NOTICE ! ! ! Decode16Bits CAN NOW DECODE 32 BITS INSTRUCTIONS ! ! !*/ 147 | /* if (ii && (dt == Decode16Bits) && (instFlags & INST_32BITS) && (~instFlags & INST_16BITS)) ii = NULL; */ 148 | 149 | /* Drop instructions which are invalid in 64 bits. */ 150 | if ((ci->dt == Decode64Bits) && (instFlags & INST_INVALID_64BITS)) goto _Undecodable; 151 | 152 | /* If it's only a 64 bits instruction drop it in other decoding modes. */ 153 | if ((ci->dt != Decode64Bits) && (instFlags & INST_64BITS_FETCH)) goto _Undecodable; 154 | 155 | if (instFlags & INST_MODRM_REQUIRED) { 156 | /* If the ModRM byte is not part of the opcode, skip the last byte code, so code points now to ModRM. */ 157 | if (~instFlags & INST_MODRM_INCLUDED) { 158 | ci->code++; 159 | if (--ci->codeLen < 0) goto _Undecodable; 160 | } 161 | modrm = *ci->code; 162 | 163 | /* Some instructions enforce that reg=000, so validate that. (Specifically EXTRQ). */ 164 | if ((instFlags & INST_FORCE_REG0) && (((modrm >> 3) & 7) != 0)) goto _Undecodable; 165 | /* Some instructions enforce that mod=11, so validate that. */ 166 | if ((instFlags & INST_MODRR_REQUIRED) && (modrm < INST_DIVIDED_MODRM)) goto _Undecodable; 167 | } 168 | 169 | ci->code++; /* Skip the last byte we just read (either last opcode's byte code or a ModRM). */ 170 | 171 | /* Cache the effective operand-size and address-size. */ 172 | effOpSz = decode_get_effective_op_size(ci->dt, ps->decodedPrefixes, vrex, instFlags); 173 | effAdrSz = decode_get_effective_addr_size(ci->dt, ps->decodedPrefixes); 174 | 175 | memset(di, 0, sizeof(_DInst)); 176 | di->base = R_NONE; 177 | 178 | /* 179 | * Try to extract the next operand only if the latter exists. 180 | * For example, if there is not first operand, no reason to try to extract second operand... 181 | * I decided that a for-break is better for readability in this specific case than goto. 182 | * Note: do-while with a constant 0 makes the compiler warning about it. 183 | */ 184 | for (;;) { 185 | if (isi->d != OT_NONE) { 186 | if (!operands_extract(ci, di, ii, instFlags, (_OpType)isi->d, ONT_1, modrm, ps, effOpSz, effAdrSz, &lockable)) goto _Undecodable; 187 | } else break; 188 | 189 | if (isi->s != OT_NONE) { 190 | if (!operands_extract(ci, di, ii, instFlags, (_OpType)isi->s, ONT_2, modrm, ps, effOpSz, effAdrSz, NULL)) goto _Undecodable; 191 | } else break; 192 | 193 | /* Use third operand, only if the flags says this InstInfo requires it. */ 194 | if (instFlags & INST_USE_OP3) { 195 | if (!operands_extract(ci, di, ii, instFlags, (_OpType)((_InstInfoEx*)ii)->op3, ONT_3, modrm, ps, effOpSz, effAdrSz, NULL)) goto _Undecodable; 196 | } else break; 197 | 198 | /* Support for a fourth operand is added for (i.e:) INSERTQ instruction. */ 199 | if (instFlags & INST_USE_OP4) { 200 | if (!operands_extract(ci, di, ii, instFlags, (_OpType)((_InstInfoEx*)ii)->op4, ONT_4, modrm, ps, effOpSz, effAdrSz, NULL)) goto _Undecodable; 201 | } 202 | break; 203 | } /* Continue here after all operands were extracted. */ 204 | 205 | /* If it were a 3DNow! instruction, we will have to find the instruction itself now that we got its operands extracted. */ 206 | if (instFlags & INST_3DNOW_FETCH) { 207 | ii = inst_lookup_3dnow(ci); 208 | if (ii == NULL) goto _Undecodable; 209 | isi = &InstSharedInfoTable[ii->sharedIndex]; 210 | instFlags = FlagsTable[isi->flagsIndex]; 211 | } 212 | 213 | /* Check whether pseudo opcode is needed, only for CMP instructions: */ 214 | if (instFlags & INST_PSEUDO_OPCODE) { 215 | if (--ci->codeLen < 0) goto _Undecodable; 216 | cmpType = *ci->code; 217 | ci->code++; 218 | if (instFlags & INST_PRE_VEX) { 219 | /* AVX Comparison type must be between 0 to 32, otherwise Reserved. */ 220 | if (cmpType >= INST_VCMP_MAX_RANGE) goto _Undecodable; 221 | } else { 222 | /* SSE Comparison type must be between 0 to 8, otherwise Reserved. */ 223 | if (cmpType >= INST_CMP_MAX_RANGE) goto _Undecodable; 224 | } 225 | } 226 | 227 | /* 228 | * There's a limit of 15 bytes on instruction length. The only way to violate 229 | * this limit is by putting redundant prefixes before an instruction. 230 | * start points to first prefix if any, otherwise it points to instruction first byte. 231 | */ 232 | if ((ci->code - ps->start) > INST_MAXIMUM_SIZE) goto _Undecodable; /* Drop instruction. */ 233 | 234 | /* 235 | * If we reached here the instruction was fully decoded, we located the instruction in the DB and extracted operands. 236 | * Use the correct mnemonic according to the DT. 237 | * If we are in 32 bits decoding mode it doesn't necessarily mean we will choose mnemonic2, alas, 238 | * it means that if there is a mnemonic2, it will be used. 239 | */ 240 | 241 | /* Start with prefix LOCK. */ 242 | if ((lockable == TRUE) && (instFlags & INST_PRE_LOCK)) { 243 | ps->usedPrefixes |= INST_PRE_LOCK; 244 | di->flags |= FLAG_LOCK; 245 | } else if ((instFlags & INST_PRE_REPNZ) && (ps->decodedPrefixes & INST_PRE_REPNZ)) { 246 | ps->usedPrefixes |= INST_PRE_REPNZ; 247 | di->flags |= FLAG_REPNZ; 248 | } else if ((instFlags & INST_PRE_REP) && (ps->decodedPrefixes & INST_PRE_REP)) { 249 | ps->usedPrefixes |= INST_PRE_REP; 250 | di->flags |= FLAG_REP; 251 | } 252 | 253 | /* If it's JeCXZ the ADDR_SIZE prefix affects them. */ 254 | if ((instFlags & (INST_PRE_ADDR_SIZE | INST_USE_EXMNEMONIC)) == (INST_PRE_ADDR_SIZE | INST_USE_EXMNEMONIC)) { 255 | ps->usedPrefixes |= INST_PRE_ADDR_SIZE; 256 | if (effAdrSz == Decode16Bits) di->opcode = ii->opcodeId; 257 | else if (effAdrSz == Decode32Bits) di->opcode = ((_InstInfoEx*)ii)->opcodeId2; 258 | /* Ignore REX.W in 64bits, JECXZ is promoted. */ 259 | else /* Decode64Bits */ di->opcode = ((_InstInfoEx*)ii)->opcodeId3; 260 | } 261 | 262 | /* LOOPxx instructions are also native instruction, but they are special case ones, ADDR_SIZE prefix affects them. */ 263 | else if ((instFlags & (INST_PRE_ADDR_SIZE | INST_NATIVE)) == (INST_PRE_ADDR_SIZE | INST_NATIVE)) { 264 | di->opcode = ii->opcodeId; 265 | 266 | /* If LOOPxx gets here from 64bits, it must be Decode32Bits because Address Size perfix is set. */ 267 | ps->usedPrefixes |= INST_PRE_ADDR_SIZE; 268 | } 269 | /* 270 | * Note: 271 | * If the instruction is prefixed by operand size we will format it in the non-default decoding mode! 272 | * So there might be a situation that an instruction of 32 bit gets formatted in 16 bits decoding mode. 273 | * Both ways should end up with a correct and expected formatting of the text. 274 | */ 275 | else if (effOpSz == Decode16Bits) { /* Decode16Bits */ 276 | 277 | /* Set operand size. */ 278 | FLAG_SET_OPSIZE(di, Decode16Bits); 279 | 280 | /* 281 | * If it's a special instruction which has two mnemonics, then use the 16 bits one + update usedPrefixes. 282 | * Note: use 16 bits mnemonic if that instruction supports 32 bit or 64 bit explicitly. 283 | */ 284 | if ((instFlags & INST_USE_EXMNEMONIC) && ((instFlags & (INST_32BITS | INST_64BITS)) == 0)) ps->usedPrefixes |= INST_PRE_OP_SIZE; 285 | di->opcode = ii->opcodeId; 286 | } else if (effOpSz == Decode32Bits) { /* Decode32Bits */ 287 | 288 | /* Set operand size. */ 289 | FLAG_SET_OPSIZE(di, Decode32Bits); 290 | 291 | /* Give a chance for special mnemonic instruction in 32 bits decoding. */ 292 | if (instFlags & INST_USE_EXMNEMONIC) { 293 | ps->usedPrefixes |= INST_PRE_OP_SIZE; 294 | /* Is it a special instruction which has another mnemonic for mod=11 ? */ 295 | if (instFlags & INST_MNEMONIC_MODRM_BASED) { 296 | if (modrm >= INST_DIVIDED_MODRM) di->opcode = ii->opcodeId; 297 | else di->opcode = ((_InstInfoEx*)ii)->opcodeId2; 298 | } else di->opcode = ((_InstInfoEx*)ii)->opcodeId2; 299 | } else di->opcode = ii->opcodeId; 300 | } else { /* Decode64Bits, note that some instructions might be decoded in Decode32Bits above. */ 301 | 302 | /* Set operand size. */ 303 | FLAG_SET_OPSIZE(di, Decode64Bits); 304 | 305 | if (instFlags & (INST_USE_EXMNEMONIC | INST_USE_EXMNEMONIC2)) { 306 | /* 307 | * We shouldn't be here for MODRM based mnemonics with a MOD=11, 308 | * because they must not use REX (otherwise it will get to the wrong instruction which share same opcode). 309 | * See XRSTOR and XSAVEOPT. 310 | */ 311 | if ((instFlags & INST_MNEMONIC_MODRM_BASED) && (modrm >= INST_DIVIDED_MODRM)) goto _Undecodable; 312 | 313 | /* Use third mnemonic, for 64 bits. */ 314 | if ((instFlags & INST_USE_EXMNEMONIC2) && (vrex & PREFIX_EX_W)) { 315 | ps->usedPrefixes |= INST_PRE_REX; 316 | di->opcode = ((_InstInfoEx*)ii)->opcodeId3; 317 | } else di->opcode = ((_InstInfoEx*)ii)->opcodeId2; /* Use second mnemonic. */ 318 | } else di->opcode = ii->opcodeId; 319 | } 320 | 321 | /* If it's a native instruction use OpSize Prefix. */ 322 | if ((instFlags & INST_NATIVE) && (ps->decodedPrefixes & INST_PRE_OP_SIZE)) ps->usedPrefixes |= INST_PRE_OP_SIZE; 323 | 324 | /* Check VEX mnemonics: */ 325 | if ((instFlags & INST_PRE_VEX) && 326 | (((((_InstInfoEx*)ii)->flagsEx & INST_MNEMONIC_VEXW_BASED) && (vrex & PREFIX_EX_W)) || 327 | ((((_InstInfoEx*)ii)->flagsEx & INST_MNEMONIC_VEXL_BASED) && (vrex & PREFIX_EX_L)))) { 328 | di->opcode = ((_InstInfoEx*)ii)->opcodeId2; 329 | } 330 | 331 | /* Or is it a special CMP instruction which needs a pseudo opcode suffix ? */ 332 | if (instFlags & INST_PSEUDO_OPCODE) { 333 | /* 334 | * The opcodeId is the offset to the FIRST pseudo compare mnemonic, 335 | * we will have to fix it so it offsets into the corrected mnemonic. 336 | * Therefore, we use another table to fix the offset. 337 | */ 338 | if (instFlags & INST_PRE_VEX) { 339 | /* Use the AVX pesudo compare mnemonics table. */ 340 | di->opcode = ii->opcodeId + VCmpMnemonicOffsets[cmpType]; 341 | } else { 342 | /* Use the SSE psuedo compare mnemonics table. */ 343 | di->opcode = ii->opcodeId + CmpMnemonicOffsets[cmpType]; 344 | } 345 | } 346 | 347 | /* 348 | * Store the address size inside the flags. 349 | * This is necessary for the caller to know the size of rSP when using PUSHA for example. 350 | */ 351 | FLAG_SET_ADDRSIZE(di, effAdrSz); 352 | 353 | /* Copy DST_WR flag. */ 354 | if (instFlags & INST_DST_WR) di->flags |= FLAG_DST_WR; 355 | 356 | /* Set the unused prefixes mask. */ 357 | di->unusedPrefixesMask = prefixes_set_unused_mask(ps); 358 | 359 | /* Copy instruction meta. */ 360 | di->meta = isi->meta; 361 | if (di->segment == 0) di->segment = R_NONE; 362 | 363 | /* Take into account the O_MEM base register for the mask. */ 364 | if (di->base != R_NONE) di->usedRegistersMask |= _REGISTERTORCLASS[di->base]; 365 | 366 | /* Copy CPU affected flags. */ 367 | di->modifiedFlagsMask = isi->modifiedFlags; 368 | di->testedFlagsMask = isi->testedFlags; 369 | di->undefinedFlagsMask = isi->undefinedFlags; 370 | 371 | /* Calculate the size of the instruction we've just decoded. */ 372 | di->size = (uint8_t)((ci->code - startCode) & 0xff); 373 | return DECRES_SUCCESS; 374 | 375 | _Undecodable: /* If the instruction couldn't be decoded for some reason, drop the first byte. */ 376 | memset(di, 0, sizeof(_DInst)); 377 | di->base = R_NONE; 378 | 379 | di->size = 1; 380 | /* Clean prefixes just in case... */ 381 | ps->usedPrefixes = 0; 382 | 383 | /* Special case for WAIT instruction: If it's dropped, you have to return a valid instruction! */ 384 | if (*startCode == INST_WAIT_INDEX) { 385 | di->opcode = I_WAIT; 386 | META_SET_ISC(di, ISC_INTEGER); 387 | return DECRES_SUCCESS; 388 | } 389 | 390 | /* Mark that we didn't manage to decode the instruction well, caller will drop it. */ 391 | return DECRES_INPUTERR; 392 | } 393 | 394 | /* 395 | * decode_internal 396 | * 397 | * supportOldIntr - Since now we work with new structure instead of the old _DecodedInst, we are still interested in backward compatibility. 398 | * So although, the array is now of type _DInst, we want to read it in jumps of the old array element's size. 399 | * This is in order to save memory allocation for conversion between the new and the old structures. 400 | * It really means we can do the conversion in-place now. 401 | */ 402 | _DecodeResult decode_internal(_CodeInfo* _ci, int supportOldIntr, _DInst result[], unsigned int maxResultCount, unsigned int* usedInstructionsCount) 403 | { 404 | _PrefixState ps; 405 | unsigned int prefixSize; 406 | _CodeInfo ci; 407 | 408 | _OffsetType codeOffset = _ci->codeOffset; 409 | const uint8_t* code = _ci->code; 410 | int codeLen = _ci->codeLen; 411 | 412 | /* 413 | * This is used for printing only, it is the real offset of where the whole instruction begins. 414 | * We need this variable in addition to codeOffset, because prefixes might change the real offset an instruction begins at. 415 | * So we keep track of both. 416 | */ 417 | _OffsetType startInstOffset = 0; 418 | 419 | const uint8_t* p; 420 | 421 | /* Current working decoded instruction in results. */ 422 | unsigned int nextPos = 0; 423 | _DInst *pdi = NULL; 424 | 425 | _OffsetType addrMask = (_OffsetType)-1; 426 | 427 | _DecodeResult decodeResult; 428 | 429 | #ifdef DISTORM_LIGHT 430 | supportOldIntr; /* Unreferenced. */ 431 | #endif 432 | 433 | if (_ci->features & DF_MAXIMUM_ADDR32) addrMask = 0xffffffff; 434 | else if (_ci->features & DF_MAXIMUM_ADDR16) addrMask = 0xffff; 435 | 436 | /* No entries are used yet. */ 437 | *usedInstructionsCount = 0; 438 | ci.dt = _ci->dt; 439 | _ci->nextOffset = codeOffset; 440 | 441 | /* Decode instructions as long as we have what to decode/enough room in entries. */ 442 | while (codeLen > 0) { 443 | 444 | /* startInstOffset holds the displayed offset of current instruction. */ 445 | startInstOffset = codeOffset; 446 | 447 | memset(&ps, 0, (size_t)((char*)&ps.pfxIndexer[0] - (char*)&ps)); 448 | memset(ps.pfxIndexer, PFXIDX_NONE, sizeof(int) * PFXIDX_MAX); 449 | ps.start = code; 450 | ps.last = code; 451 | prefixSize = 0; 452 | 453 | if (prefixes_is_valid(*code, ci.dt)) { 454 | prefixes_decode(code, codeLen, &ps, ci.dt); 455 | /* Count prefixes, start points to first prefix. */ 456 | prefixSize = (unsigned int)(ps.last - ps.start); 457 | /* 458 | * It might be that we will just notice that we ran out of bytes, or only prefixes 459 | * so we will have to drop everything and halt. 460 | * Also take into consideration of flow control instruction filter. 461 | */ 462 | codeLen -= prefixSize; 463 | if ((codeLen == 0) || (prefixSize == INST_MAXIMUM_SIZE)) { 464 | if (~_ci->features & DF_RETURN_FC_ONLY) { 465 | /* Make sure there is enough room. */ 466 | if (nextPos + (ps.last - code) > maxResultCount) return DECRES_MEMORYERR; 467 | 468 | for (p = code; p < ps.last; p++, startInstOffset++) { 469 | /* Use next entry. */ 470 | #ifndef DISTORM_LIGHT 471 | if (supportOldIntr) { 472 | pdi = (_DInst*)((char*)result + nextPos * sizeof(_DecodedInst)); 473 | } 474 | else 475 | #endif /* DISTORM_LIGHT */ 476 | { 477 | pdi = &result[nextPos]; 478 | } 479 | nextPos++; 480 | memset(pdi, 0, sizeof(_DInst)); 481 | 482 | pdi->flags = FLAG_NOT_DECODABLE; 483 | pdi->imm.byte = *p; 484 | pdi->size = 1; 485 | pdi->addr = startInstOffset & addrMask; 486 | } 487 | *usedInstructionsCount = nextPos; /* Include them all. */ 488 | } 489 | if (codeLen == 0) break; /* Bye bye, out of bytes. */ 490 | } 491 | code += prefixSize; 492 | codeOffset += prefixSize; 493 | 494 | /* If we got only prefixes continue to next instruction. */ 495 | if (prefixSize == INST_MAXIMUM_SIZE) continue; 496 | } 497 | 498 | /* 499 | * Now we decode the instruction and only then we do further prefixes handling. 500 | * This is because the instruction could not be decoded at all, or an instruction requires 501 | * a mandatory prefix, or some of the prefixes were useless, etc... 502 | 503 | * Even if there were a mandatory prefix, we already took into account its size as a normal prefix. 504 | * so prefixSize includes that, and the returned size in pdi is simply the size of the real(=without prefixes) instruction. 505 | */ 506 | if (ci.dt == Decode64Bits) { 507 | if (ps.decodedPrefixes & INST_PRE_REX) { 508 | /* REX prefix must precede first byte of instruction. */ 509 | if (ps.rexPos != (code - 1)) { 510 | ps.decodedPrefixes &= ~INST_PRE_REX; 511 | ps.prefixExtType = PET_NONE; 512 | prefixes_ignore(&ps, PFXIDX_REX); 513 | } 514 | /* 515 | * We will disable operand size prefix, 516 | * if it exists only after decoding the instruction, since it might be a mandatory prefix. 517 | * This will be done after calling inst_lookup in decode_inst. 518 | */ 519 | } 520 | /* In 64 bits, segment overrides of CS, DS, ES and SS are ignored. So don't take'em into account. */ 521 | if (ps.decodedPrefixes & INST_PRE_SEGOVRD_MASK32) { 522 | ps.decodedPrefixes &= ~INST_PRE_SEGOVRD_MASK32; 523 | prefixes_ignore(&ps, PFXIDX_SEG); 524 | } 525 | } 526 | 527 | /* Make sure there is at least one more entry to use, for the upcoming instruction. */ 528 | if (nextPos + 1 > maxResultCount) return DECRES_MEMORYERR; 529 | #ifndef DISTORM_LIGHT 530 | if (supportOldIntr) { 531 | pdi = (_DInst*)((char*)result + nextPos * sizeof(_DecodedInst)); 532 | } 533 | else 534 | #endif /* DISTORM_LIGHT */ 535 | { 536 | pdi = &result[nextPos]; 537 | } 538 | nextPos++; 539 | 540 | /* 541 | * The reason we copy these two again is because we have to keep track on the input ourselves. 542 | * There might be a case when an instruction is invalid, and then it will be counted as one byte only. 543 | * But that instruction already read a byte or two from the stream and only then returned the error. 544 | * Thus, we end up unsynchronized on the stream. 545 | * This way, we are totally safe, because we keep track after the call to decode_inst, using the returned size. 546 | */ 547 | ci.code = code; 548 | ci.codeLen = codeLen; 549 | /* Nobody uses codeOffset in the decoder itself, so spare it. */ 550 | 551 | decodeResult = decode_inst(&ci, &ps, pdi); 552 | 553 | /* See if we need to filter this instruction. */ 554 | if ((_ci->features & DF_RETURN_FC_ONLY) && (META_GET_FC(pdi->meta) == FC_NONE)) decodeResult = DECRES_FILTERED; 555 | 556 | /* Set address to the beginning of the instruction. */ 557 | pdi->addr = startInstOffset & addrMask; 558 | /* pdi->disp &= addrMask; */ 559 | 560 | /* Advance to next instruction. */ 561 | codeLen -= pdi->size; 562 | codeOffset += pdi->size; 563 | code += pdi->size; 564 | 565 | /* Instruction's size should include prefixes. */ 566 | pdi->size += (uint8_t)prefixSize; 567 | 568 | /* Drop all prefixes and the instruction itself, because the instruction wasn't successfully decoded. */ 569 | if ((decodeResult == DECRES_INPUTERR) && (~_ci->features & DF_RETURN_FC_ONLY)) { 570 | nextPos--; /* Undo last result. */ 571 | if ((prefixSize + 1) > 0) { /* 1 for the first instruction's byte. */ 572 | if ((nextPos + prefixSize + 1) > maxResultCount) return DECRES_MEMORYERR; 573 | 574 | for (p = ps.start; p < ps.last + 1; p++, startInstOffset++) { 575 | /* Use next entry. */ 576 | #ifndef DISTORM_LIGHT 577 | if (supportOldIntr) { 578 | pdi = (_DInst*)((char*)result + nextPos * sizeof(_DecodedInst)); 579 | } 580 | else 581 | #endif /* DISTORM_LIGHT */ 582 | { 583 | pdi = &result[nextPos]; 584 | } 585 | nextPos++; 586 | 587 | memset(pdi, 0, sizeof(_DInst)); 588 | pdi->flags = FLAG_NOT_DECODABLE; 589 | pdi->imm.byte = *p; 590 | pdi->size = 1; 591 | pdi->addr = startInstOffset & addrMask; 592 | } 593 | } 594 | } else if (decodeResult == DECRES_FILTERED) nextPos--; /* Return it to pool, since it was filtered. */ 595 | 596 | /* Alright, the caller can read, at least, up to this one. */ 597 | *usedInstructionsCount = nextPos; 598 | /* Fix next offset. */ 599 | _ci->nextOffset = codeOffset; 600 | 601 | /* Check whether we need to stop on any flow control instruction. */ 602 | if ((decodeResult == DECRES_SUCCESS) && (_ci->features & DF_STOP_ON_FLOW_CONTROL)) { 603 | if (((_ci->features & DF_STOP_ON_CALL) && (META_GET_FC(pdi->meta) == FC_CALL)) || 604 | ((_ci->features & DF_STOP_ON_RET) && (META_GET_FC(pdi->meta) == FC_RET)) || 605 | ((_ci->features & DF_STOP_ON_SYS) && (META_GET_FC(pdi->meta) == FC_SYS)) || 606 | ((_ci->features & DF_STOP_ON_UNC_BRANCH) && (META_GET_FC(pdi->meta) == FC_UNC_BRANCH)) || 607 | ((_ci->features & DF_STOP_ON_CND_BRANCH) && (META_GET_FC(pdi->meta) == FC_CND_BRANCH)) || 608 | ((_ci->features & DF_STOP_ON_INT) && (META_GET_FC(pdi->meta) == FC_INT)) || 609 | ((_ci->features & DF_STOP_ON_CMOV) && (META_GET_FC(pdi->meta) == FC_CMOV))) 610 | return DECRES_SUCCESS; 611 | } 612 | } 613 | 614 | return DECRES_SUCCESS; 615 | } 616 | --------------------------------------------------------------------------------