├── 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 |
--------------------------------------------------------------------------------