├── .github └── workflows │ └── py.yml ├── .gitignore ├── COPYING ├── MANIFEST.in ├── README.md ├── disOps ├── disOps.py ├── registers.py ├── x86db.py ├── x86generator.py ├── x86header.py └── x86sets.py ├── examples ├── cs │ ├── TestdiStorm │ │ ├── Program.cs │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ └── TestdiStorm.csproj │ ├── distorm-net.sln │ ├── distorm-net │ │ ├── CodeInfo.cs │ │ ├── DecodedInst.cs │ │ ├── DecodedResult.cs │ │ ├── DecomposedInst.cs │ │ ├── DecomposedResult.cs │ │ ├── Opcodes.cs │ │ ├── Opcodes.tt │ │ ├── Operand.cs │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ ├── diStorm3.cs │ │ └── distorm-net.csproj │ └── readme ├── ddk │ ├── README │ ├── distorm.ini │ ├── dummy.c │ ├── main.c │ ├── makefile │ └── sources ├── java │ ├── Makefile │ ├── distorm │ │ ├── .classpath │ │ ├── .project │ │ ├── .settings │ │ │ └── org.eclipse.jdt.core.prefs │ │ └── src │ │ │ ├── Main.java │ │ │ └── diStorm3 │ │ │ ├── CodeInfo.java │ │ │ ├── DecodedInst.java │ │ │ ├── DecodedResult.java │ │ │ ├── DecomposedInst.java │ │ │ ├── DecomposedResult.java │ │ │ ├── OpcodeEnum.java │ │ │ ├── Opcodes.java │ │ │ ├── Operand.java │ │ │ └── distorm3.java │ ├── jdistorm.c │ ├── jdistorm.h │ ├── jdistorm.sln │ └── jdistorm.vcproj ├── linux │ ├── Makefile │ └── main.c ├── tests │ ├── Makefile │ ├── main.cpp │ ├── tests.sln │ ├── tests.vcxproj │ └── tests.vcxproj.filters └── win32 │ ├── disasm.sln │ ├── disasm.vcxproj │ ├── disasm.vcxproj.filters │ └── main.cpp ├── include ├── distorm.h └── mnemonics.h ├── make ├── linux │ └── Makefile ├── mac │ └── Makefile ├── tinycc │ └── Makefile └── win32 │ ├── cdistorm.vcxproj │ ├── cdistorm.vcxproj.filters │ ├── distorm.sln │ ├── resource.h │ └── resource.rc ├── python ├── distorm3 │ ├── __init__.py │ ├── __main__.py │ └── _generated.py ├── python_module_init.c └── test_distorm3.py ├── setup.cfg ├── setup.py ├── src ├── config.h ├── decoder.c ├── decoder.h ├── distorm.c ├── instructions.c ├── instructions.h ├── insts.c ├── insts.h ├── mnemonics.c ├── operands.c ├── operands.h ├── prefix.c ├── prefix.h ├── textdefs.c ├── textdefs.h ├── wstring.h └── x86defs.h └── test-deps └── yasm-1.3.0-win64.exe /.github/workflows/py.yml: -------------------------------------------------------------------------------- 1 | name: Python package 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | runs-on: ${{ matrix.os }} 8 | strategy: 9 | max-parallel: 4 10 | matrix: 11 | os: [ubuntu-18.04, windows-latest, macos-latest] 12 | python-version: [3.x] 13 | steps: 14 | - uses: actions/checkout@v1 15 | - name: Set up Python ${{ matrix.python-version }} 16 | uses: actions/setup-python@v1 17 | with: 18 | python-version: ${{ matrix.python-version }} 19 | - uses: ilammy/msvc-dev-cmd@v1 20 | - name: Build and install package 21 | run: | 22 | python -m pip install --upgrade pip setuptools wheel 23 | python setup.py bdist_wheel 24 | pip install --find-links=dist --no-index distorm3 25 | - uses: actions/upload-artifact@v1 26 | with: 27 | name: Wheels 28 | path: dist 29 | - name: Test importing 30 | run: python -c 'import distorm3' 31 | - name: Install yasm (macOS) 32 | run: brew install yasm 33 | if: runner.os == 'macOS' 34 | - name: Install yasm (Ubuntu) 35 | run: sudo apt-get install -y yasm 36 | if: runner.os == 'Linux' 37 | - name: Copy yasm (Windows) 38 | run: copy test-deps\yasm-1.3.0-win64.exe python\yasm.exe 39 | if: runner.os == 'Windows' 40 | - name: Run test_distorm3.py 41 | working-directory: ./python 42 | run: python test_distorm3.py 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.egg-info 2 | *.py[cod] 3 | *.so 4 | build 5 | dist 6 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | :[diStorm3}: 2 | The ultimate disassembler library. 3 | Copyright (c) 2003-2021, Gil Dabah 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | * Neither the name of the Gil Dabah nor the 14 | names of its contributors may be used to endorse or promote products 15 | derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL GIL DABAH BE LIABLE FOR ANY 21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include COPYING setup.cfg setup.py 2 | include make\win32\cdistorm.vcxproj make\win32\cdistorm.vcxproj.filters make\win32\distorm.sln make\win32\resource.h make\win32\Resource.rc 3 | recursive-include src *.c *.h 4 | recursive-include include *.h 5 | recursive-include python *.py 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Powerful Disassembler Library For x86/AMD64 2 | ----------- 3 | 4 | Welcome to the diStorm3 binary stream disassembler library project. 5 | 6 | diStorm3 is really a decomposer, which means it takes an instruction and returns a binary structure which describes it rather than static text, which is great for advanced binary code analysis. 7 | 8 | diStorm3 is super lightweight (~45KB), ultra fast and easy to use (a single API), licensed under BSD! 9 | 10 | For a light hooking library see the https://github.com/gdabah/distormx project. 11 | 12 | "We benchmarked five popular open-source disassembly libraries and chose diStorm3, which had the best performance (and furthermore, has complete 64-bit support).", July 2014, Quoting David Williams-King in his Thesis about Binary Shuffling. 13 | 14 | Installing diStorm3 - 15 | 'python -m pip install distorm3' 16 | 17 | RTFM, the wiki has plenty of info. 18 | -------------------------------------------------------------------------------- /disOps/disOps.py: -------------------------------------------------------------------------------- 1 | # 2 | # disOps.py v 1.0.0 3 | # 4 | # Copyright (C) 2003-2020 Gil Dabah, http://ragestorm.net/distorm/ 5 | # 6 | # disOps is a part of the diStorm project, but can be used for anything. 7 | # The generated output is tightly coupled with diStorm data structures which can be found at instructions.h. 8 | # The code in diStorm that actually walks these structures is found at instructions.c. 9 | # 10 | # Since the DB was built purposely for diStorm, there are some 11 | # Known issues: 12 | # 1. ARPL/MOVSXD information in DB is stored as ARPL. 13 | # Since ARPL and MOVSXD share the same opcode this DB doesn't support this mix. 14 | # Therefore, if you use this DB for x64 instructions, you have to take care of this one. 15 | # 16 | # 2. SSE CMP pseudo instructions have the DEFAULT suffix letters of its type in the second mnemonic, 17 | # the third operand, Imm8 which is responsible for determining the suffix, 18 | # doesn't appear in the operands list but rather an InstFlag.PSEUDO_OPCODE implies this behavior. 19 | # 20 | # 3. The WAIT instruction is a bit problematic from a static DB point of view, read the comments in init_FPU in x86sets.py. 21 | # 22 | # 4. The OpLen.OL_33, [0x66, 0x0f, 0x78, 0x0], ["EXTRQ"] is very problematic as well. 23 | # Since there's another 8 group table after the 0x78 byte in this case, but it's already a Prefixed table. 24 | # Therefore, we will handle it as a normal 0x78 instruction with a mandatory prefix of 0x66. 25 | # But the REG (=0) field of the ModRM byte will be checked in the decoder by a flag that states so. 26 | # Otherwise, another normal table after Prefixed table really complicates matters, 27 | # and doesn't worth the hassle for one exceptional instruction. 28 | # 29 | # 5. The NOP (0x90) instruction is really set in the DB as xchg rAX, rAX. Rather than true NOP, this is because of x64 behavior. 30 | # Hence, it will be decided in runtime when decoding streams according to the mode. 31 | # 32 | # 6. The PAUSE (0xf3, 0x90) instruction isn't found in the DB, it will be returned directly by diStorm. 33 | # This is because the 0xf3 in this case is not a mandatory prefix, and we don't want it to be built as part of a prefixed table. 34 | # 35 | # 7. The IO String instructions don't have explicit form and they don't support segments. 36 | # It's up to diStorm to decide what to do with the operands and which segment is default and overrided. 37 | # 38 | # 8. Since opcodeId is an offset into the mnemonics table, the psuedo compare mnemonics needs a helper table to fix the offset. 39 | # Psuedo compare instructions work in such a way that only the first instruction is defined in the DB. 40 | # The rest are found using the third operand (that's why they are psuedo). 41 | # 42 | # To maximize the usage of this DB, one should learn the documentation of diStorm regarding the InstFlag and Operands Types. 43 | # 44 | 45 | import re 46 | import time 47 | import functools 48 | import os 49 | import x86sets 50 | import x86db 51 | import x86generator 52 | 53 | # Work with multi line and dot-all. 54 | reFlags = re.M | re.S 55 | 56 | def CreateMnemonicsC(mnemonicsIds): 57 | """ Create the opcodes arrays for C header files. """ 58 | opsEnum = "typedef enum {\n\tI_UNDEFINED = 0, " 59 | pos = 0 60 | l2 = sorted(mnemonicsIds.keys()) 61 | for i in l2: 62 | s = "I_%s = %d" % (i.replace(" ", "_").replace(",", ""), mnemonicsIds[i]) 63 | if i != l2[-1]: 64 | s += "," 65 | pos += len(s) 66 | if pos >= 70: 67 | s += "\n\t" 68 | pos = 0 69 | elif i != l2[-1]: 70 | s += " " 71 | opsEnum += s 72 | opsEnum += "\n} _InstructionType;" 73 | 74 | # Mnemonics are sorted by insertion order. (Psuedo mnemonics depend on this!) 75 | # NOTE: EXTRA BACKSLASHES FORE RE.SUB !!! 76 | s = "const unsigned char _MNEMONICS[] =\n\"\\\\x09\" \"UNDEFINED\\\\0\" " 77 | l = list(zip(mnemonicsIds.keys(), mnemonicsIds.values())) 78 | l = sorted(l, key=functools.cmp_to_key(lambda x, y: x[1] - y[1])) 79 | for i in l: 80 | s += "\"\\\\x%02x\" \"%s\\\\0\" " % (len(i[0]), i[0]) 81 | if len(s) - s.rfind("\n") >= 76: 82 | s += "\\\\\n" 83 | s = s[:-1] # Ignore last space. 84 | s += " \\\\\\n\"" + "\\\\x00" * 20 + "\"; /* Sentinel mnemonic. */" 85 | # Return enum & mnemonics. 86 | return (opsEnum, s) 87 | 88 | def CreateMnemonicsPython(mnemonicsIds): 89 | """ Create the opcodes dictionary for Python. """ 90 | s = "Mnemonics = {\n" 91 | for i in mnemonicsIds: 92 | s += "0x%x: \"%s\", " % (mnemonicsIds[i], i) 93 | if len(s) - s.rfind("\n") >= 76: 94 | s = s[:-1] + "\n" 95 | # Fix ending of the block. 96 | s = s[:-2] # Remote last comma/space we always add for the last line. 97 | if s[-1] != "\n": 98 | s += "\n" 99 | # Return mnemonics dictionary only. 100 | return s + "}" 101 | 102 | def CreateMnemonicsJava(mnemonicsIds): 103 | """ Create the opcodes dictionary/enum for Java. """ 104 | s = "public enum OpcodeEnum {\n\tUNDEFINED, " 105 | for i in mnemonicsIds: 106 | s += "%s, " % (i.replace(" ", "_").replace(",", "")) 107 | if len(s) - s.rfind("\n") >= 76: 108 | s = s[:-1] + "\n\t" 109 | # Fix ending of the block. 110 | s = s[:-2] # Remote last comma/space we always add for the last line. 111 | if s[-1] != "\n": 112 | s += "\n" 113 | opsEnum = s + "}" 114 | s = "static {\n\t\tmOpcodes.put(0, OpcodeEnum.UNDEFINED);\n" 115 | for i in mnemonicsIds: 116 | s += "\t\tmOpcodes.put(0x%x, OpcodeEnum.%s);\n" % (mnemonicsIds[i], i.replace(" ", "_").replace(",", "")) 117 | s += "\t}" 118 | # Return enum & mnemonics. 119 | return (opsEnum, s) 120 | 121 | def WriteMnemonicsC(mnemonicsIds): 122 | """ Write the enum of opcods and their corresponding mnemonics to the C files. """ 123 | path = os.path.join("..", "include", "mnemonics.h") 124 | print("- Try rewriting mnemonics for %s." % path) 125 | e, m = CreateMnemonicsC(mnemonicsIds) 126 | old = open(path, "r").read() 127 | rePattern = "typedef.{5,20}I_UNDEFINED.*?_InstructionType\;" 128 | if re.compile(rePattern, reFlags).search(old) == None: 129 | raise Exception("Couldn't find matching mnemonics enum block for substitution in " + path) 130 | new = re.sub(rePattern, e, old, 1, reFlags) 131 | open(path, "w").write(new) 132 | print("Succeeded") 133 | 134 | path = os.path.join("..", "src", "mnemonics.c") 135 | print("- Try rewriting mnemonics for %s." % path) 136 | old = open(path, "r").read() 137 | rePattern = "const unsigned char _MNEMONICS\[\] =.*?\*/" 138 | if re.compile(rePattern, reFlags).search(old) == None: 139 | raise Exception("Couldn't find matching mnemonics text block for substitution in " + path) 140 | new = re.sub(rePattern, m, old, 1, reFlags) 141 | open(path, "w").write(new) 142 | print("Succeeded") 143 | 144 | def WriteMnemonicsPython(mnemonicsIds): 145 | """ Write the dictionary of opcods to the python module. """ 146 | # 147 | # Fix Python dictionary inside distorm3/_generated.py. 148 | # 149 | path = os.path.join("..", "python", "distorm3", "_generated.py") 150 | print("- Try rewriting mnemonics for %s." % path) 151 | d = CreateMnemonicsPython(mnemonicsIds) 152 | old = open(path, "r").read() 153 | rePattern = "Mnemonics = \{.*?\}" 154 | if re.compile(rePattern, reFlags).search(old) == None: 155 | raise Exception("Couldn't find matching mnemonics dictionary for substitution in " + path) 156 | new = re.sub(rePattern, d, old, 1, reFlags) 157 | open(path, "w").write(new) 158 | print("Succeeded") 159 | 160 | def WriteMnemonicsJava(mnemonicsIds): 161 | """ Write the enum of opcods and their corresponding mnemonics to the Java files. """ 162 | # 163 | # Fix Java enum and mnemonics arrays 164 | # 165 | path = os.path.join("..", "examples", "java", "distorm", "src", "diStorm3", "OpcodeEnum.java") 166 | print("- Try rewriting mnemonics for %s." % path) 167 | e, m = CreateMnemonicsJava(mnemonicsIds) 168 | old = open(path, "r").read() 169 | rePattern = "public enum OpcodeEnum \{.*?}" 170 | if re.compile(rePattern, reFlags).search(old) == None: 171 | raise Exception("Couldn't find matching mnemonics enum block for substitution in " + path) 172 | new = re.sub(rePattern, e, old, 1, reFlags) 173 | open(path, "w").write(new) 174 | print("Succeeded") 175 | 176 | path = os.path.join("..", "examples", "java", "distorm", "src", "diStorm3", "Opcodes.java") 177 | print("- Try rewriting mnemonics for %s." % path) 178 | old = open(path, "r").read() 179 | rePattern = "static \{.*?}" 180 | if re.compile(rePattern, reFlags).search(old) == None: 181 | raise Exception("Couldn't find matching mnemonics text block for substitution in " + path) 182 | new = re.sub(rePattern, m, old, 1, reFlags) 183 | open(path, "w").write(new) 184 | print("Succeeded") 185 | 186 | def WriteInstsC(lists): 187 | """ Write the tables of the instructions in the C source code. """ 188 | path = os.path.join("..", "src", "insts.c") 189 | print("- Try rewriting instructions for %s." % path) 190 | old = open(path, "r").read() 191 | pos = old.find("/*\n * GENERATED") 192 | if pos == -1: 193 | raise Exception("Can't find marker in %s" % path) 194 | new = old[:pos] 195 | new += "/*\n * GENERATED BY disOps at %s\n */\n\n" % time.asctime() 196 | new += lists 197 | open(path, "w").write(new) 198 | print("Succeeded") 199 | 200 | def main(): 201 | # Init the 80x86/x64 instructions sets DB. 202 | db = x86db.InstructionsDB() 203 | x86InstructionsSet = x86sets.Instructions(db.SetInstruction) 204 | # Generate all tables of id's and pointers with the instructions themselves. 205 | mnemonicsIds, lists = x86generator.CreateTables(db) 206 | # Rewrite C instructions tables. 207 | WriteInstsC(lists) 208 | # Rewrite mnemonics of the C source code. 209 | WriteMnemonicsC(mnemonicsIds) 210 | # Rewrite mnemonics for the Python module. 211 | WriteMnemonicsPython(mnemonicsIds) 212 | # Rewrite mnemonics for the Java binding example code. 213 | WriteMnemonicsJava(mnemonicsIds) 214 | # C#: 215 | # Note that it will update its mnemonics upon compilation by taking them directly from the C code. 216 | 217 | main() 218 | -------------------------------------------------------------------------------- /disOps/registers.py: -------------------------------------------------------------------------------- 1 | # All VIAL and diStorm3 code are based on the order of this list, do NOT edit! 2 | REGISTERS = [ 3 | "RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", "XX", 4 | "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", "R8D", "R9D", "R10D", "R11D", "R12D", "R13D", "R14D", "R15D", "XX", 5 | "AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI", "R8W", "R9W", "R10W", "R11W", "R12W", "R13W", "R14W", "R15W", "XX", 6 | "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH", "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B", "XX", 7 | "SPL", "BPL", "SIL", "DIL", "XX", 8 | "ES", "CS", "SS", "DS", "FS", "GS", "XX", 9 | "RIP", "XX", 10 | "ST0", "ST1", "ST2", "ST3", "ST4", "ST5", "ST6", "ST7", "XX", 11 | "MM0", "MM1", "MM2", "MM3", "MM4", "MM5", "MM6", "MM7", "XX", 12 | "XMM0", "XMM1", "XMM2", "XMM3", "XMM4", "XMM5", "XMM6", "XMM7", "XMM8", "XMM9", "XMM10", "XMM11", "XMM12", "XMM13", "XMM14", "XMM15", "XX", 13 | "YMM0", "YMM1", "YMM2", "YMM3", "YMM4", "YMM5", "YMM6", "YMM7", "YMM8", "YMM9", "YMM10", "YMM11", "YMM12", "YMM13", "YMM14", "YMM15", "XX", 14 | "CR0", "", "CR2", "CR3", "CR4", "", "", "", "CR8", "XX", 15 | "DR0", "DR1", "DR2", "DR3", "", "", "DR6", "DR7"] 16 | 17 | regsText = "const _WRegister _REGISTERS[] = {\n\t" 18 | regsEnum = "typedef enum {\n\t" 19 | old = "*" 20 | unused = 0 21 | for i in REGISTERS: 22 | if old != "*": 23 | if old == "XX": 24 | regsText += "\n\t" 25 | regsEnum += "\n\t" 26 | old = i 27 | continue 28 | else: 29 | regsText += "{%d, \"%s\"}," % (len(old), old) 30 | if len(old): 31 | regsEnum += "R_%s," % old 32 | else: 33 | regsEnum += "R_UNUSED%d," % unused 34 | unused += 1 35 | if i != "XX": 36 | regsText += " " 37 | regsEnum += " " 38 | old = i 39 | regsText += "{%d, \"%s\"},\n\t{0, \"\"} /* There must be an empty last reg, see strcat_WSR. */\n};\n" % (len(old), old) 40 | regsEnum += "R_" + old + "\n} _RegisterType;\n" 41 | 42 | print(regsEnum) 43 | print(regsText) 44 | -------------------------------------------------------------------------------- /disOps/x86header.py: -------------------------------------------------------------------------------- 1 | # 2 | # x86header.py 3 | # 4 | # Copyright (C) 2009 Gil Dabah, http://ragestorm.net/disops/ 5 | # 6 | 7 | class OperandType: 8 | """ Types of possible operands in an opcode. 9 | Refer to the diStorm's documentation or diStorm's instructions.h 10 | for more explanation about every one of them. """ 11 | (NONE, 12 | # REG only operands: 13 | IMM8, 14 | IMM16, 15 | IMM_FULL, 16 | IMM32, 17 | SEIMM8, 18 | REG8, 19 | REG16, 20 | REG_FULL, 21 | REG32, 22 | REG32_64, 23 | ACC8, 24 | ACC16, 25 | ACC_FULL, 26 | ACC_FULL_NOT64, 27 | RELCB, 28 | RELC_FULL, 29 | IB_RB, 30 | IB_R_FULL, 31 | MOFFS8, 32 | MOFFS_FULL, 33 | REGI_ESI, 34 | REGI_EDI, 35 | REGI_EBXAL, 36 | REGI_EAX, 37 | REGDX, 38 | REGECX, 39 | FPU_SI, 40 | FPU_SSI, 41 | FPU_SIS, 42 | XMM, 43 | XMM_RM, 44 | REGXMM0, 45 | WREG32_64, 46 | VXMM, 47 | XMM_IMM, 48 | YXMM, 49 | YXMM_IMM, 50 | YMM, 51 | VYMM, 52 | VYXMM, 53 | CONST1, 54 | REGCL, 55 | CREG, 56 | DREG, 57 | SREG, 58 | SEG, 59 | IMM16_1, 60 | IMM8_1, 61 | IMM8_2, 62 | PTR16_FULL, 63 | FREG32_64_RM, 64 | MM, 65 | MM_RM, 66 | # MEM only operands: 67 | MEM, 68 | MEM32, 69 | MEM32_64, 70 | MEM64, 71 | MEM64_128, 72 | MEM128, 73 | MEM16_FULL, 74 | MEM16_3264, 75 | MEM_OPT, 76 | FPUM16, 77 | FPUM32, 78 | FPUM64, 79 | FPUM80, 80 | LMEM128_256, 81 | # MEM & REG operands ahead: 82 | RM8, 83 | RM16, 84 | RM32, 85 | RFULL_M16, 86 | RM_FULL, 87 | WRM32_64, 88 | R32_64_M8, 89 | R32_64_M16, 90 | RM32_64, 91 | RM16_32, 92 | R32_M8, 93 | R32_M16, 94 | REG32_64_M8, 95 | REG32_64_M16, 96 | MM32, 97 | MM64, 98 | XMM16, 99 | XMM32, 100 | XMM64, 101 | XMM128, 102 | WXMM32_64, 103 | YMM256, 104 | YXMM64_256, 105 | YXMM128_256, 106 | LXMM64_128) = range(93) 107 | 108 | class OpcodeLength: 109 | """ The length of the opcode in bytes. 110 | Where a suffix of '3' means we have to read the REG field of the ModR/M byte (REG size is 3 bits). 111 | Suffix of 'd' means it's a Divided instruction (see documentation), 112 | tells the disassembler to read the REG field or the whole next byte. 113 | 114 | OL_33 and OL_4 are used in raw opcode bytes, they include the mandatory prefix, 115 | therefore when they are defined in the instruction tables, the mandatory prefix table is added, 116 | and they become OL_23 and OL_3 correspondingly. There is no effective opcode which is more than 3 bytes. """ 117 | (OL_1, # 0 118 | OL_13, # 1 119 | OL_1d, # 2 - Can be prefixed (only by WAIT/9b) 120 | OL_2, # 3 - Can be prefixed 121 | OL_23, # 4 - Can be prefixed 122 | OL_2d, # 5 123 | OL_3, # 6 - Can be prefixed 124 | OL_33, # 7 - Internal only 125 | OL_4 # 8 - Internal only 126 | ) = range(9) 127 | 128 | """ Next-Opcode-Length dictionary is used in order to recursively build the instructions' tables dynamically. 129 | It is used in such a way that it indicates how many more nested tables 130 | we have to build and link starting from a given OL. """ 131 | NextOL = {OL_13: OL_1, OL_1d: OL_1, OL_2: OL_1, OL_23: OL_13, 132 | OL_2d: OL_1d, OL_3: OL_2, OL_33: OL_23, OL_4: OL_3} 133 | 134 | class InstFlag: 135 | """ Instruction Flag contains all bit mask constants for describing an instruction. 136 | You can bitwise-or the flags. See diStorm's documentation for more explanation. 137 | 138 | The GEN_BLOCK is a special flag, it is used in the tables generator only; 139 | See GenBlock class inside x86db.py. """ 140 | FLAGS_EX_START_INDEX = 32 141 | INST_FLAGS_NONE = 0 142 | (MODRM_REQUIRED, # 0 143 | NOT_DIVIDED, # 1 144 | _16BITS, # 2 145 | _32BITS, # 3 146 | PRE_LOCK, # 4 147 | PRE_REPNZ, # 5 148 | PRE_REP, # 6 149 | PRE_CS, # 7 150 | PRE_SS, # 8 151 | PRE_DS, # 9 152 | PRE_ES, # 10 153 | PRE_FS, # 11 154 | PRE_GS, # 12 155 | PRE_OP_SIZE, # 13 156 | PRE_ADDR_SIZE, # 14 157 | NATIVE, # 15 158 | USE_EXMNEMONIC, # 16 159 | USE_OP3, # 17 160 | USE_OP4, # 18 161 | MNEMONIC_MODRM_BASED, # 19 162 | MODRR_REQUIRED, # 20 163 | _3DNOW_FETCH, # 21 164 | PSEUDO_OPCODE, # 22 165 | INVALID_64BITS, # 23 166 | _64BITS, # 24 167 | PRE_REX, # 25 168 | USE_EXMNEMONIC2, # 26 169 | _64BITS_FETCH, # 27 170 | FORCE_REG0, # 28 171 | PRE_VEX, # 29 172 | MODRM_INCLUDED, # 30 173 | DST_WR, # 31 174 | VEX_L, # 32 From here on: flagsEx. 175 | VEX_W, # 33 176 | MNEMONIC_VEXW_BASED, # 34 177 | MNEMONIC_VEXL_BASED, # 35 178 | FORCE_VEXL, # 36 179 | MODRR_BASED, # 37 180 | VEX_V_UNUSED, # 38 181 | GEN_BLOCK, # 39 From here on: internal to disOps. 182 | EXPORTED # 40 183 | ) = [1 << i for i in range(41)] 184 | # Nodes are extended if they have any of the following flags: 185 | EXTENDED = (PRE_VEX | USE_EXMNEMONIC | USE_EXMNEMONIC2 | USE_OP3 | USE_OP4) 186 | SEGMENTS = (PRE_CS | PRE_SS | PRE_DS | PRE_ES | PRE_FS | PRE_FS) 187 | 188 | class ISetClass: 189 | """ Instruction-Set-Class indicates to which set the instruction belongs. 190 | These types are taken from the documentation of Intel/AMD. """ 191 | (INTEGER, 192 | FPU, 193 | P6, 194 | MMX, 195 | SSE, 196 | SSE2, 197 | SSE3, 198 | SSSE3, 199 | SSE4_1, 200 | SSE4_2, 201 | SSE4_A, 202 | _3DNOW, 203 | _3DNOWEXT, 204 | VMX, 205 | SVM, 206 | AVX, 207 | FMA, 208 | CLMUL, 209 | AES) = range(1, 20) 210 | 211 | class FlowControl: 212 | """ The flow control instruction will be flagged in the lo byte of the 'meta' field in _InstInfo of diStorm. 213 | They are used to distinguish between flow control instructions (such as: ret, call, jmp, jz, etc) to normal ones. """ 214 | (CALL, 215 | RET, 216 | SYS, 217 | UNC_BRANCH, 218 | CND_BRANCH, 219 | INT, 220 | CMOV, 221 | HLT) = range(1, 9) 222 | 223 | class NodeType: 224 | """ A node can really be an object holder for an instruction-info object or 225 | another table (list) with a different size. 226 | 227 | GROUP - 8 entries in the table 228 | FULL - 256 entries in the table. 229 | Divided - 72 entries in the table (ranges: 0x0-0x7, 0xc0-0xff). 230 | Prefixed - 12 entries in the table (none, 0x66, 0xf2, 0xf3). """ 231 | (NONE, # 0 232 | INFO, # 1 233 | INFOEX, # 2 234 | INFO_TREAT, # 3 235 | LIST_GROUP, # 4 236 | LIST_FULL, # 5 237 | LIST_DIVIDED, # 6 238 | LIST_PREFIXED # 7 239 | ) = range(0, 8) 240 | 241 | class CPUFlags: 242 | """ Specifies all the flags that the x86/x64 CPU supports, in a special compact order. """ 243 | (CF, # 0 244 | IF, # 1 245 | PF, # 2 246 | DF, # 3 247 | AF, # 4 248 | OF, # 5 249 | ZF, # 6 250 | SF # 7 251 | ) = [1 << i for i in range(8)] 252 | -------------------------------------------------------------------------------- /examples/cs/TestdiStorm/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Reflection.Emit; 4 | using diStorm; 5 | 6 | namespace TestdiStorm 7 | { 8 | public class Program 9 | { 10 | private static IntPtr LeakNativeMethodPtr(MethodInfo x) 11 | { 12 | 13 | //if ((x.MethodImplementationFlags & MethodImplAttributes.InternalCall) != 0) 14 | // Console.WriteLine("{0} is an InternalCall method. These methods always point to the same address.", x.Name); 15 | var domain = AppDomain.CurrentDomain; 16 | var dynAsm = new AssemblyName("MethodLeakAssembly"); 17 | var asmBuilder = domain.DefineDynamicAssembly(dynAsm, AssemblyBuilderAccess.Run); 18 | var moduleBuilder = asmBuilder.DefineDynamicModule("MethodLeakModule"); 19 | var typeBuilder = moduleBuilder.DefineType("MethodLeaker", TypeAttributes.Public); 20 | var p = new Type[0]; 21 | var methodBuilder = typeBuilder.DefineMethod("LeakNativeMethodPtr", MethodAttributes.Public | MethodAttributes.Static, typeof(IntPtr), null); 22 | var generator = methodBuilder.GetILGenerator(); 23 | 24 | // Push unmanaged pointer to MethodInfo onto the evaluation stack 25 | generator.Emit(OpCodes.Ldftn, x); 26 | // Convert the pointer to type - unsigned int64 27 | //generator.Emit(OpCodes.Conv_Ovf_U); 28 | generator.Emit(OpCodes.Ret); 29 | 30 | // Assemble everything 31 | var type = typeBuilder.CreateType(); 32 | 33 | var method = type.GetMethod("LeakNativeMethodPtr"); 34 | 35 | try { 36 | // Call the method and return its JITed address 37 | var address = (IntPtr) method.Invoke(null, new object[0]); 38 | 39 | Console.WriteLine("0x{0}", address.ToString(string.Format("X{0})", IntPtr.Size * 2))); 40 | return address; 41 | } 42 | catch (Exception e) { 43 | Console.WriteLine("{0} cannot return an unmanaged address."); 44 | } 45 | return IntPtr.Zero; 46 | } 47 | 48 | 49 | private static unsafe void Main(string[] args) 50 | { 51 | var buf = new byte[4]; 52 | buf[0] = (byte) 0xc3; 53 | buf[1] = (byte) 0x33; 54 | buf[2] = (byte) 0xc0; 55 | buf[3] = (byte) 0xc3; 56 | var ci = new CodeInfo((long) 0x1000, buf, DecodeType.Decode32Bits, 0); 57 | var dr = new DecodedResult(10); 58 | diStorm3.Decode(ci, dr); 59 | 60 | foreach (var x in dr.Instructions) { 61 | var s = String.Format("{0:X} {1} {2}", x.Offset, x.Mnemonic, x.Operands); 62 | Console.WriteLine(s); 63 | } 64 | 65 | var dr2 = new DecomposedResult(10); 66 | diStorm3.Decompose(ci, dr2); 67 | 68 | foreach (var y in dr2.Instructions) { 69 | if (y.Opcode != Opcode.RET) 70 | { 71 | var x = diStorm3.Format(ci, y); 72 | var s = String.Format("{0:X} {1} {2}", x.Offset, x.Mnemonic, x.Operands); 73 | Console.WriteLine(s); 74 | } 75 | } 76 | 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /examples/cs/TestdiStorm/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TestDiStorm")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TestDiStorm")] 13 | [assembly: AssemblyCopyright("Copyright © 2012")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("737cf66b-c136-47be-b92d-3f2fefbaf27a")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /examples/cs/TestdiStorm/TestdiStorm.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {2F2F3CBD-F968-47E4-ADEC-D42E42A924AC} 8 | Exe 9 | Properties 10 | TestDiStorm 11 | TestDiStorm 12 | v4.0 13 | 512 14 | 15 | 16 | 17 | x64 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | true 26 | false 27 | 28 | 29 | x64 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | true 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | {137ade63-2489-4235-91c6-6cb664cab63f} 55 | distorm-net 56 | 57 | 58 | 59 | 60 | copy $(SolutionDir)\..\..\distorm3.dll $(TargetDir) 61 | 62 | 69 | -------------------------------------------------------------------------------- /examples/cs/distorm-net.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "distorm-net", "distorm-net\distorm-net.csproj", "{137ADE63-2489-4235-91C6-6CB664CAB63F}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestdiStorm", "TestDiStorm\TestdiStorm.csproj", "{2F2F3CBD-F968-47E4-ADEC-D42E42A924AC}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {137ADE63-2489-4235-91C6-6CB664CAB63F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {137ADE63-2489-4235-91C6-6CB664CAB63F}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {137ADE63-2489-4235-91C6-6CB664CAB63F}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {137ADE63-2489-4235-91C6-6CB664CAB63F}.Release|Any CPU.Build.0 = Release|Any CPU 18 | {2F2F3CBD-F968-47E4-ADEC-D42E42A924AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {2F2F3CBD-F968-47E4-ADEC-D42E42A924AC}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {2F2F3CBD-F968-47E4-ADEC-D42E42A924AC}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {2F2F3CBD-F968-47E4-ADEC-D42E42A924AC}.Release|Any CPU.Build.0 = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /examples/cs/distorm-net/CodeInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace diStorm 4 | { 5 | public class CodeInfo 6 | { 7 | public CodeInfo(long codeOffset, byte[] rawCode, DecodeType dt, int features) 8 | { 9 | _code = new byte[rawCode.Length]; 10 | Array.Copy(rawCode, _code, _code.Length); 11 | 12 | _codeOffset = codeOffset; 13 | _decodeType = dt; 14 | _features = features; 15 | } 16 | 17 | internal long _codeOffset; 18 | internal long _nextOffset; 19 | internal byte[] _code; 20 | internal DecodeType _decodeType; 21 | internal int _features; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/cs/distorm-net/DecodedInst.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace diStorm 4 | { 5 | public class DecodedInst 6 | { 7 | internal DecodedInst() { } 8 | 9 | public string Mnemonic { get; internal set; } 10 | public string Operands { get; internal set; } 11 | public string Hex { get; internal set; } 12 | public uint Size { get; internal set; } 13 | public IntPtr Offset { get; internal set; } 14 | } 15 | } -------------------------------------------------------------------------------- /examples/cs/distorm-net/DecodedResult.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace diStorm 3 | { 4 | public class DecodedResult 5 | { 6 | public DecodedResult(int maxInstructions) 7 | { 8 | MaxInstructions = maxInstructions; 9 | Instructions = null; 10 | } 11 | public DecodedInst[] Instructions { get; internal set; } 12 | public int MaxInstructions { get; internal set; } 13 | } 14 | } -------------------------------------------------------------------------------- /examples/cs/distorm-net/DecomposedInst.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace diStorm 4 | { 5 | public class DecomposedInst 6 | { 7 | public class ImmVariant 8 | { 9 | public ulong Imm { get; internal set; } 10 | public int Size { get; internal set; } 11 | } 12 | public class DispVariant 13 | { 14 | public ulong Displacement { get; internal set; } 15 | public int Size { get; internal set; } 16 | } 17 | internal int _segment; 18 | public IntPtr Address { get; internal set; } 19 | public ushort Flags { get; internal set; } 20 | public int Size { get; internal set; } 21 | public Opcode Opcode { get; internal set; } 22 | public int Segment { get { return _segment & 0x7f; } } 23 | public bool IsSegmentDefault { get { return (_segment & 0x80) == 0x80; } } 24 | public int Base { get; internal set; } 25 | public int Scale { get; internal set; } 26 | public int UnusedPrefixesMask { get; internal set; } 27 | public int Meta { get; internal set; } 28 | public int RegistersMask { get; internal set; } 29 | public int ModifiedFlagsMask { get; internal set; } 30 | public int TestedFlagsMask { get; internal set; } 31 | public int UndefinedFlagsMask { get; internal set; } 32 | public ImmVariant Imm { get; internal set; } 33 | public DispVariant Disp { get; internal set; } 34 | public Operand[] Operands { get; internal set; } 35 | } 36 | } -------------------------------------------------------------------------------- /examples/cs/distorm-net/DecomposedResult.cs: -------------------------------------------------------------------------------- 1 | namespace diStorm 2 | { 3 | public class DecomposedResult 4 | { 5 | public DecomposedResult(int maxInstructions) 6 | { 7 | MaxInstructions = maxInstructions; 8 | Instructions = null; 9 | } 10 | 11 | public DecomposedInst[] Instructions { get; internal set; } 12 | public int MaxInstructions { get; private set; } 13 | } 14 | } -------------------------------------------------------------------------------- /examples/cs/distorm-net/Opcodes.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="true" hostSpecific="true" #> 2 | <#@ output extension=".cs" #> 3 | <#@ Assembly Name="System.Core" #> 4 | <#@ Assembly Name="System.Windows.Forms" #> 5 | <#@ import namespace="System" #> 6 | <#@ import namespace="System.IO" #> 7 | <#@ import namespace="System.Diagnostics" #> 8 | <#@ import namespace="System.Linq" #> 9 | <#@ import namespace="System.Collections" #> 10 | <#@ import namespace="System.Collections.Generic" #> 11 | <#@ import namespace="System.Text.RegularExpressions" #> 12 | // This file was auto generated from the distrom opcodes.h file 13 | // on <#= DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.FFF") #> 14 | <# 15 | var mnemonics = File.ReadAllText(Host.ResolvePath(@"..\..\..\include\mnemonics.h")); 16 | var instRe = new Regex("typedef enum {(.+)} _InstructionType;", RegexOptions.Singleline); 17 | var regRe = new Regex("typedef enum {(.+)} _RegisterType;", RegexOptions.Singleline); 18 | var m = instRe.Match(mnemonics); 19 | var insts = m.Groups[1].Value.Split(',').Select(x => new { 20 | Name = x.Split('=')[0].Trim().Substring(2), 21 | Value = x.Split('=')[1].Trim(), 22 | }).ToArray(); 23 | m = regRe.Match(mnemonics, m.Index + m.Length); 24 | var regs = m.Groups[1].Value.Split(',').Select(x => x.Trim()).ToArray(); 25 | #> 26 | namespace diStorm 27 | { 28 | public enum Opcode : ushort { 29 | <# foreach (var i in insts) { #> 30 | <#= i.Name #> = <#= i.Value #>,<# } #> 31 | } 32 | 33 | public enum Register { 34 | <# foreach (var r in regs) { #> 35 | <#= r #>,<# } #> 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/cs/distorm-net/Operand.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace diStorm 3 | { 4 | 5 | public enum OperandType : byte 6 | { 7 | None, 8 | Reg, 9 | Imm, 10 | Imm1, 11 | Imm2, 12 | Disp, 13 | Smem, 14 | Mem, 15 | Pc, 16 | Ptr 17 | } 18 | 19 | public class Operand 20 | { 21 | public OperandType Type { get; internal set; } 22 | public int Index { get; internal set; } 23 | public int Size { get; internal set; } 24 | } 25 | } -------------------------------------------------------------------------------- /examples/cs/distorm-net/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("distorm-net")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("distorm-net")] 13 | [assembly: AssemblyCopyright("Copyright © 2012")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("ddf3403b-11ea-4470-9fb3-03e68ac68fb5")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /examples/cs/distorm-net/diStorm3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace diStorm 6 | { 7 | public enum DecodeType 8 | { 9 | Decode16Bits, 10 | Decode32Bits, 11 | Decode64Bits 12 | } 13 | 14 | public class diStorm3 15 | { 16 | [StructLayout(LayoutKind.Sequential, Pack = 8)] 17 | public unsafe struct _CodeInfo 18 | { 19 | internal IntPtr codeOffset; 20 | internal IntPtr addrMask; 21 | internal IntPtr nextOffset; /* nextOffset is OUT only. */ 22 | internal byte* code; 23 | internal int codeLen; /* Using signed integer makes it easier to detect an underflow. */ 24 | internal DecodeType dt; 25 | internal int features; 26 | }; 27 | 28 | 29 | public struct _WString 30 | { 31 | public const int MAX_TEXT_SIZE = 48; 32 | public uint length; 33 | public unsafe fixed sbyte p[MAX_TEXT_SIZE]; /* p is a null terminated string. */ 34 | } 35 | 36 | [StructLayout(LayoutKind.Sequential, Pack = 8)] 37 | public struct _DecodedInst 38 | { 39 | public IntPtr offset; /* Start offset of the decoded instruction. */ 40 | public uint size; /* Size of decoded instruction. */ 41 | public _WString mnemonic; /* Mnemonic of decoded instruction, prefixed if required by REP, LOCK etc. */ 42 | public _WString operands; /* Operands of the decoded instruction, up to 3 operands, comma-seperated. */ 43 | public _WString instructionHex; /* Hex dump - little endian, including prefixes. */ 44 | }; 45 | 46 | 47 | /* Used by O_PTR: */ 48 | 49 | public struct PtrStruct 50 | { 51 | private ushort seg; 52 | /* Can be 16 or 32 bits, size is in ops[n].size. */ 53 | private uint off; 54 | }; 55 | 56 | /* Used by O_IMM1 (i1) and O_IMM2 (i2). ENTER instruction only. */ 57 | 58 | public struct ExStruct 59 | { 60 | private uint i1; 61 | private uint i2; 62 | }; 63 | 64 | [StructLayout(LayoutKind.Explicit)] 65 | public struct _Value 66 | { 67 | /* Used by O_IMM: */ 68 | [FieldOffset(0)] public sbyte sbyt; 69 | [FieldOffset(0)] public byte byt; 70 | [FieldOffset(0)] public short sword; 71 | [FieldOffset(0)] public ushort word; 72 | [FieldOffset(0)] public int sdword; 73 | [FieldOffset(0)] public uint dword; 74 | [FieldOffset(0)] public long sqword; /* All immediates are SIGN-EXTENDED to 64 bits! */ 75 | [FieldOffset(0)] public ulong qword; 76 | /* Used by O_PC: (Use GET_TARGET_ADDR).*/ 77 | [FieldOffset(0)] public IntPtr addr; /* It's a relative offset as for now. */ 78 | [FieldOffset(0)] public PtrStruct ptr; 79 | [FieldOffset(0)] public ExStruct ex; 80 | }; 81 | 82 | public struct _Operand 83 | { 84 | /* Type of operand: 85 | O_NONE: operand is to be ignored. 86 | O_REG: index holds global register index. 87 | O_IMM: instruction.imm. 88 | O_IMM1: instruction.imm.ex.i1. 89 | O_IMM2: instruction.imm.ex.i2. 90 | O_DISP: memory dereference with displacement only, instruction.disp. 91 | O_SMEM: simple memory dereference with optional displacement (a single register memory dereference). 92 | O_MEM: complex memory dereference (optional fields: s/i/b/disp). 93 | O_PC: the relative address of a branch instruction (instruction.imm.addr). 94 | O_PTR: the absolute target address of a far branch instruction (instruction.imm.ptr.seg/off). 95 | */ 96 | public OperandType type; /* _OperandType */ 97 | 98 | /* Index of: 99 | O_REG: holds global register index 100 | O_SMEM: holds the 'base' register. E.G: [ECX], [EBX+0x1234] are both in operand.index. 101 | O_MEM: holds the 'index' register. E.G: [EAX*4] is in operand.index. 102 | */ 103 | public byte index; 104 | 105 | /* Size of: 106 | O_REG: register 107 | O_IMM: instruction.imm 108 | O_IMM1: instruction.imm.ex.i1 109 | O_IMM2: instruction.imm.ex.i2 110 | O_DISP: instruction.disp 111 | O_SMEM: size of indirection. 112 | O_MEM: size of indirection. 113 | O_PC: size of the relative offset 114 | O_PTR: size of instruction.imm.ptr.off (16 or 32) 115 | */ 116 | public ushort size; 117 | }; 118 | 119 | public struct _DInst 120 | { 121 | public const int OPERANDS_NO = 4; 122 | private const int OPERANDS_SIZE = 4*OPERANDS_NO; 123 | 124 | /* Used by ops[n].type == O_IMM/O_IMM1&O_IMM2/O_PTR/O_PC. Its size is ops[n].size. */ 125 | internal _Value imm; 126 | /* Used by ops[n].type == O_SMEM/O_MEM/O_DISP. Its size is dispSize. */ 127 | internal ulong disp; 128 | /* Virtual address of first byte of instruction. */ 129 | internal IntPtr addr; 130 | /* General flags of instruction, holds prefixes and more, if FLAG_NOT_DECODABLE, instruction is invalid. */ 131 | internal ushort flags; 132 | /* Unused prefixes mask, for each bit that is set that prefix is not used (LSB is byte [addr + 0]). */ 133 | internal ushort unusedPrefixesMask; 134 | /* 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. */ 135 | internal ushort usedRegistersMask; 136 | /* ID of opcode in the global opcode table. Use for mnemonic look up. */ 137 | internal ushort opcode; 138 | /* Up to four operands per instruction, ignored if ops[n].type == O_NONE. */ 139 | private unsafe fixed byte ops_storage[OPERANDS_SIZE]; 140 | internal unsafe _Operand* ops 141 | { 142 | get 143 | { 144 | fixed (byte* p = ops_storage) 145 | { 146 | return (_Operand*) p; 147 | } 148 | } 149 | } 150 | /* Number of valid operands. */ 151 | internal byte opsNo; 152 | /* Size of the whole instruction. */ 153 | internal byte size; 154 | /* Segment information of memory indirection, default segment, or overridden one, can be -1. Use SEGMENT macros. */ 155 | internal byte segment; 156 | /* 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. */ 157 | internal byte ibase, scale; 158 | internal byte dispSize; 159 | /* Meta defines the instruction set class, and the flow control flags. Use META macros. */ 160 | internal ushort meta; 161 | /* The CPU flags that the instruction operates upon. */ 162 | internal ushort modifiedFlagsMask, testedFlagsMask, undefinedFlagsMask; 163 | }; 164 | 165 | [DllImport("distorm3")] 166 | private static extern unsafe void distorm_decompose64(void* codeInfo, void* dinsts, int maxInstructions, int* usedInstructions); 167 | 168 | [DllImport("distorm3")] 169 | private static extern unsafe void distorm_decode64(IntPtr codeOffset, byte* code, int codeLen, DecodeType dt, void *result, uint maxInstructions, uint* usedInstructionsCount); 170 | 171 | [DllImport("distorm3")] 172 | private static extern unsafe void distorm_format64(void* codeInfo, void* dinst, void* output); 173 | 174 | public static unsafe void* Malloc(int sz) 175 | { 176 | return Marshal.AllocHGlobal(new IntPtr(sz)).ToPointer(); 177 | } 178 | 179 | private static unsafe void Free(void* mem) 180 | { 181 | Marshal.FreeHGlobal(new IntPtr(mem)); 182 | } 183 | 184 | private static unsafe _CodeInfo* AcquireCodeInfoStruct(CodeInfo nci, out GCHandle gch) 185 | { 186 | var ci = (_CodeInfo*) Malloc(sizeof (_CodeInfo)); 187 | if (ci == null) 188 | throw new OutOfMemoryException(); 189 | 190 | Memset(ci, 0, sizeof (_CodeInfo)); 191 | 192 | ci->codeOffset = new IntPtr(nci._codeOffset); 193 | gch = GCHandle.Alloc(nci._code, GCHandleType.Pinned); 194 | 195 | ci->code = (byte*) gch.AddrOfPinnedObject().ToPointer(); 196 | ci->codeLen = nci._code.Length; 197 | ci->dt = nci._decodeType; 198 | ci->features = nci._features; 199 | return ci; 200 | } 201 | 202 | private static unsafe DecodedInst CreateDecodedInstObj(_DecodedInst* inst) 203 | { 204 | return new DecodedInst { 205 | Offset = inst->offset, 206 | Size = inst->size, 207 | Mnemonic = new String(inst->mnemonic.p), 208 | Operands = new String(inst->operands.p), 209 | Hex = new string(inst->instructionHex.p) 210 | }; 211 | } 212 | 213 | private static unsafe void Memset(void *p, int v, int sz) 214 | { 215 | } 216 | 217 | 218 | public static unsafe void Decompose(CodeInfo nci, DecomposedResult ndr) 219 | { 220 | _CodeInfo* ci = null; 221 | _DInst* insts = null; 222 | var gch = new GCHandle(); 223 | var usedInstructionsCount = 0; 224 | 225 | try 226 | { 227 | if ((ci = AcquireCodeInfoStruct(nci, out gch)) == null) 228 | throw new OutOfMemoryException(); 229 | 230 | var maxInstructions = ndr.MaxInstructions; 231 | 232 | if ((insts = (_DInst*) Malloc(maxInstructions*sizeof (_DInst))) == null) 233 | throw new OutOfMemoryException(); 234 | 235 | distorm_decompose64(ci, insts, maxInstructions, &usedInstructionsCount); 236 | 237 | var dinsts = new DecomposedInst[usedInstructionsCount]; 238 | 239 | for (var i = 0; i < usedInstructionsCount; i++) { 240 | var di = new DecomposedInst { 241 | Address = insts[i].addr, 242 | Flags = insts[i].flags, 243 | Size = insts[i].size, 244 | _segment = insts[i].segment, 245 | Base = insts[i].ibase, 246 | Scale = insts[i].scale, 247 | Opcode = (Opcode) insts[i].opcode, 248 | UnusedPrefixesMask = insts[i].unusedPrefixesMask, 249 | Meta = insts[i].meta, 250 | RegistersMask = insts[i].usedRegistersMask, 251 | ModifiedFlagsMask = insts[i].modifiedFlagsMask, 252 | TestedFlagsMask = insts[i].testedFlagsMask, 253 | UndefinedFlagsMask = insts[i].undefinedFlagsMask 254 | }; 255 | 256 | /* Simple fields: */ 257 | 258 | /* Immediate variant. */ 259 | var immVariant = new DecomposedInst.ImmVariant { 260 | Imm = insts[i].imm.qword, 261 | Size = 0 262 | }; 263 | /* The size of the immediate is in one of the operands, if at all. Look for it below. Zero by default. */ 264 | 265 | /* Count operands. */ 266 | var operandsNo = 0; 267 | for (operandsNo = 0; operandsNo < _DInst.OPERANDS_NO; operandsNo++) 268 | { 269 | if (insts[i].ops[operandsNo].type == OperandType.None) 270 | break; 271 | } 272 | 273 | var ops = new Operand[operandsNo]; 274 | 275 | for (var j = 0; j < operandsNo; j++) 276 | { 277 | if (insts[i].ops[j].type == OperandType.Imm) { 278 | /* Set the size of the immediate operand. */ 279 | immVariant.Size = insts[i].ops[j].size; 280 | } 281 | 282 | var op = new Operand { 283 | Type = insts[i].ops[j].type, 284 | Index = insts[i].ops[j].index, 285 | Size = insts[i].ops[j].size 286 | }; 287 | 288 | ops[j] = op; 289 | } 290 | di.Operands = ops; 291 | 292 | /* Attach the immediate variant. */ 293 | di.Imm = immVariant; 294 | 295 | /* Displacement variant. */ 296 | var disp = new DecomposedInst.DispVariant { 297 | Displacement = insts[i].disp, 298 | Size = insts[i].dispSize 299 | }; 300 | 301 | di.Disp = disp; 302 | dinsts[i] = di; 303 | } 304 | 305 | ndr.Instructions = dinsts; 306 | } 307 | finally 308 | { 309 | if (gch.IsAllocated) 310 | gch.Free(); 311 | if (ci != null) 312 | Free(ci); 313 | if (insts != null) 314 | Free(insts); 315 | } 316 | } 317 | 318 | public static unsafe void Decode(CodeInfo nci, DecodedResult dr) 319 | { 320 | _CodeInfo* ci = null; 321 | _DecodedInst* insts = null; 322 | var gch = new GCHandle(); 323 | uint usedInstructionsCount = 0; 324 | 325 | try 326 | { 327 | if ((ci = AcquireCodeInfoStruct(nci, out gch)) == null) 328 | throw new OutOfMemoryException(); 329 | 330 | var maxInstructions = dr.MaxInstructions; 331 | 332 | if ((insts = (_DecodedInst*) Malloc(maxInstructions*sizeof (_DecodedInst))) == null) 333 | throw new OutOfMemoryException(); 334 | 335 | distorm_decode64(ci->codeOffset, ci->code, ci->codeLen, ci->dt, insts, (uint) maxInstructions, 336 | &usedInstructionsCount); 337 | 338 | var dinsts = new DecodedInst[usedInstructionsCount]; 339 | 340 | for (var i = 0; i < usedInstructionsCount; i++) 341 | dinsts[i] = CreateDecodedInstObj(&insts[i]); 342 | dr.Instructions = dinsts; 343 | } 344 | finally { 345 | /* In case of an error, jInsts will get cleaned automatically. */ 346 | if (gch.IsAllocated) 347 | gch.Free(); 348 | if (ci != null) 349 | Free(ci); 350 | if (insts != null) 351 | Free(insts); 352 | } 353 | } 354 | 355 | 356 | public static unsafe DecodedInst Format(CodeInfo nci, DecomposedInst ndi) 357 | { 358 | var input = new _DInst(); 359 | _CodeInfo *ci = null; 360 | var gch = new GCHandle(); 361 | DecodedInst di; 362 | 363 | try 364 | { 365 | ci = AcquireCodeInfoStruct(nci, out gch); 366 | if (ci == null) 367 | throw new OutOfMemoryException(); 368 | 369 | input.addr = ndi.Address; 370 | input.flags = ndi.Flags; 371 | input.size = (byte) ndi.Size; 372 | input.segment = (byte) ndi._segment; 373 | input.ibase = (byte) ndi.Base; 374 | input.scale = (byte) ndi.Scale; 375 | input.opcode = (ushort) ndi.Opcode; 376 | /* unusedPrefixesMask is unused indeed, lol. */ 377 | input.meta = (ushort) ndi.Meta; 378 | /* Nor usedRegistersMask. */ 379 | 380 | int opsCount = ndi.Operands.Length; 381 | for (var i = 0; i < opsCount; i++) { 382 | var op = ndi.Operands[i]; 383 | if (op == null) continue; 384 | input.ops[i].index = (byte) op.Index; 385 | input.ops[i].type = op.Type; 386 | input.ops[i].size = (ushort) op.Size; 387 | } 388 | 389 | if (ndi.Imm != null) 390 | input.imm.qword = ndi.Imm.Imm; 391 | 392 | if (ndi.Disp != null) 393 | { 394 | input.disp = ndi.Disp.Displacement; 395 | input.dispSize = (byte) ndi.Disp.Size; 396 | } 397 | 398 | _DecodedInst output; 399 | distorm_format64(ci, &input, &output); 400 | 401 | di = CreateDecodedInstObj(&output); 402 | } 403 | finally 404 | { 405 | if (gch.IsAllocated) 406 | gch.Free(); 407 | if (ci != null) 408 | Free(ci); 409 | } 410 | return di; 411 | } 412 | } 413 | } 414 | -------------------------------------------------------------------------------- /examples/cs/distorm-net/distorm-net.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {137ADE63-2489-4235-91C6-6CB664CAB63F} 8 | Library 9 | Properties 10 | diStorm 11 | diStorm 12 | v4.0 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | true 25 | x64 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | true 35 | x64 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | True 51 | True 52 | Opcodes.tt 53 | 54 | 55 | 56 | 57 | 58 | TextTemplatingFileGenerator 59 | Opcodes.cs 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 80 | -------------------------------------------------------------------------------- /examples/cs/readme: -------------------------------------------------------------------------------- 1 | This is a .NET Wrapper of the distorm project for seamless decompilation of 32-bit and 64-bit intel binaries. 2 | This project is licensed under the GPLv3. 3 | By Dan Shechter -------------------------------------------------------------------------------- /examples/ddk/README: -------------------------------------------------------------------------------- 1 | diStorm3 for Ring 0 2 | Gil Dabah Aug 2010 3 | http://ragestorm.net/distorm/ 4 | 5 | Tested sample with DDK 7600.16385.1 using WinXPSP2. 6 | 7 | Steps of how to build the diStorm64 sample using the DDK. 8 | 9 | Warning - Make sure the path you extracted diStorm to does not include any spaces, otherwise you will get an error from the build. 10 | 11 | 1) Open the DDK's build environment, for example: "Win XP Free Build Environment", 12 | which readies the evnrionment variables for building a driver. Or run the SETENV.BAT in console. 13 | 14 | 2) Launch "build", once you're in the directory of the /ddkproj. 15 | 16 | 3) If everything worked smoothly, you should see a new file named "distorm.sys" under objfre_wxp_x86\i386 17 | (that's if you use WinXP and the Free Environment). 18 | 19 | - If you experienced any errors, try moving the whole distorm directory to c:\winddk\src\ 20 | (or any other directory tree which doesn't contain spaces in its name). 21 | 22 | 4) Now you will have to register the new driver: 23 | a. Copy the distorm.sys file to \windows\system32\drivers\. 24 | b. Use the DDK's regini.exe with the supplied distorm.ini. 25 | c. Restart Windows for the effect to take place. :( 26 | 27 | **The alternative is to use some tool like KmdManager.exe, which will register the driver without a need for the .ini file, nor a reboot. 28 | 29 | 30 | 5) Now open your favorite debug-strings monitor (mine is DebugView). 31 | Make sure you monitor kernel debug-strings. 32 | 33 | 6) Launching "net start distorm" from command line, will run the DriverEntry code in "main.c", 34 | which will disassemble a few instructions from the KeBugcheck routine and dump it using DbgPrint. 35 | 36 | 37 | NOTES: 38 | -+---- 39 | The sample uses the stack for storing the results from the decode function. 40 | If you have too many structures on the stack, you better allocate memory before calling the decode function, 41 | and later on free that memory. Don't use the NONPAGED pool if you don't really need it. 42 | 43 | _OffsetType is the type of the DecodedInstruction.Offset field, which defaults to 64bits, 44 | so make sure that when you print this variable you use %I64X, or when you use it anywhere else, you use the _OffsetType as well. 45 | Notice that we call directly distorm_decode64, since we SUPPORT_64BIT_OFFSET and because we don't have the macros of distorm.h. 46 | 47 | diStorm can be really compiled for all IRQL, it doesn't use any resource or the standard C library at all. 48 | Although the sample uses diStorm at PASSIVE level. 49 | -------------------------------------------------------------------------------- /examples/ddk/distorm.ini: -------------------------------------------------------------------------------- 1 | \registry\machine\system\currentcontrolset\services\distorm 2 | ImagePath = system32\drivers\distorm.sys 3 | DisplayName = "distorm" 4 | Type = REG_DWORD 0x1 5 | Start = REG_DWORD 0x3 6 | Group = Extended base 7 | ErrorControl = REG_DWORD 0x1 8 | \registry\machine\system\currentcontrolset\services\distorm\Parameters 9 | BreakOnEntry = REG_DWORD 0x0 10 | DebugMask = REG_DWORD 0x0 11 | LogEvents = REG_DWORD 0x0 -------------------------------------------------------------------------------- /examples/ddk/dummy.c: -------------------------------------------------------------------------------- 1 | // Since the DDK's nmake is limited with directories, we will bypass that with this simple hack. 2 | // Thanks to Razvan Hobeanu. 3 | // Sep 2009. 4 | 5 | 6 | #include "../src/mnemonics.c" 7 | #include "../src/wstring.c" 8 | #include "../src/textdefs.c" 9 | #include "../src/x86defs.c" 10 | #include "../src/prefix.c" 11 | #include "../src/operands.c" 12 | #include "../src/insts.c" 13 | #include "../src/instructions.c" 14 | #include "../src/distorm.c" 15 | #include "../src/decoder.c" 16 | -------------------------------------------------------------------------------- /examples/ddk/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * main.c 3 | * Sample kernel driver to show how diStorm can be easily compiled and used in Ring 0. 4 | * 5 | * /// Follow the README file in order to compile diStorm using the DDK. \\\ 6 | * 7 | * Izik, Gil Dabah 8 | * Jan 2007 9 | * http://ragestorm.net/distorm/ 10 | */ 11 | 12 | #include 13 | #include "../include/distorm.h" 14 | #include "dummy.c" 15 | 16 | // The number of the array of instructions the decoder function will use to return the disassembled instructions. 17 | // Play with this value for performance... 18 | #define MAX_INSTRUCTIONS (15) 19 | 20 | void DriverUnload(IN PDRIVER_OBJECT DriverObject) 21 | { 22 | } 23 | 24 | NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) 25 | { 26 | UNICODE_STRING pFcnName; 27 | 28 | // Holds the result of the decoding. 29 | _DecodeResult res; 30 | // Decoded instruction information. 31 | _DecodedInst decodedInstructions[MAX_INSTRUCTIONS]; 32 | // next is used for instruction's offset synchronization. 33 | // decodedInstructionsCount holds the count of filled instructions' array by the decoder. 34 | unsigned int decodedInstructionsCount = 0, i, next; 35 | // Default decoding mode is 32 bits, could be set by command line. 36 | _DecodeType dt = Decode32Bits; 37 | 38 | // Default offset for buffer is 0, could be set in command line. 39 | _OffsetType offset = 0; 40 | char* errch = NULL; 41 | 42 | // Buffer to disassemble. 43 | unsigned char *buf; 44 | int len = 100; 45 | 46 | // Register unload routine 47 | DriverObject->DriverUnload = DriverUnload; 48 | 49 | DbgPrint("diStorm Loaded!\n"); 50 | 51 | // Get address of KeBugCheck 52 | RtlInitUnicodeString(&pFcnName, L"KeBugCheck"); 53 | buf = (char *)MmGetSystemRoutineAddress(&pFcnName); 54 | offset = (unsigned) (_OffsetType)buf; 55 | 56 | DbgPrint("Resolving KeBugCheck @ 0x%08x\n", buf); 57 | // Decode the buffer at given offset (virtual address). 58 | 59 | while (1) { 60 | res = distorm_decode64(offset, (const unsigned char*)buf, len, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount); 61 | if (res == DECRES_INPUTERR) { 62 | DbgPrint(("NULL Buffer?!\n")); 63 | break; 64 | } 65 | 66 | for (i = 0; i < decodedInstructionsCount; i++) { 67 | // Note that we print the offset as a 64 bits variable!!! 68 | // It might be that you'll have to change it to %08X... 69 | DbgPrint("%08I64x (%02d) %s %s %s\n", decodedInstructions[i].offset, decodedInstructions[i].size, 70 | (char*)decodedInstructions[i].instructionHex.p, 71 | (char*)decodedInstructions[i].mnemonic.p, 72 | (char*)decodedInstructions[i].operands.p); 73 | } 74 | 75 | if (res == DECRES_SUCCESS || decodedInstructionsCount == 0) { 76 | break; // All instructions were decoded. 77 | } 78 | 79 | // Synchronize: 80 | next = (unsigned int)(decodedInstructions[decodedInstructionsCount-1].offset - offset); 81 | next += decodedInstructions[decodedInstructionsCount-1].size; 82 | 83 | // Advance ptr and recalc offset. 84 | buf += next; 85 | len -= next; 86 | offset += next; 87 | } 88 | 89 | DbgPrint(("Done!\n")); 90 | return STATUS_UNSUCCESSFUL; // Make sure the driver doesn't stay resident, so we can recompile and run again! 91 | } 92 | -------------------------------------------------------------------------------- /examples/ddk/makefile: -------------------------------------------------------------------------------- 1 | !INCLUDE $(NTMAKEENV)\makefile.def -------------------------------------------------------------------------------- /examples/ddk/sources: -------------------------------------------------------------------------------- 1 | TARGETNAME = distorm 2 | TARGETPATH = obj 3 | TARGETTYPE = DRIVER 4 | 5 | C_DEFINES = $(C_DEFINES) -DSUPPORT_64BIT_OFFSET -DLIBDISTORM 6 | 7 | INCLUDES = %BUILD%\inc;..\src; 8 | LIBS = %BUILD%\lib 9 | 10 | SOURCES = main.c 11 | -------------------------------------------------------------------------------- /examples/java/Makefile: -------------------------------------------------------------------------------- 1 | UNAME_S := $(shell uname -s) 2 | 3 | ifeq ($(UNAME_S),Darwin) 4 | 5 | JAVA_HOME=$(shell /usr/libexec/java_home) 6 | 7 | all: libjdistorm.dylib 8 | libjdistorm.dylib: jdistorm.c jdistorm.h 9 | gcc -dynamiclib -o libjdistorm.dylib jdistorm.c -I ${JAVA_HOME}/include/ -I ${JAVA_HOME}/include/darwin/ -ldistorm3 10 | 11 | endif 12 | 13 | ifeq ($(UNAME_S),Linux) 14 | 15 | all: libjdistorm.so 16 | jdistorm.o: jdistorm.c jdistorm.h 17 | gcc -c jdistorm.c -fPIC -I ${JAVA_HOME}/include -I ${JAVA_HOME}/include/linux 18 | 19 | libjdistorm.so: jdistorm.o 20 | gcc -shared -o libjdistorm.so -L${JAVA_HOME}/jre/lib -ldistorm3 jdistorm.o 21 | 22 | endif 23 | 24 | -------------------------------------------------------------------------------- /examples/java/distorm/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /examples/java/distorm/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | distorm 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/java/distorm/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | #Sun Oct 31 17:27:29 IST 2010 2 | eclipse.preferences.version=1 3 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 6 | org.eclipse.jdt.core.compiler.compliance=1.6 7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 11 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 12 | org.eclipse.jdt.core.compiler.source=1.6 13 | -------------------------------------------------------------------------------- /examples/java/distorm/src/Main.java: -------------------------------------------------------------------------------- 1 | import java.nio.ByteBuffer; 2 | 3 | import diStorm3.distorm3.*; 4 | import diStorm3.CodeInfo; 5 | import diStorm3.DecodedInst; 6 | import diStorm3.OpcodeEnum; 7 | import diStorm3.distorm3; 8 | import diStorm3.DecodedResult; 9 | import diStorm3.DecomposedResult; 10 | import diStorm3.DecomposedInst; 11 | 12 | public class Main { 13 | 14 | public static void main(String[] args) { 15 | byte[] buf = new byte[4]; 16 | buf[0] = (byte)0xc3; 17 | buf[1] = (byte)0x33; 18 | buf[2] = (byte)0xc0; 19 | buf[3] = (byte)0xc3; 20 | CodeInfo ci = new CodeInfo((long)0x1000, buf, DecodeType.Decode32Bits, 0); 21 | DecodedResult dr = new DecodedResult(10); 22 | distorm3.Decode(ci, dr); 23 | 24 | for (DecodedInst x : dr.mInstructions) { 25 | String s = String.format("%x %s %s", x.getOffset(), x.getMnemonic(), x.getOperands()); 26 | System.out.println(s); 27 | } 28 | 29 | DecomposedResult dr2 = new DecomposedResult(10); 30 | distorm3.Decompose(ci, dr2); 31 | 32 | for (DecomposedInst y: dr2.mInstructions) { 33 | if (y.getOpcode() != OpcodeEnum.RET) { 34 | DecodedInst x = distorm3.Format(ci, y); 35 | String s = String.format("%x %s %s", x.getOffset(), x.getMnemonic(), x.getOperands()); 36 | System.out.println(s); 37 | } 38 | } 39 | 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /examples/java/distorm/src/diStorm3/CodeInfo.java: -------------------------------------------------------------------------------- 1 | package diStorm3; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | public class CodeInfo { 6 | public CodeInfo(long codeOffset, ByteBuffer code, distorm3.DecodeType dt, int features) { 7 | mCodeOffset = codeOffset; 8 | mCode = code; 9 | mDecodeType = dt.ordinal(); 10 | mFeatures = features; 11 | mAddrMask = 0; 12 | } 13 | 14 | public CodeInfo(long codeOffset, byte[] rawCode, distorm3.DecodeType dt, int features) { 15 | mCode = ByteBuffer.allocateDirect(rawCode.length); 16 | mCode.put(rawCode); 17 | 18 | mCodeOffset = codeOffset; 19 | mDecodeType = dt.ordinal(); 20 | mFeatures = features; 21 | mAddrMask = 0; 22 | } 23 | 24 | private long mAddrMask; 25 | private long mCodeOffset; 26 | private long mNextOffset; 27 | private ByteBuffer mCode; 28 | private int mDecodeType; 29 | private int mFeatures; 30 | } -------------------------------------------------------------------------------- /examples/java/distorm/src/diStorm3/DecodedInst.java: -------------------------------------------------------------------------------- 1 | package diStorm3; 2 | 3 | public class DecodedInst { 4 | DecodedInst() 5 | { 6 | } 7 | private String mMnemonic; 8 | private String mOperands; 9 | private String mHex; 10 | private int mSize; 11 | private long mOffset; 12 | 13 | public String getMnemonic() { 14 | return mMnemonic; 15 | } 16 | 17 | public String getOperands() { 18 | return mOperands; 19 | } 20 | 21 | public String getHex() { 22 | return mHex; 23 | } 24 | 25 | public int getSize() { 26 | return mSize; 27 | } 28 | 29 | public long getOffset() { 30 | return mOffset; 31 | } 32 | } -------------------------------------------------------------------------------- /examples/java/distorm/src/diStorm3/DecodedResult.java: -------------------------------------------------------------------------------- 1 | package diStorm3; 2 | 3 | public class DecodedResult { 4 | public DecodedResult(int maxInstructions) { 5 | mMaxInstructions = maxInstructions; 6 | mInstructions = null; 7 | } 8 | 9 | public DecodedInst[] mInstructions; 10 | private int mMaxInstructions; 11 | } -------------------------------------------------------------------------------- /examples/java/distorm/src/diStorm3/DecomposedInst.java: -------------------------------------------------------------------------------- 1 | package diStorm3; 2 | 3 | import diStorm3.Operand; 4 | import diStorm3.Opcodes; 5 | 6 | public class DecomposedInst { 7 | private class ImmVariant { 8 | private long mValue; 9 | private int mSize; 10 | 11 | public long getImm() { 12 | return mValue; 13 | } 14 | 15 | public int getSize() { 16 | return mSize; 17 | } 18 | } 19 | 20 | private class DispVariant { 21 | 22 | private long mDisplacement; 23 | private int mSize; 24 | 25 | public long getDisplacement() { 26 | return mDisplacement; 27 | } 28 | 29 | public int getSize() { 30 | return mSize; 31 | } 32 | } 33 | 34 | private long mAddr; 35 | private int mSize; 36 | private int mFlags; 37 | private int mSegment; 38 | private int mBase, mScale; 39 | private int mOpcode; 40 | public Operand[] mOperands; 41 | public DispVariant mDisp; 42 | public ImmVariant mImm; 43 | private int mUnusedPrefixesMask; 44 | private int mMeta; 45 | private int mRegistersMask; 46 | private int mModifiedFlagsMask; 47 | private int mTestedFlagsMask; 48 | private int mUndefinedFlagsMask; 49 | 50 | public long getAddress() { 51 | return mAddr; 52 | } 53 | public int getSize() { 54 | return mSize; 55 | } 56 | public OpcodeEnum getOpcode() { 57 | return Opcodes.lookup(mOpcode); 58 | } 59 | public int getSegment() { 60 | return mSegment & 0x7f; 61 | } 62 | public boolean isSegmentDefault() { 63 | return (mSegment & 0x80) == 0x80; 64 | } 65 | public int getBase() { 66 | return mBase; 67 | } 68 | public int getScale() { 69 | return mScale; 70 | } 71 | public int getUnusedPrefixesMask() { 72 | return mUnusedPrefixesMask; 73 | } 74 | public int getMeta() { 75 | return mMeta; 76 | } 77 | public int getRegistersMask() { 78 | return mRegistersMask; 79 | } 80 | public int getModifiedFlagsMask() { 81 | return mModifiedFlagsMask; 82 | } 83 | public int getTestedFlagsMask() { 84 | return mTestedFlagsMask; 85 | } 86 | public int getUndefinedFlagsMask() { 87 | return mUndefinedFlagsMask; 88 | } 89 | } -------------------------------------------------------------------------------- /examples/java/distorm/src/diStorm3/DecomposedResult.java: -------------------------------------------------------------------------------- 1 | package diStorm3; 2 | 3 | public class DecomposedResult { 4 | public DecomposedResult(int maxInstructions) { 5 | mMaxInstructions = maxInstructions; 6 | mInstructions = null; 7 | } 8 | 9 | public DecomposedInst[] mInstructions; 10 | private int mMaxInstructions; 11 | } -------------------------------------------------------------------------------- /examples/java/distorm/src/diStorm3/OpcodeEnum.java: -------------------------------------------------------------------------------- 1 | package diStorm3; 2 | 3 | public enum OpcodeEnum { 4 | UNDEFINED, ADD, PUSH, POP, OR, ADC, SBB, AND, DAA, SUB, DAS, XOR, AAA, CMP, 5 | AAS, INC, DEC, PUSHA, POPA, BOUND, ARPL, IMUL, INS, OUTS, JO, JNO, JB, JAE, 6 | JZ, JNZ, JBE, JA, JS, JNS, JP, JNP, JL, JGE, JLE, JG, TEST, XCHG, MOV, LEA, 7 | CBW, CWDE, CDQE, CWD, CDQ, CQO, CALL_FAR, PUSHF, POPF, SAHF, LAHF, MOVS, CMPS, 8 | STOS, LODS, SCAS, RET, LES, LDS, ENTER, LEAVE, RETF, INT3, INT, INTO, IRET, 9 | AAM, AAD, SALC, XLAT, LOOPNZ, LOOPZ, LOOP, JCXZ, JECXZ, JRCXZ, IN, OUT, CALL, 10 | JMP, JMP_FAR, INT1, HLT, CMC, CLC, STC, CLI, STI, CLD, STD, LAR, LSL, SYSCALL, 11 | CLTS, SYSRET, INVD, WBINVD, UD2, FEMMS, NOP, WRMSR, RDTSC, RDMSR, RDPMC, SYSENTER, 12 | SYSEXIT, GETSEC, CMOVO, CMOVNO, CMOVB, CMOVAE, CMOVZ, CMOVNZ, CMOVBE, CMOVA, 13 | CMOVS, CMOVNS, CMOVP, CMOVNP, CMOVL, CMOVGE, CMOVLE, CMOVG, SETO, SETNO, SETB, 14 | SETAE, SETZ, SETNZ, SETBE, SETA, SETS, SETNS, SETP, SETNP, SETL, SETGE, SETLE, 15 | SETG, CPUID, BT, SHLD, RSM, BTS, SHRD, CMPXCHG, LSS, BTR, LFS, LGS, MOVZX, 16 | BTC, MOVSX, XADD, MOVNTI, BSWAP, ROL, ROR, RCL, RCR, SHL, SHR, SAL, SAR, XABORT, 17 | XBEGIN, FADD, FMUL, FCOM, FCOMP, FSUB, FSUBR, FDIV, FDIVR, FLD, FST, FSTP, 18 | FLDENV, FLDCW, FXCH, FNOP, FCHS, FABS, FTST, FXAM, FLD1, FLDL2T, FLDL2E, FLDPI, 19 | FLDLG2, FLDLN2, FLDZ, F2XM1, FYL2X, FPTAN, FPATAN, FXTRACT, FPREM1, FDECSTP, 20 | FINCSTP, FPREM, FYL2XP1, FSQRT, FSINCOS, FRNDINT, FSCALE, FSIN, FCOS, FIADD, 21 | FIMUL, FICOM, FICOMP, FISUB, FISUBR, FIDIV, FIDIVR, FCMOVB, FCMOVE, FCMOVBE, 22 | FCMOVU, FUCOMPP, FILD, FISTTP, FIST, FISTP, FCMOVNB, FCMOVNE, FCMOVNBE, FCMOVNU, 23 | FENI, FEDISI, FSETPM, FUCOMI, FCOMI, FRSTOR, FFREE, FUCOM, FUCOMP, FADDP, 24 | FMULP, FCOMPP, FSUBRP, FSUBP, FDIVRP, FDIVP, FBLD, FBSTP, FUCOMIP, FCOMIP, 25 | NOT, NEG, MUL, DIV, IDIV, SLDT, STR, LLDT, LTR, VERR, VERW, SGDT, SIDT, LGDT, 26 | LIDT, SMSW, LMSW, INVLPG, VMCALL, VMLAUNCH, VMRESUME, VMXOFF, MONITOR, MWAIT, 27 | CLAC, STAC, XGETBV, XSETBV, VMFUNC, XEND, VMRUN, VMMCALL, VMLOAD, VMSAVE, 28 | STGI, CLGI, SKINIT, INVLPGA, SWAPGS, RDTSCP, PREFETCH, PREFETCHW, PI2FW, PI2FD, 29 | PF2IW, PF2ID, PFNACC, PFPNACC, PFCMPGE, PFMIN, PFRCP, PFRSQRT, PFSUB, PFADD, 30 | PFCMPGT, PFMAX, PFRCPIT1, PFRSQIT1, PFSUBR, PFACC, PFCMPEQ, PFMUL, PFRCPIT2, 31 | PMULHRW, PSWAPD, PAVGUSB, MOVUPS, MOVUPD, MOVSS, MOVSD, VMOVUPS, VMOVUPD, 32 | VMOVSS, VMOVSD, MOVHLPS, MOVLPS, MOVLPD, MOVSLDUP, MOVDDUP, VMOVHLPS, VMOVLPS, 33 | VMOVLPD, VMOVSLDUP, VMOVDDUP, UNPCKLPS, UNPCKLPD, VUNPCKLPS, VUNPCKLPD, UNPCKHPS, 34 | UNPCKHPD, VUNPCKHPS, VUNPCKHPD, MOVLHPS, MOVHPS, MOVHPD, MOVSHDUP, VMOVLHPS, 35 | VMOVHPS, VMOVHPD, VMOVSHDUP, PREFETCHNTA, PREFETCHT0, PREFETCHT1, PREFETCHT2, 36 | MOVAPS, MOVAPD, VMOVAPS, VMOVAPD, CVTPI2PS, CVTPI2PD, CVTSI2SS, CVTSI2SD, 37 | VCVTSI2SS, VCVTSI2SD, MOVNTPS, MOVNTPD, MOVNTSS, MOVNTSD, VMOVNTPS, VMOVNTPD, 38 | CVTTPS2PI, CVTTPD2PI, CVTTSS2SI, CVTTSD2SI, VCVTTSS2SI, VCVTTSD2SI, CVTPS2PI, 39 | CVTPD2PI, CVTSS2SI, CVTSD2SI, VCVTSS2SI, VCVTSD2SI, UCOMISS, UCOMISD, VUCOMISS, 40 | VUCOMISD, COMISS, COMISD, VCOMISS, VCOMISD, MOVMSKPS, MOVMSKPD, VMOVMSKPS, 41 | VMOVMSKPD, SQRTPS, SQRTPD, SQRTSS, SQRTSD, VSQRTPS, VSQRTPD, VSQRTSS, VSQRTSD, 42 | RSQRTPS, RSQRTSS, VRSQRTPS, VRSQRTSS, RCPPS, RCPSS, VRCPPS, VRCPSS, ANDPS, 43 | ANDPD, VANDPS, VANDPD, ANDNPS, ANDNPD, VANDNPS, VANDNPD, ORPS, ORPD, VORPS, 44 | VORPD, XORPS, XORPD, VXORPS, VXORPD, ADDPS, ADDPD, ADDSS, ADDSD, VADDPS, VADDPD, 45 | VADDSS, VADDSD, MULPS, MULPD, MULSS, MULSD, VMULPS, VMULPD, VMULSS, VMULSD, 46 | CVTPS2PD, CVTPD2PS, CVTSS2SD, CVTSD2SS, VCVTPS2PD, VCVTPD2PS, VCVTSS2SD, VCVTSD2SS, 47 | CVTDQ2PS, CVTPS2DQ, CVTTPS2DQ, VCVTDQ2PS, VCVTPS2DQ, VCVTTPS2DQ, SUBPS, SUBPD, 48 | SUBSS, SUBSD, VSUBPS, VSUBPD, VSUBSS, VSUBSD, MINPS, MINPD, MINSS, MINSD, 49 | VMINPS, VMINPD, VMINSS, VMINSD, DIVPS, DIVPD, DIVSS, DIVSD, VDIVPS, VDIVPD, 50 | VDIVSS, VDIVSD, MAXPS, MAXPD, MAXSS, MAXSD, VMAXPS, VMAXPD, VMAXSS, VMAXSD, 51 | PUNPCKLBW, VPUNPCKLBW, PUNPCKLWD, VPUNPCKLWD, PUNPCKLDQ, VPUNPCKLDQ, PACKSSWB, 52 | VPACKSSWB, PCMPGTB, VPCMPGTB, PCMPGTW, VPCMPGTW, PCMPGTD, VPCMPGTD, PACKUSWB, 53 | VPACKUSWB, PUNPCKHBW, VPUNPCKHBW, PUNPCKHWD, VPUNPCKHWD, PUNPCKHDQ, VPUNPCKHDQ, 54 | PACKSSDW, VPACKSSDW, PUNPCKLQDQ, VPUNPCKLQDQ, PUNPCKHQDQ, VPUNPCKHQDQ, MOVD, 55 | MOVQ, VMOVD, VMOVQ, MOVDQA, MOVDQU, VMOVDQA, VMOVDQU, PSHUFW, PSHUFD, PSHUFHW, 56 | PSHUFLW, VPSHUFD, VPSHUFHW, VPSHUFLW, PCMPEQB, VPCMPEQB, PCMPEQW, VPCMPEQW, 57 | PCMPEQD, VPCMPEQD, EMMS, VZEROUPPER, VZEROALL, VMREAD, EXTRQ, INSERTQ, VMWRITE, 58 | CVTPH2PS, CVTPS2PH, HADDPD, HADDPS, VHADDPD, VHADDPS, HSUBPD, HSUBPS, VHSUBPD, 59 | VHSUBPS, XSAVE, XSAVE64, LFENCE, XRSTOR, XRSTOR64, MFENCE, XSAVEOPT, XSAVEOPT64, 60 | SFENCE, CLFLUSH, POPCNT, BSF, TZCNT, BSR, LZCNT, CMPEQPS, CMPLTPS, CMPLEPS, 61 | CMPUNORDPS, CMPNEQPS, CMPNLTPS, CMPNLEPS, CMPORDPS, CMPEQPD, CMPLTPD, CMPLEPD, 62 | CMPUNORDPD, CMPNEQPD, CMPNLTPD, CMPNLEPD, CMPORDPD, CMPEQSS, CMPLTSS, CMPLESS, 63 | CMPUNORDSS, CMPNEQSS, CMPNLTSS, CMPNLESS, CMPORDSS, CMPEQSD, CMPLTSD, CMPLESD, 64 | CMPUNORDSD, CMPNEQSD, CMPNLTSD, CMPNLESD, CMPORDSD, VCMPEQPS, VCMPLTPS, VCMPLEPS, 65 | VCMPUNORDPS, VCMPNEQPS, VCMPNLTPS, VCMPNLEPS, VCMPORDPS, VCMPEQ_UQPS, VCMPNGEPS, 66 | VCMPNGTPS, VCMPFALSEPS, VCMPNEQ_OQPS, VCMPGEPS, VCMPGTPS, VCMPTRUEPS, VCMPEQ_OSPS, 67 | VCMPLT_OQPS, VCMPLE_OQPS, VCMPUNORD_SPS, VCMPNEQ_USPS, VCMPNLT_UQPS, VCMPNLE_UQPS, 68 | VCMPORD_SPS, VCMPEQ_USPS, VCMPNGE_UQPS, VCMPNGT_UQPS, VCMPFALSE_OSPS, VCMPNEQ_OSPS, 69 | VCMPGE_OQPS, VCMPGT_OQPS, VCMPTRUE_USPS, VCMPEQPD, VCMPLTPD, VCMPLEPD, VCMPUNORDPD, 70 | VCMPNEQPD, VCMPNLTPD, VCMPNLEPD, VCMPORDPD, VCMPEQ_UQPD, VCMPNGEPD, VCMPNGTPD, 71 | VCMPFALSEPD, VCMPNEQ_OQPD, VCMPGEPD, VCMPGTPD, VCMPTRUEPD, VCMPEQ_OSPD, VCMPLT_OQPD, 72 | VCMPLE_OQPD, VCMPUNORD_SPD, VCMPNEQ_USPD, VCMPNLT_UQPD, VCMPNLE_UQPD, VCMPORD_SPD, 73 | VCMPEQ_USPD, VCMPNGE_UQPD, VCMPNGT_UQPD, VCMPFALSE_OSPD, VCMPNEQ_OSPD, VCMPGE_OQPD, 74 | VCMPGT_OQPD, VCMPTRUE_USPD, VCMPEQSS, VCMPLTSS, VCMPLESS, VCMPUNORDSS, VCMPNEQSS, 75 | VCMPNLTSS, VCMPNLESS, VCMPORDSS, VCMPEQ_UQSS, VCMPNGESS, VCMPNGTSS, VCMPFALSESS, 76 | VCMPNEQ_OQSS, VCMPGESS, VCMPGTSS, VCMPTRUESS, VCMPEQ_OSSS, VCMPLT_OQSS, VCMPLE_OQSS, 77 | VCMPUNORD_SSS, VCMPNEQ_USSS, VCMPNLT_UQSS, VCMPNLE_UQSS, VCMPORD_SSS, VCMPEQ_USSS, 78 | VCMPNGE_UQSS, VCMPNGT_UQSS, VCMPFALSE_OSSS, VCMPNEQ_OSSS, VCMPGE_OQSS, VCMPGT_OQSS, 79 | VCMPTRUE_USSS, VCMPEQSD, VCMPLTSD, VCMPLESD, VCMPUNORDSD, VCMPNEQSD, VCMPNLTSD, 80 | VCMPNLESD, VCMPORDSD, VCMPEQ_UQSD, VCMPNGESD, VCMPNGTSD, VCMPFALSESD, VCMPNEQ_OQSD, 81 | VCMPGESD, VCMPGTSD, VCMPTRUESD, VCMPEQ_OSSD, VCMPLT_OQSD, VCMPLE_OQSD, VCMPUNORD_SSD, 82 | VCMPNEQ_USSD, VCMPNLT_UQSD, VCMPNLE_UQSD, VCMPORD_SSD, VCMPEQ_USSD, VCMPNGE_UQSD, 83 | VCMPNGT_UQSD, VCMPFALSE_OSSD, VCMPNEQ_OSSD, VCMPGE_OQSD, VCMPGT_OQSD, VCMPTRUE_USSD, 84 | PINSRW, VPINSRW, PEXTRW, VPEXTRW, SHUFPS, SHUFPD, VSHUFPS, VSHUFPD, CMPXCHG8B, 85 | CMPXCHG16B, VMPTRST, ADDSUBPD, ADDSUBPS, VADDSUBPD, VADDSUBPS, PSRLW, VPSRLW, 86 | PSRLD, VPSRLD, PSRLQ, VPSRLQ, PADDQ, VPADDQ, PMULLW, VPMULLW, MOVQ2DQ, MOVDQ2Q, 87 | PMOVMSKB, VPMOVMSKB, PSUBUSB, VPSUBUSB, PSUBUSW, VPSUBUSW, PMINUB, VPMINUB, 88 | PAND, VPAND, PADDUSB, VPADDUSW, PADDUSW, PMAXUB, VPMAXUB, PANDN, VPANDN, PAVGB, 89 | VPAVGB, PSRAW, VPSRAW, PSRAD, VPSRAD, PAVGW, VPAVGW, PMULHUW, VPMULHUW, PMULHW, 90 | VPMULHW, CVTTPD2DQ, CVTDQ2PD, CVTPD2DQ, VCVTTPD2DQ, VCVTDQ2PD, VCVTPD2DQ, 91 | MOVNTQ, MOVNTDQ, VMOVNTDQ, PSUBSB, VPSUBSB, PSUBSW, VPSUBSW, PMINSW, VPMINSW, 92 | POR, VPOR, PADDSB, VPADDSB, PADDSW, VPADDSW, PMAXSW, VPMAXSW, PXOR, VPXOR, 93 | LDDQU, VLDDQU, PSLLW, VPSLLW, PSLLD, VPSLLD, PSLLQ, VPSLLQ, PMULUDQ, VPMULUDQ, 94 | PMADDWD, VPMADDWD, PSADBW, VPSADBW, MASKMOVQ, MASKMOVDQU, VMASKMOVDQU, PSUBB, 95 | VPSUBB, PSUBW, VPSUBW, PSUBD, VPSUBD, PSUBQ, VPSUBQ, PADDB, VPADDB, PADDW, 96 | VPADDW, PADDD, VPADDD, FNSTENV, FSTENV, FNSTCW, FSTCW, FNCLEX, FCLEX, FNINIT, 97 | FINIT, FNSAVE, FSAVE, FNSTSW, FSTSW, PSHUFB, VPSHUFB, PHADDW, VPHADDW, PHADDD, 98 | VPHADDD, PHADDSW, VPHADDSW, PMADDUBSW, VPMADDUBSW, PHSUBW, VPHSUBW, PHSUBD, 99 | VPHSUBD, PHSUBSW, VPHSUBSW, PSIGNB, VPSIGNB, PSIGNW, VPSIGNW, PSIGND, VPSIGND, 100 | PMULHRSW, VPMULHRSW, VPERMILPS, VPERMILPD, VTESTPS, VTESTPD, PBLENDVB, BLENDVPS, 101 | BLENDVPD, PTEST, VPTEST, VBROADCASTSS, VBROADCASTSD, VBROADCASTF128, PABSB, 102 | VPABSB, PABSW, VPABSW, PABSD, VPABSD, PMOVSXBW, VPMOVSXBW, PMOVSXBD, VPMOVSXBD, 103 | PMOVSXBQ, VPMOVSXBQ, PMOVSXWD, VPMOVSXWD, PMOVSXWQ, VPMOVSXWQ, PMOVSXDQ, VPMOVSXDQ, 104 | PMULDQ, VPMULDQ, PCMPEQQ, VPCMPEQQ, MOVNTDQA, VMOVNTDQA, PACKUSDW, VPACKUSDW, 105 | VMASKMOVPS, VMASKMOVPD, PMOVZXBW, VPMOVZXBW, PMOVZXBD, VPMOVZXBD, PMOVZXBQ, 106 | VPMOVZXBQ, PMOVZXWD, VPMOVZXWD, PMOVZXWQ, VPMOVZXWQ, PMOVZXDQ, VPMOVZXDQ, 107 | PCMPGTQ, VPCMPGTQ, PMINSB, VPMINSB, PMINSD, VPMINSD, PMINUW, VPMINUW, PMINUD, 108 | VPMINUD, PMAXSB, VPMAXSB, PMAXSD, VPMAXSD, PMAXUW, VPMAXUW, PMAXUD, VPMAXUD, 109 | PMULLD, VPMULLD, PHMINPOSUW, VPHMINPOSUW, INVEPT, INVVPID, INVPCID, VFMADDSUB132PS, 110 | VFMADDSUB132PD, VFMSUBADD132PS, VFMSUBADD132PD, VFMADD132PS, VFMADD132PD, 111 | VFMADD132SS, VFMADD132SD, VFMSUB132PS, VFMSUB132PD, VFMSUB132SS, VFMSUB132SD, 112 | VFNMADD132PS, VFNMADD132PD, VFNMADD132SS, VFNMADD132SD, VFNMSUB132PS, VFNMSUB132PD, 113 | VFNMSUB132SS, VFNMSUB132SD, VFMADDSUB213PS, VFMADDSUB213PD, VFMSUBADD213PS, 114 | VFMSUBADD213PD, VFMADD213PS, VFMADD213PD, VFMADD213SS, VFMADD213SD, VFMSUB213PS, 115 | VFMSUB213PD, VFMSUB213SS, VFMSUB213SD, VFNMADD213PS, VFNMADD213PD, VFNMADD213SS, 116 | VFNMADD213SD, VFNMSUB213PS, VFNMSUB213PD, VFNMSUB213SS, VFNMSUB213SD, VFMADDSUB231PS, 117 | VFMADDSUB231PD, VFMSUBADD231PS, VFMSUBADD231PD, VFMADD231PS, VFMADD231PD, 118 | VFMADD231SS, VFMADD231SD, VFMSUB231PS, VFMSUB231PD, VFMSUB231SS, VFMSUB231SD, 119 | VFNMADD231PS, VFNMADD231PD, VFNMADD231SS, VFNMADD231SD, VFNMSUB231PS, VFNMSUB231PD, 120 | VFNMSUB231SS, VFNMSUB231SD, AESIMC, VAESIMC, AESENC, VAESENC, AESENCLAST, 121 | VAESENCLAST, AESDEC, VAESDEC, AESDECLAST, VAESDECLAST, MOVBE, CRC32, VPERM2F128, 122 | ROUNDPS, VROUNDPS, ROUNDPD, VROUNDPD, ROUNDSS, VROUNDSS, ROUNDSD, VROUNDSD, 123 | BLENDPS, VBLENDPS, BLENDPD, VBLENDPD, PBLENDW, VPBLENDW, PALIGNR, VPALIGNR, 124 | PEXTRB, VPEXTRB, PEXTRD, PEXTRQ, VPEXTRD, VPEXTRQ, EXTRACTPS, VEXTRACTPS, 125 | VINSERTF128, VEXTRACTF128, PINSRB, VPINSRB, INSERTPS, VINSERTPS, PINSRD, PINSRQ, 126 | VPINSRD, VPINSRQ, DPPS, VDPPS, DPPD, VDPPD, MPSADBW, VMPSADBW, PCLMULQDQ, 127 | VPCLMULQDQ, VBLENDVPS, VBLENDVPD, VPBLENDVB, PCMPESTRM, VPCMPESTRM, PCMPESTRI, 128 | VPCMPESTRI, PCMPISTRM, VPCMPISTRM, PCMPISTRI, VPCMPISTRI, AESKEYGENASSIST, 129 | VAESKEYGENASSIST, PSRLDQ, VPSRLDQ, PSLLDQ, VPSLLDQ, FXSAVE, FXSAVE64, RDFSBASE, 130 | FXRSTOR, FXRSTOR64, RDGSBASE, LDMXCSR, WRFSBASE, VLDMXCSR, STMXCSR, WRGSBASE, 131 | VSTMXCSR, VMPTRLD, VMCLEAR, VMXON, MOVSXD, PAUSE, WAIT, RDRAND, _3DNOW 132 | } -------------------------------------------------------------------------------- /examples/java/distorm/src/diStorm3/Operand.java: -------------------------------------------------------------------------------- 1 | package diStorm3; 2 | 3 | public class Operand { 4 | 5 | public enum OperandType { 6 | None, Reg, Imm, Imm1, Imm2, Disp, Smem, Mem, Pc, Ptr 7 | } 8 | 9 | private int mType; 10 | private int mIndex; 11 | private int mSize; 12 | 13 | public OperandType getType() { 14 | return OperandType.values()[mType]; 15 | } 16 | 17 | public int getIndex() { 18 | return mIndex; 19 | } 20 | 21 | public int getSize() { 22 | return mSize; 23 | } 24 | } -------------------------------------------------------------------------------- /examples/java/distorm/src/diStorm3/distorm3.java: -------------------------------------------------------------------------------- 1 | /* 2 | * diStorm3 JNI 3 | * Gil Dabah, Sep 2010 4 | * 5 | */ 6 | package diStorm3; 7 | import diStorm3.CodeInfo; 8 | import diStorm3.DecodedResult; 9 | import diStorm3.DecomposedResult; 10 | import diStorm3.Opcodes; 11 | 12 | public class distorm3 { 13 | 14 | public enum DecodeType { 15 | Decode16Bits, Decode32Bits, Decode64Bits 16 | } 17 | 18 | public static native void Decompose(CodeInfo ci, DecomposedResult dr); 19 | public static native void Decode(CodeInfo ci, DecodedResult dr); 20 | public static native DecodedInst Format(CodeInfo ci, DecomposedInst di); 21 | 22 | public enum Registers { 23 | RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15, 24 | EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, R8D, R9D, R10D, R11D, R12D, R13D, R14D, R15D, 25 | AX, CX, DX, BX, SP, BP, SI, DI, R8W, R9W, R10W, R11W, R12W, R13W, R14W, R15W, 26 | AL, CL, DL, BL, AH, CH, DH, BH, R8B, R9B, R10B, R11B, R12B, R13B, R14B, R15B, 27 | SPL, BPL, SIL, DIL, 28 | ES, CS, SS, DS, FS, GS, 29 | RIP, 30 | ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7, 31 | MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, 32 | XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, 33 | YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, YMM8, YMM9, YMM10, YMM11, YMM12, YMM13, YMM14, YMM15, 34 | CR0, UNUSED0, CR2, CR3, CR4, UNUSED1, UNUSED2, UNUSED3, CR8, 35 | DR0, DR1, DR2, DR3, UNUSED4, UNUSED5, DR6, DR7 36 | }; 37 | 38 | static { 39 | System.loadLibrary("jdistorm"); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /examples/java/jdistorm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * diStorm3 JNI wrapper. 3 | * Gil Dabah, October 2010. 4 | */ 5 | 6 | #include "jdistorm.h" 7 | #include "../../include/distorm.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #pragma comment(lib, "../../distorm.lib") 14 | 15 | static struct _CodeInfoIds { 16 | jclass jCls; 17 | jfieldID ID_CodeOffset; 18 | jfieldID ID_Code; 19 | jfieldID ID_DecodeType; 20 | jfieldID ID_Features; 21 | } g_CodeInfoIds; 22 | 23 | static struct _DecodedResultIds { 24 | jclass jCls; 25 | jfieldID ID_Instructions; 26 | jfieldID ID_MaxInstructions; 27 | } g_DecodedResultIds; 28 | 29 | static struct _DecodedInstIds { 30 | jclass jCls; 31 | jfieldID ID_Mnemonic; 32 | jfieldID ID_Operands; 33 | jfieldID ID_Hex; 34 | jfieldID ID_Size; 35 | jfieldID ID_Offset; 36 | } g_DecodedInstIds; 37 | 38 | static struct _DecomposedResultIds { 39 | jclass jCls; 40 | jfieldID ID_Instructions; 41 | jfieldID ID_MaxInstructions; 42 | } g_DecomposedResultIds; 43 | 44 | static struct _DecomposedInstIds { 45 | jclass jCls; 46 | jfieldID ID_Address; 47 | jfieldID ID_Size; 48 | jfieldID ID_Flags; 49 | jfieldID ID_Segment; 50 | jfieldID ID_Base; 51 | jfieldID ID_Scale; 52 | jfieldID ID_Opcode; 53 | jfieldID ID_Operands; 54 | jfieldID ID_Disp; 55 | jfieldID ID_Imm; 56 | jfieldID ID_UnusedPrefixesMask; 57 | jfieldID ID_Meta; 58 | jfieldID ID_RegistersMask; 59 | jfieldID ID_ModifiedFlagsMask; 60 | jfieldID ID_TestedFlagsMask; 61 | jfieldID ID_UndefinedFlagsMask; 62 | } g_DecomposedInstIds; 63 | 64 | static struct _OperandIds { 65 | jclass jCls; 66 | jfieldID ID_Type; 67 | jfieldID ID_Index; 68 | jfieldID ID_Size; 69 | } g_OperandIds; 70 | 71 | static struct _ImmIds { 72 | jclass jCls; 73 | jfieldID ID_Value; 74 | jfieldID ID_Size; 75 | } g_ImmIds; 76 | 77 | static struct _DispIds { 78 | jclass jCls; 79 | jfieldID ID_Displacement; 80 | jfieldID ID_Size; 81 | } g_DispIds; 82 | 83 | void JThrowByName(JNIEnv* env, const char *name, const char* msg) 84 | { 85 | jclass cls = (*env)->FindClass(env, name); 86 | if (cls != NULL) { 87 | (*env)->ThrowNew(env, cls, msg); 88 | } 89 | (*env)->DeleteLocalRef(env, cls); 90 | } 91 | 92 | _CodeInfo* AcquireCodeInfoStruct(JNIEnv *env, jobject jciObj) 93 | { 94 | jobject jCodeObj = NULL; 95 | _CodeInfo* ci = (_CodeInfo*)malloc(sizeof(_CodeInfo)); 96 | if (ci == NULL) { 97 | JThrowByName(env, "java/lang/OutOfMemoryError", NULL); 98 | return NULL; 99 | } 100 | memset(ci, 0, sizeof(_CodeInfo)); 101 | 102 | ci->codeOffset = (*env)->GetLongField(env, jciObj, g_CodeInfoIds.ID_CodeOffset); 103 | 104 | jCodeObj = (*env)->GetObjectField(env, jciObj, g_CodeInfoIds.ID_Code); 105 | ci->code = (uint8_t*) (*env)->GetDirectBufferAddress(env, jCodeObj); 106 | ci->codeLen = (int)(*env)->GetDirectBufferCapacity(env, jCodeObj); 107 | 108 | ci->dt = (*env)->GetIntField(env, jciObj, g_CodeInfoIds.ID_DecodeType); 109 | 110 | ci->features = (*env)->GetIntField(env, jciObj, g_CodeInfoIds.ID_Features); 111 | 112 | return ci; 113 | } 114 | 115 | jobject CreateDecodedInstObj(JNIEnv* env, const _DecodedInst* inst) 116 | { 117 | jobject jInst = (*env)->AllocObject(env, g_DecodedInstIds.jCls); 118 | if (jInst == NULL) return NULL; 119 | (*env)->SetObjectField(env, jInst, g_DecodedInstIds.ID_Mnemonic, (*env)->NewStringUTF(env, (const char*)inst->mnemonic.p)); 120 | (*env)->SetObjectField(env, jInst, g_DecodedInstIds.ID_Operands, (*env)->NewStringUTF(env, (const char*)inst->operands.p)); 121 | (*env)->SetObjectField(env, jInst, g_DecodedInstIds.ID_Hex, (*env)->NewStringUTF(env, (const char*)inst->instructionHex.p)); 122 | (*env)->SetIntField(env, jInst, g_DecodedInstIds.ID_Size, inst->size); 123 | (*env)->SetLongField(env, jInst, g_DecodedInstIds.ID_Offset, inst->offset); 124 | return jInst; 125 | } 126 | 127 | JNIEXPORT void JNICALL Java_diStorm3_distorm3_Decode 128 | (JNIEnv *env, jobject thiz, jobject jciObj, jobject jdrObj) 129 | { 130 | jarray jInsts = NULL; 131 | jobject jInst = NULL; 132 | _CodeInfo* ci = NULL; 133 | _DecodedInst* insts = NULL; 134 | jint maxInstructions = 0; 135 | unsigned int usedInstructionsCount = 0, i = 0; 136 | 137 | thiz; /* Unused. */ 138 | 139 | ci = AcquireCodeInfoStruct(env, jciObj); 140 | if (ci == NULL) { 141 | JThrowByName(env, "java/lang/OutOfMemoryError", NULL); 142 | return; 143 | } 144 | 145 | maxInstructions = (*env)->GetIntField(env, jdrObj, g_DecodedResultIds.ID_MaxInstructions); 146 | 147 | insts = (_DecodedInst*)malloc(maxInstructions * sizeof(_DecodedInst)); 148 | if (insts == NULL) goto Cleanup; 149 | 150 | distorm_decode(ci->codeOffset, ci->code, ci->codeLen, ci->dt, insts, maxInstructions, &usedInstructionsCount); 151 | 152 | jInsts = (*env)->NewObjectArray(env, usedInstructionsCount, g_DecodedInstIds.jCls, NULL); 153 | if (jInsts == NULL) goto Cleanup; 154 | 155 | for (i = 0; i < usedInstructionsCount; i++) { 156 | jInst = CreateDecodedInstObj(env, &insts[i]); 157 | if (jInst == NULL) goto Cleanup; 158 | (*env)->SetObjectArrayElement(env, jInsts, i, jInst); 159 | } 160 | 161 | (*env)->SetObjectField(env, jdrObj, g_DecodedResultIds.ID_Instructions, jInsts); 162 | 163 | Cleanup: 164 | /* In case of an error, jInsts will get cleaned automatically. */ 165 | if (ci != NULL) free(ci); 166 | if (insts != NULL) free(insts); 167 | } 168 | 169 | JNIEXPORT void JNICALL Java_diStorm3_distorm3_Decompose 170 | (JNIEnv *env, jobject thiz, jobject jciObj, jobject jdrObj) 171 | { 172 | jarray jInsts = NULL, jOperands = NULL; 173 | jobject jInst = NULL, jOperand = NULL, jImm = NULL, jDisp = NULL; 174 | _CodeInfo* ci = NULL; 175 | _DInst* insts = NULL; 176 | jint maxInstructions = 0; 177 | unsigned int usedInstructionsCount = 0, i = 0, j = 0, operandsNo = 0; 178 | int success = 0; 179 | 180 | thiz; /* Unused. */ 181 | 182 | ci = AcquireCodeInfoStruct(env, jciObj); 183 | if (ci == NULL) { 184 | JThrowByName(env, "java/lang/OutOfMemoryError", NULL); 185 | return; 186 | } 187 | 188 | maxInstructions = (*env)->GetIntField(env, jdrObj, g_DecomposedResultIds.ID_MaxInstructions); 189 | 190 | insts = (_DInst*)malloc(maxInstructions * sizeof(_DInst)); 191 | if (insts == NULL) goto Cleanup; 192 | 193 | distorm_decompose(ci, insts, maxInstructions, &usedInstructionsCount); 194 | 195 | jInsts = (*env)->NewObjectArray(env, usedInstructionsCount, g_DecomposedInstIds.jCls, NULL); 196 | if (jInsts == NULL) goto Cleanup; 197 | 198 | for (i = 0; i < usedInstructionsCount; i++) { 199 | jInst = (*env)->AllocObject(env, g_DecomposedInstIds.jCls); 200 | if (jInst == NULL) goto Cleanup; 201 | 202 | /* Simple fields: */ 203 | (*env)->SetLongField(env, jInst, g_DecomposedInstIds.ID_Address, insts[i].addr); 204 | (*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_Flags, insts[i].flags); 205 | (*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_Size, insts[i].size); 206 | (*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_Segment, insts[i].segment); 207 | (*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_Base, insts[i].base); 208 | (*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_Scale, insts[i].scale); 209 | (*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_Opcode, insts[i].opcode); 210 | (*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_UnusedPrefixesMask, insts[i].unusedPrefixesMask); 211 | (*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_Meta, insts[i].meta); 212 | (*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_RegistersMask, insts[i].usedRegistersMask); 213 | (*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_ModifiedFlagsMask, insts[i].modifiedFlagsMask); 214 | (*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_TestedFlagsMask, insts[i].testedFlagsMask); 215 | (*env)->SetIntField(env, jInst, g_DecomposedInstIds.ID_UndefinedFlagsMask, insts[i].undefinedFlagsMask); 216 | 217 | /* Immediate variant. */ 218 | jImm = (*env)->AllocObject(env, g_ImmIds.jCls); 219 | if (jImm == NULL) goto Cleanup; 220 | (*env)->SetLongField(env, jImm, g_ImmIds.ID_Value, insts[i].imm.qword); 221 | /* The size of the immediate is in one of the operands, if at all. Look for it below. Zero by default. */ 222 | (*env)->SetIntField(env, jImm, g_ImmIds.ID_Size, 0); 223 | 224 | /* Count operands. */ 225 | for (operandsNo = 0; operandsNo < OPERANDS_NO; operandsNo++) { 226 | if (insts[i].ops[operandsNo].type == O_NONE) break; 227 | } 228 | 229 | jOperands = (*env)->NewObjectArray(env, operandsNo, g_OperandIds.jCls, NULL); 230 | if (jOperands == NULL) goto Cleanup; 231 | 232 | for (j = 0; j < operandsNo; j++) { 233 | if (insts[i].ops[j].type == O_IMM) { 234 | /* Set the size of the immediate operand. */ 235 | (*env)->SetIntField(env, jImm, g_ImmIds.ID_Size, insts[i].ops[j].size); 236 | } 237 | 238 | jOperand = (*env)->AllocObject(env, g_OperandIds.jCls); 239 | if (jOperand == NULL) goto Cleanup; 240 | (*env)->SetIntField(env, jOperand, g_OperandIds.ID_Type, insts[i].ops[j].type); 241 | (*env)->SetIntField(env, jOperand, g_OperandIds.ID_Index, insts[i].ops[j].index); 242 | (*env)->SetIntField(env, jOperand, g_OperandIds.ID_Size, insts[i].ops[j].size); 243 | (*env)->SetObjectArrayElement(env, jOperands, j, jOperand); 244 | } 245 | (*env)->SetObjectField(env, jInst, g_DecomposedInstIds.ID_Operands, jOperands); 246 | 247 | /* Attach the immediate variant. */ 248 | (*env)->SetObjectField(env, jInst, g_DecomposedInstIds.ID_Imm, jImm); 249 | 250 | /* Displacement variant. */ 251 | jDisp = (*env)->AllocObject(env, g_DispIds.jCls); 252 | if (jDisp == NULL) goto Cleanup; 253 | (*env)->SetLongField(env, jDisp, g_DispIds.ID_Displacement, insts[i].disp); 254 | (*env)->SetIntField(env, jDisp, g_DispIds.ID_Size, insts[i].dispSize); 255 | (*env)->SetObjectField(env, jInst, g_DecomposedInstIds.ID_Disp, jDisp); 256 | 257 | (*env)->SetObjectArrayElement(env, jInsts, i, jInst); 258 | } 259 | 260 | (*env)->SetObjectField(env, jdrObj, g_DecodedResultIds.ID_Instructions, jInsts); 261 | 262 | Cleanup: 263 | /* In case of an error, jInsts will get cleaned automatically. */ 264 | if (ci != NULL) free(ci); 265 | if (insts != NULL) free(insts); 266 | } 267 | 268 | JNIEXPORT jobject JNICALL Java_diStorm3_distorm3_Format 269 | (JNIEnv *env, jobject thiz, jobject jciObj, jobject jdiObj) 270 | { 271 | _CodeInfo* ci = NULL; 272 | _DInst input = {0}; 273 | _DecodedInst output = {0}; 274 | jobject ret = NULL, jOperands = NULL, jOp = NULL, jTmp = NULL; 275 | jsize i, opsCount; 276 | 277 | thiz; /* Unused. */ 278 | 279 | ci = AcquireCodeInfoStruct(env, jciObj); 280 | if (ci == NULL) { 281 | JThrowByName(env, "java/lang/OutOfMemoryError", NULL); 282 | return NULL; 283 | } 284 | 285 | input.addr = (*env)->GetLongField(env, jdiObj, g_DecomposedInstIds.ID_Address); 286 | input.flags = (uint16_t) (*env)->GetIntField(env, jdiObj, g_DecomposedInstIds.ID_Flags); 287 | input.size = (uint8_t) (*env)->GetIntField(env, jdiObj, g_DecomposedInstIds.ID_Size); 288 | input.segment = (uint8_t) (*env)->GetIntField(env, jdiObj, g_DecomposedInstIds.ID_Segment); 289 | input.base = (uint8_t) (*env)->GetIntField(env, jdiObj, g_DecomposedInstIds.ID_Base); 290 | input.scale = (uint8_t) (*env)->GetIntField(env, jdiObj, g_DecomposedInstIds.ID_Scale); 291 | input.opcode = (uint16_t) (*env)->GetIntField(env, jdiObj, g_DecomposedInstIds.ID_Opcode); 292 | /* unusedPrefixesMask is unused indeed, lol. */ 293 | input.meta = (uint16_t) (*env)->GetIntField(env, jdiObj, g_DecomposedInstIds.ID_Meta); 294 | /* Nor usedRegistersMask. */ 295 | 296 | jOperands = (*env)->GetObjectField(env, jdiObj, g_DecomposedInstIds.ID_Operands); 297 | if (jOperands != NULL) { 298 | opsCount = (*env)->GetArrayLength(env, jOperands); 299 | for (i = 0; i < opsCount; i++) { 300 | jOp = (*env)->GetObjectArrayElement(env, jOperands, i); 301 | if (jOp != NULL) { 302 | input.ops[i].index = (uint8_t) (*env)->GetIntField(env, jOp, g_OperandIds.ID_Index); 303 | input.ops[i].type = (uint8_t) (*env)->GetIntField(env, jOp, g_OperandIds.ID_Type); 304 | input.ops[i].size = (uint16_t) (*env)->GetIntField(env, jOp, g_OperandIds.ID_Size); 305 | } 306 | } 307 | } 308 | 309 | jTmp = (*env)->GetObjectField(env, jdiObj, g_DecomposedInstIds.ID_Imm); 310 | if (jTmp != NULL) { 311 | input.imm.qword = (uint64_t) (*env)->GetLongField(env, jTmp, g_ImmIds.ID_Value); 312 | } 313 | 314 | jTmp = (*env)->GetObjectField(env, jdiObj, g_DecomposedInstIds.ID_Disp); 315 | if (jTmp != NULL) { 316 | input.disp = (uint64_t) (*env)->GetLongField(env, jTmp, g_DispIds.ID_Displacement); 317 | input.dispSize = (uint8_t) (*env)->GetIntField(env, jTmp, g_DispIds.ID_Size); 318 | } 319 | 320 | distorm_format(ci, &input, &output); 321 | 322 | ret = CreateDecodedInstObj(env, &output); 323 | 324 | if (ci != NULL) free(ci); 325 | return ret; 326 | } 327 | 328 | /* Cache all ID's and classes! Release in unload. */ 329 | jint JNI_OnLoad(JavaVM *vm, void *reserved) 330 | { 331 | jclass jCls = NULL; 332 | JNIEnv* env = NULL; 333 | 334 | if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) { 335 | return JNI_VERSION_1_6; 336 | } 337 | 338 | jCls = (*env)->FindClass(env, PACKAGE_PREFIX "CodeInfo"); 339 | g_CodeInfoIds.jCls = (*env)->NewWeakGlobalRef(env, jCls); 340 | g_CodeInfoIds.ID_CodeOffset = (*env)->GetFieldID(env, jCls, "mCodeOffset", "J"); 341 | g_CodeInfoIds.ID_Code = (*env)->GetFieldID(env, jCls, "mCode", "Ljava/nio/ByteBuffer;"); 342 | g_CodeInfoIds.ID_DecodeType = (*env)->GetFieldID(env, jCls, "mDecodeType", "I"); 343 | g_CodeInfoIds.ID_Features = (*env)->GetFieldID(env, jCls, "mFeatures", "I"); 344 | 345 | jCls = (*env)->FindClass(env, PACKAGE_PREFIX "DecodedResult"); 346 | g_DecodedResultIds.jCls = (*env)->NewWeakGlobalRef(env, jCls); 347 | g_DecodedResultIds.ID_MaxInstructions = (*env)->GetFieldID(env, jCls, "mMaxInstructions", "I"); 348 | g_DecodedResultIds.ID_Instructions = (*env)->GetFieldID(env, jCls, "mInstructions", "[L" PACKAGE_PREFIX "DecodedInst;"); 349 | 350 | jCls = (*env)->FindClass(env, PACKAGE_PREFIX "DecodedInst"); 351 | g_DecodedInstIds.jCls = (*env)->NewWeakGlobalRef(env, jCls); 352 | g_DecodedInstIds.ID_Mnemonic = (*env)->GetFieldID(env, jCls, "mMnemonic", "Ljava/lang/String;"); 353 | g_DecodedInstIds.ID_Operands = (*env)->GetFieldID(env, jCls, "mOperands", "Ljava/lang/String;"); 354 | g_DecodedInstIds.ID_Hex = (*env)->GetFieldID(env, jCls, "mHex", "Ljava/lang/String;"); 355 | g_DecodedInstIds.ID_Size = (*env)->GetFieldID(env, jCls, "mSize", "I"); 356 | g_DecodedInstIds.ID_Offset = (*env)->GetFieldID(env, jCls, "mOffset", "J"); 357 | 358 | jCls = (*env)->FindClass(env, PACKAGE_PREFIX "DecomposedResult"); 359 | g_DecomposedResultIds.jCls = (*env)->NewWeakGlobalRef(env, jCls); 360 | g_DecomposedResultIds.ID_Instructions = (*env)->GetFieldID(env, jCls, "mInstructions", "[L" PACKAGE_PREFIX "DecomposedInst;"); 361 | g_DecomposedResultIds.ID_MaxInstructions = (*env)->GetFieldID(env, jCls, "mMaxInstructions", "I"); 362 | 363 | jCls = (*env)->FindClass(env, PACKAGE_PREFIX "DecomposedInst"); 364 | g_DecomposedInstIds.jCls = (*env)->NewWeakGlobalRef(env, jCls); 365 | g_DecomposedInstIds.ID_Address = (*env)->GetFieldID(env, jCls, "mAddr", "J"); 366 | g_DecomposedInstIds.ID_Size = (*env)->GetFieldID(env, jCls, "mSize", "I"); 367 | g_DecomposedInstIds.ID_Flags = (*env)->GetFieldID(env, jCls, "mFlags", "I"); 368 | g_DecomposedInstIds.ID_Segment = (*env)->GetFieldID(env, jCls, "mSegment", "I"); 369 | g_DecomposedInstIds.ID_Base = (*env)->GetFieldID(env, jCls, "mBase", "I"); 370 | g_DecomposedInstIds.ID_Scale = (*env)->GetFieldID(env, jCls, "mScale", "I"); 371 | g_DecomposedInstIds.ID_Opcode = (*env)->GetFieldID(env, jCls, "mOpcode", "I"); 372 | g_DecomposedInstIds.ID_Operands = (*env)->GetFieldID(env, jCls, "mOperands", "[L" PACKAGE_PREFIX "Operand;"); 373 | g_DecomposedInstIds.ID_Disp = (*env)->GetFieldID(env, jCls, "mDisp", "L" PACKAGE_PREFIX "DecomposedInst$DispVariant;"); 374 | g_DecomposedInstIds.ID_Imm = (*env)->GetFieldID(env, jCls, "mImm", "L" PACKAGE_PREFIX "DecomposedInst$ImmVariant;"); 375 | g_DecomposedInstIds.ID_UnusedPrefixesMask = (*env)->GetFieldID(env, jCls, "mUnusedPrefixesMask", "I"); 376 | g_DecomposedInstIds.ID_Meta = (*env)->GetFieldID(env, jCls, "mMeta", "I"); 377 | g_DecomposedInstIds.ID_RegistersMask = (*env)->GetFieldID(env, jCls, "mRegistersMask", "I"); 378 | g_DecomposedInstIds.ID_ModifiedFlagsMask = (*env)->GetFieldID(env, jCls, "mModifiedFlagsMask", "I"); 379 | g_DecomposedInstIds.ID_TestedFlagsMask = (*env)->GetFieldID(env, jCls, "mTestedFlagsMask", "I"); 380 | g_DecomposedInstIds.ID_UndefinedFlagsMask = (*env)->GetFieldID(env, jCls, "mUndefinedFlagsMask", "I"); 381 | 382 | jCls = (*env)->FindClass(env, PACKAGE_PREFIX "Operand"); 383 | g_OperandIds.jCls = (*env)->NewWeakGlobalRef(env, jCls); 384 | g_OperandIds.ID_Type = (*env)->GetFieldID(env, jCls, "mType", "I"); 385 | g_OperandIds.ID_Index = (*env)->GetFieldID(env, jCls, "mIndex", "I"); 386 | g_OperandIds.ID_Size = (*env)->GetFieldID(env, jCls, "mSize", "I"); 387 | 388 | jCls = (*env)->FindClass(env, PACKAGE_PREFIX "DecomposedInst$ImmVariant"); 389 | g_ImmIds.jCls = (*env)->NewWeakGlobalRef(env, jCls); 390 | g_ImmIds.ID_Value = (*env)->GetFieldID(env, jCls, "mValue", "J"); 391 | g_ImmIds.ID_Size = (*env)->GetFieldID(env, jCls, "mSize", "I"); 392 | 393 | jCls = (*env)->FindClass(env, PACKAGE_PREFIX "DecomposedInst$DispVariant"); 394 | g_DispIds.jCls = (*env)->NewWeakGlobalRef(env, jCls); 395 | g_DispIds.ID_Displacement = (*env)->GetFieldID(env, jCls, "mDisplacement", "J"); 396 | g_DispIds.ID_Size = (*env)->GetFieldID(env, jCls, "mSize", "I"); 397 | 398 | return JNI_VERSION_1_6; 399 | } 400 | 401 | 402 | JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) 403 | { 404 | /* Free global weak refs. */ 405 | } 406 | -------------------------------------------------------------------------------- /examples/java/jdistorm.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class Distorm3 */ 4 | 5 | #ifndef _Included_Distorm3 6 | #define _Included_Distorm3 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #define PACKAGE_PREFIX "diStorm3/" 12 | 13 | /* 14 | * Class: com_reviverstudio_core_disasms_distorm3_Distorm3 15 | * Method: Decompose 16 | * Signature: (LdiStorm3/CodeInfo;LdiStorm3/DecomposedResult;)V 17 | */ 18 | JNIEXPORT void JNICALL Java_diStorm3_distorm3_Decompose 19 | (JNIEnv *, jclass, jobject, jobject); 20 | 21 | /* 22 | * Class: com_reviverstudio_core_disasms_distorm3_Distorm3 23 | * Method: Decode 24 | * Signature: (LdiStorm3/CodeInfo;LdiStorm3/DecodedResult;)V 25 | */ 26 | JNIEXPORT void JNICALL Java_diStorm3_distorm3_Decode 27 | (JNIEnv *, jclass, jobject, jobject); 28 | 29 | /* 30 | * Class: com_reviverstudio_core_disasms_distorm3_Distorm3 31 | * Method: Format 32 | * Signature: (LdiStorm3/CodeInfo;LdiStorm3/DecomposedInst;)LdiStorm3/DecodedInst; 33 | */ 34 | JNIEXPORT jobject JNICALL Java_diStorm3_distorm3_Format 35 | (JNIEnv *, jclass, jobject, jobject); 36 | 37 | #ifdef __cplusplus 38 | } 39 | #endif 40 | #endif 41 | -------------------------------------------------------------------------------- /examples/java/jdistorm.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jdistorm", "jdistorm.vcproj", "{AB6B51F5-79C6-44CA-9D0B-7CB2A009A9AB}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|x64 = Debug|x64 9 | Release|x64 = Release|x64 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {AB6B51F5-79C6-44CA-9D0B-7CB2A009A9AB}.Debug|x64.ActiveCfg = Debug|x64 13 | {AB6B51F5-79C6-44CA-9D0B-7CB2A009A9AB}.Debug|x64.Build.0 = Debug|x64 14 | {AB6B51F5-79C6-44CA-9D0B-7CB2A009A9AB}.Release|x64.ActiveCfg = Release|x64 15 | {AB6B51F5-79C6-44CA-9D0B-7CB2A009A9AB}.Release|x64.Build.0 = Release|x64 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /examples/java/jdistorm.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | 26 | 29 | 32 | 35 | 38 | 42 | 55 | 58 | 61 | 64 | 73 | 76 | 79 | 82 | 85 | 88 | 91 | 94 | 95 | 103 | 106 | 109 | 112 | 115 | 119 | 131 | 134 | 137 | 140 | 153 | 156 | 159 | 162 | 165 | 168 | 171 | 174 | 175 | 176 | 177 | 178 | 179 | 184 | 187 | 188 | 189 | 194 | 197 | 198 | 199 | 204 | 205 | 206 | 207 | 208 | 209 | -------------------------------------------------------------------------------- /examples/linux/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # diStorm (Linux Port) / Demo Application Makefile 3 | # 4 | 5 | TARGET = disasm 6 | CC = gcc 7 | CFLAGS = -Wall -O2 -o 8 | 9 | all: disasm 10 | 11 | disasm: 12 | ${CC} ${CFLAGS} ${TARGET} main.c ../../distorm3.a 13 | 14 | clean: 15 | /bin/rm -rf *.o ${TARGET} 16 | -------------------------------------------------------------------------------- /examples/linux/main.c: -------------------------------------------------------------------------------- 1 | // diStorm64 library sample 2 | // http://ragestorm.net/distorm/ 3 | // Arkon, Stefan, 2005 4 | // Mikhail, 2006 5 | // JvW, 2007 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | // For the compilers who don't have sysexits.h, which is not an ISO/ANSI include! 15 | #define EX_OK 0 16 | #define EX_USAGE 64 17 | #define EX_DATAERR 65 18 | #define EX_NOINPUT 66 19 | #define EX_NOUSER 67 20 | #define EX_NOHOST 68 21 | #define EX_UNAVAILABLE 69 22 | #define EX_SOFTWARE 70 23 | #define EX_OSERR 71 24 | #define EX_OSFILE 72 25 | #define EX_CANTCREAT 73 26 | #define EX_IOERR 74 27 | #define EX_TEMPFAIL 75 28 | #define EX_PROTOCOL 76 29 | #define EX_NOPERM 77 30 | #define EX_CONFIG 78 31 | 32 | #include "../../include/distorm.h" 33 | 34 | // The number of the array of instructions the decoder function will use to return the disassembled instructions. 35 | // Play with this value for performance... 36 | #define MAX_INSTRUCTIONS (1000) 37 | 38 | int main(int argc, char **argv) 39 | { 40 | // Version of used compiled library. 41 | unsigned int dver = 0; 42 | // Holds the result of the decoding. 43 | _DecodeResult res; 44 | // Decoded instruction information. 45 | _DecodedInst decodedInstructions[MAX_INSTRUCTIONS]; 46 | // next is used for instruction's offset synchronization. 47 | // decodedInstructionsCount holds the count of filled instructions' array by the decoder. 48 | unsigned int decodedInstructionsCount = 0, i, next; 49 | 50 | // Default decoding mode is 32 bits, could be set by command line. 51 | _DecodeType dt = Decode32Bits; 52 | 53 | // Default offset for buffer is 0, could be set in command line. 54 | _OffsetType offset = 0; 55 | char* errch = NULL; 56 | 57 | // Index to file name in argv. 58 | int param = 1; 59 | 60 | // Handling file. 61 | FILE* f; 62 | unsigned long filesize = 0, bytesread = 0; 63 | struct stat st; 64 | 65 | // Buffer to disassemble. 66 | unsigned char *buf, *buf2; 67 | 68 | // Disassembler version. 69 | dver = distorm_version(); 70 | printf("diStorm version: %u.%u.%u\n", (dver >> 16), ((dver) >> 8) & 0xff, dver & 0xff); 71 | 72 | // Check params. 73 | if (argc < 2 || argc > 4) { 74 | printf("Usage: ./disasm [-b16] [-b64] filename [memory offset]\r\nRaw disassembler output.\r\nMemory offset is origin of binary file in memory (address in hex).\r\nDefault decoding mode is -b32.\r\nexample: disasm -b16 demo.com 789a\r\n"); 75 | return EX_USAGE; 76 | } 77 | 78 | if (strncmp(argv[param], "-b16", 4) == 0) { 79 | dt = Decode16Bits; 80 | param++; 81 | } else if (strncmp(argv[param], "-b64", 4) == 0) { 82 | dt = Decode64Bits; 83 | param++; 84 | } else if (*argv[param] == '-') { 85 | fputs("Decoding mode size isn't specified!\n", stderr); 86 | return EX_USAGE; 87 | } else if (argc == 4) { 88 | fputs("Too many parameters are set.\n", stderr); 89 | return EX_USAGE; 90 | } 91 | if (param >= argc) { 92 | fputs("Filename is missing.\n", stderr); 93 | return EX_USAGE; 94 | } 95 | if (param + 1 == argc-1) { // extra param? 96 | #ifdef SUPPORT_64BIT_OFFSET 97 | offset = strtoull(argv[param + 1], &errch, 16); 98 | #else 99 | offset = strtoul(argv[param + 1], &errch, 16); 100 | #endif 101 | if (*errch != '\0') { 102 | fprintf(stderr, "Offset `%s' couldn't be converted.\n", argv[param + 1]); 103 | return EX_USAGE; 104 | } 105 | } 106 | 107 | f = fopen(argv[param], "rb"); 108 | if (f == NULL) { 109 | perror(argv[param]); 110 | return EX_NOINPUT; 111 | } 112 | 113 | if (fstat(fileno(f), &st) != 0) { 114 | perror("fstat"); 115 | fclose(f); 116 | return EX_NOINPUT; 117 | } 118 | filesize = st.st_size; 119 | 120 | // We read the whole file into memory in order to make life easier, 121 | // otherwise we would have to synchronize the code buffer as well (so instructions won't be split). 122 | buf2 = buf = malloc(filesize); 123 | if (buf == NULL) { 124 | perror("File too large."); 125 | fclose(f); 126 | return EX_UNAVAILABLE; 127 | } 128 | bytesread = fread(buf, 1, filesize, f); 129 | if (bytesread != filesize) { 130 | perror("Can't read file into memory."); 131 | free(buf); 132 | fclose(f); 133 | return EX_IOERR; 134 | } 135 | 136 | fclose(f); 137 | 138 | printf("bits: %d\nfilename: %s\norigin: ", dt == Decode16Bits ? 16 : dt == Decode32Bits ? 32 : 64, argv[param]); 139 | #ifdef SUPPORT_64BIT_OFFSET 140 | if (dt != Decode64Bits) printf("%08llx\n", offset); 141 | else printf("%016llx\n", offset); 142 | #else 143 | printf("%08x\n", offset); 144 | #endif 145 | 146 | // Decode the buffer at given offset (virtual address). 147 | while (1) { 148 | // If you get an undefined reference linker error for the following line, 149 | // change the SUPPORT_64BIT_OFFSET in distorm.h. 150 | res = distorm_decode(offset, (const unsigned char*)buf, filesize, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount); 151 | if (res == DECRES_INPUTERR) { 152 | // Null buffer? Decode type not 16/32/64? 153 | fputs("Input error, halting!\n", stderr); 154 | free(buf2); 155 | return EX_SOFTWARE; 156 | } 157 | 158 | for (i = 0; i < decodedInstructionsCount; i++) 159 | #ifdef SUPPORT_64BIT_OFFSET 160 | printf("%0*llx (%02d) %-24s %s%s%s\r\n", dt != Decode64Bits ? 8 : 16, decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p); 161 | #else 162 | printf("%08x (%02d) %-24s %s%s%s\r\n", decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p); 163 | #endif 164 | 165 | if (res == DECRES_SUCCESS) break; // All instructions were decoded. 166 | else if (decodedInstructionsCount == 0) break; 167 | 168 | // Synchronize: 169 | next = (unsigned int)(decodedInstructions[decodedInstructionsCount-1].offset - offset); 170 | next += decodedInstructions[decodedInstructionsCount-1].size; 171 | // Advance ptr and recalc offset. 172 | buf += next; 173 | filesize -= next; 174 | offset += next; 175 | } 176 | 177 | // Release buffer 178 | free(buf2); 179 | 180 | return EX_OK; 181 | } 182 | -------------------------------------------------------------------------------- /examples/tests/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # diStorm (Linux Port) / Demo Application Makefile 3 | # 4 | 5 | TARGET = disasm 6 | CC = gcc 7 | CFLAGS = -Wall -O2 -I. -o 8 | 9 | all: disasm 10 | 11 | disasm: 12 | ${CC} ${CFLAGS} ${TARGET} main.cpp ../distorm64.a 13 | 14 | clean: 15 | /bin/rm -rf *.o ${TARGET} 16 | -------------------------------------------------------------------------------- /examples/tests/main.cpp: -------------------------------------------------------------------------------- 1 | // diStorm64 library sample 2 | // http://ragestorm.net/distorm/ 3 | // Arkon, Stefan, 2005 4 | 5 | 6 | #include 7 | #include 8 | 9 | #pragma comment(lib, "../../distorm.lib") 10 | 11 | #include "../../include/distorm.h" 12 | 13 | // The number of the array of instructions the decoder function will use to return the disassembled instructions. 14 | // Play with this value for performance... 15 | #define MAX_INSTRUCTIONS (1000) 16 | 17 | int main(int argc, char **argv) 18 | { 19 | _DecodeResult res; 20 | _DInst decodedInstructions[1000]; 21 | _DecodedInst di; 22 | unsigned int decodedInstructionsCount = 0, i = 0; 23 | _OffsetType offset = 0; 24 | unsigned int dver = distorm_version(); 25 | printf("diStorm version: %d.%d.%d\n", (dver >> 16), ((dver) >> 8) & 0xff, dver & 0xff); 26 | 27 | unsigned char rawData[] = { 28 | 0x0f, 0x01, 0xcb 29 | }; 30 | 31 | _CodeInfo ci = { 0 }; 32 | ci.codeLen = sizeof(rawData); 33 | ci.code = rawData; 34 | ci.dt = Decode32Bits; 35 | ci.features = 0; 36 | distorm_decompose(&ci, decodedInstructions, 1000, &decodedInstructionsCount); 37 | //distorm_decode(0, rawData, sizeof(rawData), Decode32Bits, &di, 1, &decodedInstructionsCount); 38 | for (int i = 0; i < decodedInstructionsCount; i++) { 39 | distorm_format(&ci, &decodedInstructions[i], &di); 40 | printf("%08I64x (%02d) %-24s %s%s%s\r\n", di.offset, di.size, (char*)di.instructionHex.p, (char*)di.mnemonic.p, di.operands.length != 0 ? " " : "", (char*)di.operands.p); 41 | } 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /examples/tests/tests.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tests", "tests.vcxproj", "{C35D3921-227A-432A-BB5D-90ECEBAB08B2}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Release|Win32 = Release|Win32 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {C35D3921-227A-432A-BB5D-90ECEBAB08B2}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {C35D3921-227A-432A-BB5D-90ECEBAB08B2}.Debug|Win32.Build.0 = Debug|Win32 18 | {C35D3921-227A-432A-BB5D-90ECEBAB08B2}.Debug|x64.ActiveCfg = Debug|x64 19 | {C35D3921-227A-432A-BB5D-90ECEBAB08B2}.Debug|x64.Build.0 = Debug|x64 20 | {C35D3921-227A-432A-BB5D-90ECEBAB08B2}.Release|Win32.ActiveCfg = Release|Win32 21 | {C35D3921-227A-432A-BB5D-90ECEBAB08B2}.Release|Win32.Build.0 = Release|Win32 22 | {C35D3921-227A-432A-BB5D-90ECEBAB08B2}.Release|x64.ActiveCfg = Release|x64 23 | {C35D3921-227A-432A-BB5D-90ECEBAB08B2}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {051C92F2-5C59-49A6-B43C-C701C2816520} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /examples/tests/tests.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {C35D3921-227A-432A-BB5D-90ECEBAB08B2} 23 | Win32Proj 24 | tests 25 | 10.0 26 | 27 | 28 | 29 | Application 30 | true 31 | Unicode 32 | v142 33 | 34 | 35 | Application 36 | true 37 | Unicode 38 | v142 39 | 40 | 41 | Application 42 | false 43 | true 44 | Unicode 45 | v142 46 | 47 | 48 | Application 49 | false 50 | true 51 | Unicode 52 | v142 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | true 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | false 81 | 82 | 83 | 84 | 85 | 86 | Level3 87 | Disabled 88 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 89 | 90 | 91 | Console 92 | true 93 | 94 | 95 | 96 | 97 | 98 | 99 | Level3 100 | Disabled 101 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 102 | 103 | 104 | Console 105 | true 106 | 107 | 108 | 109 | 110 | Level3 111 | 112 | 113 | MaxSpeed 114 | true 115 | true 116 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 117 | 118 | 119 | Console 120 | true 121 | true 122 | true 123 | 124 | 125 | 126 | 127 | Level3 128 | 129 | 130 | MaxSpeed 131 | true 132 | true 133 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 134 | 135 | 136 | Console 137 | true 138 | true 139 | true 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /examples/tests/tests.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /examples/win32/disasm.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 11.00 2 | # Visual Studio 2010 3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "disasm", "disasm.vcxproj", "{91227BA8-F7EB-43CC-8C4A-A4944C00567B}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Win32 = Debug|Win32 8 | Debug|x64 = Debug|x64 9 | Release|Win32 = Release|Win32 10 | Release|x64 = Release|x64 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {91227BA8-F7EB-43CC-8C4A-A4944C00567B}.Debug|Win32.ActiveCfg = Debug|Win32 14 | {91227BA8-F7EB-43CC-8C4A-A4944C00567B}.Debug|Win32.Build.0 = Debug|Win32 15 | {91227BA8-F7EB-43CC-8C4A-A4944C00567B}.Debug|x64.ActiveCfg = Debug|x64 16 | {91227BA8-F7EB-43CC-8C4A-A4944C00567B}.Debug|x64.Build.0 = Debug|x64 17 | {91227BA8-F7EB-43CC-8C4A-A4944C00567B}.Release|Win32.ActiveCfg = Release|Win32 18 | {91227BA8-F7EB-43CC-8C4A-A4944C00567B}.Release|Win32.Build.0 = Release|Win32 19 | {91227BA8-F7EB-43CC-8C4A-A4944C00567B}.Release|x64.ActiveCfg = Release|x64 20 | {91227BA8-F7EB-43CC-8C4A-A4944C00567B}.Release|x64.Build.0 = Release|x64 21 | EndGlobalSection 22 | GlobalSection(SolutionProperties) = preSolution 23 | HideSolutionNode = FALSE 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /examples/win32/disasm.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {91227BA8-F7EB-43CC-8C4A-A4944C00567B} 23 | disasm 24 | Win32Proj 25 | 26 | 27 | 28 | Application 29 | MultiByte 30 | v142 31 | 32 | 33 | Application 34 | MultiByte 35 | v142 36 | 37 | 38 | Application 39 | MultiByte 40 | v142 41 | 42 | 43 | Application 44 | MultiByte 45 | v142 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | <_ProjectFileVersion>10.0.30319.1 69 | Debug\ 70 | Debug\ 71 | true 72 | $(Platform)\$(Configuration)\ 73 | $(Platform)\$(Configuration)\ 74 | true 75 | Release\ 76 | Release\ 77 | false 78 | $(Platform)\$(Configuration)\ 79 | $(Platform)\$(Configuration)\ 80 | false 81 | AllRules.ruleset 82 | 83 | 84 | AllRules.ruleset 85 | 86 | 87 | AllRules.ruleset 88 | 89 | 90 | AllRules.ruleset 91 | 92 | 93 | 94 | 95 | 96 | Disabled 97 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 98 | true 99 | 100 | 101 | EnableFastChecks 102 | MultiThreadedDebug 103 | 104 | 105 | Level3 106 | EditAndContinue 107 | CompileAsCpp 108 | 109 | 110 | $(OutDir)disasm.exe 111 | true 112 | $(OutDir)disasm.pdb 113 | Console 114 | false 115 | 116 | 117 | MachineX86 118 | 119 | 120 | 121 | 122 | X64 123 | 124 | 125 | Disabled 126 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 127 | true 128 | 129 | 130 | EnableFastChecks 131 | MultiThreadedDebug 132 | 133 | 134 | Level3 135 | ProgramDatabase 136 | CompileAsCpp 137 | 138 | 139 | $(OutDir)disasm.exe 140 | true 141 | $(OutDir)disasm.pdb 142 | Console 143 | false 144 | 145 | 146 | MachineX64 147 | 148 | 149 | 150 | 151 | Full 152 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 153 | MultiThreaded 154 | 155 | 156 | Level3 157 | ProgramDatabase 158 | CompileAsCpp 159 | 160 | 161 | $(OutDir)disasm.exe 162 | true 163 | Console 164 | true 165 | true 166 | false 167 | 168 | 169 | MachineX86 170 | 171 | 172 | 173 | 174 | X64 175 | 176 | 177 | Full 178 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 179 | MultiThreaded 180 | 181 | 182 | Level3 183 | 184 | 185 | CompileAsCpp 186 | 187 | 188 | $(OutDir)disasm.exe 189 | true 190 | Console 191 | true 192 | true 193 | false 194 | 195 | 196 | MachineX64 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /examples/win32/disasm.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | 10 | 11 | Source Files 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/win32/main.cpp: -------------------------------------------------------------------------------- 1 | // diStorm64 library sample 2 | // http://ragestorm.net/distorm/ 3 | // Arkon, Stefan, 2005 4 | 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "../../include/distorm.h" 12 | 13 | // Link the library into our project. 14 | #pragma comment(lib, "../../distorm.lib") 15 | 16 | // The number of the array of instructions the decoder function will use to return the disassembled instructions. 17 | // Play with this value for performance... 18 | #define MAX_INSTRUCTIONS (1000) 19 | 20 | int main(int argc, char **argv) 21 | { 22 | // Version of used compiled library. 23 | unsigned long dver = 0; 24 | // Holds the result of the decoding. 25 | _DecodeResult res; 26 | // Decoded instruction information. 27 | _DecodedInst decodedInstructions[MAX_INSTRUCTIONS]; 28 | // next is used for instruction's offset synchronization. 29 | // decodedInstructionsCount holds the count of filled instructions' array by the decoder. 30 | unsigned int decodedInstructionsCount = 0, i, next; 31 | 32 | // Default decoding mode is 32 bits, could be set by command line. 33 | _DecodeType dt = Decode32Bits; 34 | 35 | // Default offset for buffer is 0, could be set in command line. 36 | _OffsetType offset = 0; 37 | char* errch = NULL; 38 | 39 | // Index to file name in argv. 40 | int param = 1; 41 | 42 | // Handling file. 43 | HANDLE file; 44 | DWORD filesize, bytesread; 45 | 46 | // Buffer to disassemble. 47 | unsigned char *buf, *buf2; 48 | 49 | // Disassembler version. 50 | dver = distorm_version(); 51 | printf("diStorm version: %d.%d.%d\n", (dver >> 16), ((dver) >> 8) & 0xff, dver & 0xff); 52 | 53 | // Check params. 54 | if (argc < 2 || argc > 4) { 55 | printf("Usage: disasm.exe [-b16] [-b64] filename [memory offset]\r\nRaw disassembler output.\r\nMemory offset is origin of binary file in memory (address in hex).\r\nDefault decoding mode is -b32.\r\nexample: disasm -b16 demo.com 789a\r\n"); 56 | return -1; 57 | } 58 | 59 | if (strncmp(argv[param], "-b16", 4) == 0) { 60 | dt = Decode16Bits; 61 | param++; 62 | } else if (strncmp(argv[param], "-b64", 4) == 0) { 63 | dt = Decode64Bits; 64 | param++; 65 | } else if (*argv[param] == '-') { 66 | printf("Decoding mode size isn't specified!"); 67 | return -1; 68 | } else if (argc == 4) { 69 | printf("Too many parameters are set."); 70 | return -1; 71 | } 72 | if (param >= argc) { 73 | printf("Filename is missing."); 74 | return -1; 75 | } 76 | if (param + 1 == argc-1) { // extra param? 77 | #ifdef SUPPORT_64BIT_OFFSET 78 | offset = _strtoui64(argv[param + 1], &errch, 16); 79 | #else 80 | offset = strtoul(argv[param + 1], &errch, 16); 81 | #endif 82 | if (*errch != '\0') { 83 | printf("Offset couldn't be converted."); 84 | return -1; 85 | } 86 | } 87 | 88 | file = CreateFile(argv[param], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 89 | if (file == INVALID_HANDLE_VALUE) { 90 | printf("Could not open file %s (error %d)\n", argv[param], GetLastError()); 91 | return -2; 92 | } 93 | 94 | if ((filesize = GetFileSize(file, NULL)) < 0) { 95 | printf("Error getting filesize (error %d)\n", GetLastError()); 96 | CloseHandle(file); 97 | return -3; 98 | } 99 | 100 | // We read the whole file into memory in order to make life easier, 101 | // otherwise we would have to synchronize the code buffer as well (so instructions won't be split). 102 | buf2 = buf = (unsigned char*)malloc(filesize); 103 | if (!ReadFile(file, buf, filesize, &bytesread, NULL)) { 104 | printf("Error reading file (error %d)\n", GetLastError()); 105 | CloseHandle(file); 106 | free(buf); 107 | return -3; 108 | } 109 | 110 | if (filesize != bytesread) { 111 | printf("Internal read-error in system\n"); 112 | CloseHandle(file); 113 | free(buf); 114 | return -3; 115 | } 116 | 117 | CloseHandle(file); 118 | 119 | printf("bits: %d\nfilename: %s\norigin: ", dt == Decode16Bits ? 16 : dt == Decode32Bits ? 32 : 64, argv[param]); 120 | #ifdef SUPPORT_64BIT_OFFSET 121 | if (dt != Decode64Bits) printf("%08I64x\n", offset); 122 | else printf("%016I64x\n", offset); 123 | #else 124 | printf("%08x\n", offset); 125 | #endif 126 | 127 | // Decode the buffer at given offset (virtual address). 128 | while (1) { 129 | // If you get an unresolved external symbol linker error for the following line, 130 | // change the SUPPORT_64BIT_OFFSET in distorm.h. 131 | res = distorm_decode(offset, (const unsigned char*)buf, filesize, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount); 132 | if (res == DECRES_INPUTERR) { 133 | // Null buffer? Decode type not 16/32/64? 134 | printf("Input error, halting!"); 135 | free(buf2); 136 | return -4; 137 | } 138 | 139 | for (i = 0; i < decodedInstructionsCount; i++) { 140 | #ifdef SUPPORT_64BIT_OFFSET 141 | printf("%0*I64x (%02d) %-24s %s%s%s\n", dt != Decode64Bits ? 8 : 16, decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p); 142 | #else 143 | printf("%08x (%02d) %-24s %s%s%s\n", decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p); 144 | #endif 145 | } 146 | 147 | if (res == DECRES_SUCCESS) break; // All instructions were decoded. 148 | else if (decodedInstructionsCount == 0) break; 149 | 150 | // Synchronize: 151 | next = (unsigned long)(decodedInstructions[decodedInstructionsCount-1].offset - offset); 152 | next += decodedInstructions[decodedInstructionsCount-1].size; 153 | // Advance ptr and recalc offset. 154 | buf += next; 155 | filesize -= next; 156 | offset += next; 157 | } 158 | 159 | // Release buffer 160 | free(buf2); 161 | 162 | return 0; 163 | } 164 | -------------------------------------------------------------------------------- /make/linux/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # diStorm3 (Linux Port) 3 | # 4 | 5 | TARGET_BASE = libdistorm3.so 6 | COBJS = ../../src/mnemonics.o ../../src/textdefs.o ../../src/prefix.o ../../src/operands.o ../../src/insts.o ../../src/instructions.o ../../src/distorm.o ../../src/decoder.o 7 | CC = gcc 8 | CFLAGS += -fPIC -O2 -Wall -DSUPPORT_64BIT_OFFSET -DDISTORM_STATIC -std=c99 9 | LDFLAGS += -shared 10 | PREFIX = /usr/local 11 | # The lib SONAME version: 12 | LIB_S_VERSION = 3 13 | # The lib real version: 14 | LIB_R_VERSION = 3.4.0 15 | LDFLAGS += -Wl,-soname,${TARGET_BASE}.${LIB_S_VERSION} 16 | DESTDIR = 17 | TARGET_NAME = ${TARGET_BASE}.${LIB_R_VERSION} 18 | 19 | all: clib 20 | 21 | clean: 22 | /bin/rm -rf ../../src/*.o ${TARGET_NAME} ../../distorm3.a ./../*.o 23 | 24 | clib: ${COBJS} 25 | ${CC} ${CFLAGS} ${VERSION} ${COBJS} ${LDFLAGS} -o ${TARGET_NAME} 26 | ar rs ../../distorm3.a ${COBJS} 27 | 28 | install: ${TARGET_NAME} 29 | install -D -s ${TARGET_NAME} ${DESTDIR}${PREFIX}/lib/${TARGET_NAME} 30 | ln -sf ${DESTDIR}${PREFIX}/lib/${TARGET_NAME} ${DESTDIR}${PREFIX}/lib/${TARGET_BASE} 31 | @echo "... running ldconfig might be smart ..." 32 | 33 | .c.o: 34 | ${CC} ${CFLAGS} ${VERSION} -c $< -o $@ 35 | 36 | -------------------------------------------------------------------------------- /make/mac/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # diStorm3 (Mac Port) 3 | # 4 | 5 | DISTORM_MODE ?= DISTORM_DYNAMIC 6 | TARGET = libdistorm3.dylib 7 | PYTHON_BUILD_DIR = ../../Python/macosx-x86 8 | COBJS = ../../src/mnemonics.o ../../src/textdefs.o ../../src/prefix.o ../../src/operands.o ../../src/insts.o ../../src/instructions.o ../../src/distorm.o ../../src/decoder.o 9 | CC = gcc 10 | CFLAGS = -arch x86_64 -O2 -Wall -fPIC -DSUPPORT_64BIT_OFFSET -D${DISTORM_MODE} 11 | ifeq ($(DISTORM_FAT), 1) 12 | CFLAGS += -arch i386 13 | endif 14 | 15 | all: clib 16 | 17 | clean: 18 | /bin/rm -rf ../../src/*.o ${TARGET} ../../libdistorm3.dylib ../../distorm3.a ../../*.a 19 | 20 | clib: ${COBJS} 21 | ifeq '$(DISTORM_MODE)' 'DISTORM_DYNAMIC' 22 | ${CC} ${CFLAGS} ${VERSION} ${COBJS} -fPIC -dynamiclib -o ${TARGET} 23 | [ -d ${PYTHON_BUILD_DIR} ] && rm -rf ${PYTHON_BUILD_DIR} || true 24 | mkdir ${PYTHON_BUILD_DIR} 25 | cp ${TARGET} ${PYTHON_BUILD_DIR}/ 26 | else 27 | ar rs ../../distorm3.a ${COBJS} 28 | endif 29 | 30 | .c.o: 31 | ${CC} ${CFLAGS} ${VERSION} -c $< -o $@ 32 | -------------------------------------------------------------------------------- /make/tinycc/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # diStorm3 (Linux Port) 3 | # 4 | 5 | TARGET_BASE = libdistorm3.so 6 | COBJS = ../../src/mnemonics.o ../../src/textdefs.o ../../src/prefix.o ../../src/operands.o ../../src/insts.o ../../src/instructions.o ../../src/distorm.o ../../src/decoder.o 7 | CC = tcc 8 | CFLAGS += -fPIC -Wall -DSUPPORT_64BIT_OFFSET -DDISTORM_STATIC -std=c99 9 | LDFLAGS += -shared 10 | PREFIX = /usr/local 11 | # The lib SONAME version: 12 | LIB_S_VERSION = 3 13 | # The lib real version: 14 | LIB_R_VERSION = 3.4.0 15 | LDFLAGS += -Wl,-soname,${TARGET_BASE}.${LIB_S_VERSION} 16 | DESTDIR = 17 | TARGET_NAME = ${TARGET_BASE}.${LIB_R_VERSION} 18 | 19 | all: clib 20 | 21 | clean: 22 | /bin/rm -rf ../../src/*.o ${TARGET_NAME} ../../distorm3.a ./../*.o 23 | 24 | clib: ${COBJS} 25 | ${CC} ${CFLAGS} ${VERSION} ${COBJS} ${LDFLAGS} -o ${TARGET_NAME} 26 | tcc -ar rs ../../distorm3.a ${COBJS} 27 | 28 | install: ${TARGET_NAME} 29 | install -D -s ${TARGET_NAME} ${DESTDIR}${PREFIX}/lib/${TARGET_NAME} 30 | ln -sf ${DESTDIR}${PREFIX}/lib/${TARGET_NAME} ${DESTDIR}${PREFIX}/lib/${TARGET_BASE} 31 | @echo "... running ldconfig might be smart ..." 32 | 33 | .c.o: 34 | ${CC} ${CFLAGS} ${VERSION} -c $< -o $@ 35 | -------------------------------------------------------------------------------- /make/win32/cdistorm.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | clib 6 | Win32 7 | 8 | 9 | clib 10 | x64 11 | 12 | 13 | dll 14 | Win32 15 | 16 | 17 | dll 18 | x64 19 | 20 | 21 | 22 | distorm 23 | {15051CE1-AB10-4239-973D-01B84F2AD0A9} 24 | distorm 25 | Win32Proj 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | false 32 | NotSet 33 | false 34 | v142 35 | 36 | 37 | StaticLibrary 38 | false 39 | NotSet 40 | v142 41 | 42 | 43 | DynamicLibrary 44 | false 45 | NotSet 46 | false 47 | v142 48 | 49 | 50 | StaticLibrary 51 | false 52 | NotSet 53 | v142 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | <_ProjectFileVersion>10.0.30319.1 77 | $(Configuration)\ 78 | $(Platform)\$(Configuration)\ 79 | $(Configuration)\ 80 | $(Platform)\$(Configuration)\ 81 | AllRules.ruleset 82 | 83 | 84 | AllRules.ruleset 85 | 86 | 87 | AllRules.ruleset 88 | 89 | 90 | AllRules.ruleset 91 | 92 | 93 | distorm3 94 | distorm3 95 | $(SolutionDir)..\..\ 96 | $(SolutionDir)..\..\ 97 | $(SolutionDir)..\..\ 98 | $(SolutionDir)..\..\ 99 | distorm 100 | distorm 101 | 102 | 103 | 104 | MaxSpeed 105 | AnySuitable 106 | Speed 107 | true 108 | false 109 | %(AdditionalIncludeDirectories) 110 | WIN32;NDEBUG;DISTORM_STATIC;SUPPORT_64BIT_OFFSET;%(PreprocessorDefinitions) 111 | true 112 | false 113 | MultiThreaded 114 | true 115 | 116 | 117 | ProgramDatabase 118 | CompileAsC 119 | distorm.pdb 120 | Level4 121 | true 122 | 123 | 124 | MachineX86 125 | 126 | 127 | 128 | 129 | X64 130 | 131 | 132 | Full 133 | AnySuitable 134 | Speed 135 | true 136 | false 137 | %(AdditionalIncludeDirectories) 138 | WIN32;NDEBUG;DISTORM_STATIC;SUPPORT_64BIT_OFFSET;%(PreprocessorDefinitions) 139 | true 140 | false 141 | MultiThreaded 142 | true 143 | 144 | 145 | Level4 146 | true 147 | ProgramDatabase 148 | CompileAsC 149 | distorm.pdb 150 | 151 | 152 | MachineX64 153 | 154 | 155 | 156 | 157 | MaxSpeed 158 | AnySuitable 159 | Speed 160 | true 161 | false 162 | %(AdditionalIncludeDirectories) 163 | WIN32;NDEBUG;DISTORM_DYNAMIC;SUPPORT_64BIT_OFFSET;%(PreprocessorDefinitions) 164 | true 165 | false 166 | true 167 | 168 | 169 | Level4 170 | ProgramDatabase 171 | CompileAsC 172 | true 173 | distorm3.pdb 174 | MultiThreadedDLL 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | X64 183 | 184 | 185 | MaxSpeed 186 | AnySuitable 187 | Speed 188 | true 189 | false 190 | %(AdditionalIncludeDirectories) 191 | WIN32;NDEBUG;DISTORM_DYNAMIC;SUPPORT_64BIT_OFFSET;%(PreprocessorDefinitions) 192 | true 193 | false 194 | MultiThreadedDLL 195 | true 196 | 197 | 198 | Level4 199 | ProgramDatabase 200 | CompileAsC 201 | true 202 | distorm3.pdb 203 | 204 | 205 | MachineX64 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | -------------------------------------------------------------------------------- /make/win32/cdistorm.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {50ac9ad6-0895-4596-b142-1a7fad1b97d5} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm 7 | 8 | 9 | {8612ae75-7b41-4557-b23b-d3e14e7f9613} 10 | h;hpp;hxx;hm;inl;inc 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | Source Files 19 | 20 | 21 | Source Files 22 | 23 | 24 | Source Files 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | 40 | 41 | Header Files 42 | 43 | 44 | Header Files 45 | 46 | 47 | Header Files 48 | 49 | 50 | Header Files 51 | 52 | 53 | Header Files 54 | 55 | 56 | Header Files 57 | 58 | 59 | Header Files 60 | 61 | 62 | Header Files 63 | 64 | 65 | Header Files 66 | 67 | 68 | Header Files 69 | 70 | 71 | Header Files 72 | 73 | 74 | Header Files 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /make/win32/distorm.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 15 3 | VisualStudioVersion = 15.0.28307.572 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "distorm", "cdistorm.vcxproj", "{15051CE1-AB10-4239-973D-01B84F2AD0A9}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | clib|Win32 = clib|Win32 10 | clib|x64 = clib|x64 11 | dll|Win32 = dll|Win32 12 | dll|x64 = dll|x64 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {15051CE1-AB10-4239-973D-01B84F2AD0A9}.clib|Win32.ActiveCfg = clib|Win32 16 | {15051CE1-AB10-4239-973D-01B84F2AD0A9}.clib|Win32.Build.0 = clib|Win32 17 | {15051CE1-AB10-4239-973D-01B84F2AD0A9}.clib|x64.ActiveCfg = clib|x64 18 | {15051CE1-AB10-4239-973D-01B84F2AD0A9}.clib|x64.Build.0 = clib|x64 19 | {15051CE1-AB10-4239-973D-01B84F2AD0A9}.dll|Win32.ActiveCfg = dll|Win32 20 | {15051CE1-AB10-4239-973D-01B84F2AD0A9}.dll|Win32.Build.0 = dll|Win32 21 | {15051CE1-AB10-4239-973D-01B84F2AD0A9}.dll|x64.ActiveCfg = dll|x64 22 | {15051CE1-AB10-4239-973D-01B84F2AD0A9}.dll|x64.Build.0 = dll|x64 23 | EndGlobalSection 24 | GlobalSection(SolutionProperties) = preSolution 25 | HideSolutionNode = FALSE 26 | EndGlobalSection 27 | GlobalSection(ExtensibilityGlobals) = postSolution 28 | SolutionGuid = {11B358A5-CF9E-4C14-9F0F-B7DE2C53FA81} 29 | EndGlobalSection 30 | EndGlobal 31 | -------------------------------------------------------------------------------- /make/win32/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by resource.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | //{{NO_DEPENDENCIES}} 16 | // Microsoft Visual C++ generated include file. 17 | // Used by Resource.rc 18 | 19 | // Next default values for new objects 20 | // 21 | #ifdef APSTUDIO_INVOKED 22 | #ifndef APSTUDIO_READONLY_SYMBOLS 23 | #define _APS_NEXT_RESOURCE_VALUE 101 24 | #define _APS_NEXT_COMMAND_VALUE 40001 25 | #define _APS_NEXT_CONTROL_VALUE 1001 26 | #define _APS_NEXT_SYMED_VALUE 101 27 | #endif 28 | #endif 29 | -------------------------------------------------------------------------------- /make/win32/resource.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdabah/distorm/7a02caa1a936f0a653fc75f1aaea9bd3fa654603/make/win32/resource.rc -------------------------------------------------------------------------------- /python/distorm3/__main__.py: -------------------------------------------------------------------------------- 1 | # Based on work by Mario Vilas, http://breakingcode.wordpress.com, licensed under BSD in 2016 2 | 3 | import distorm3 4 | import argparse 5 | 6 | 7 | def parse_args(): 8 | parser = argparse.ArgumentParser() 9 | parser.add_argument( 10 | "--b16", 11 | help="80286 decoding", 12 | action="store_const", 13 | dest="dt", 14 | const=distorm3.Decode16Bits, 15 | ) 16 | parser.add_argument( 17 | "--b32", 18 | help="IA-32 decoding [default]", 19 | action="store_const", 20 | dest="dt", 21 | const=distorm3.Decode32Bits, 22 | ) 23 | parser.add_argument( 24 | "--b64", 25 | help="AMD64 decoding", 26 | action="store_const", 27 | dest="dt", 28 | const=distorm3.Decode64Bits, 29 | ) 30 | parser.add_argument("file",) 31 | parser.add_argument( 32 | "offset", type=int, nargs="?", 33 | ) 34 | parser.set_defaults(dt=distorm3.Decode32Bits) 35 | args = parser.parse_args() 36 | return args 37 | 38 | 39 | def main(): 40 | args = parse_args() 41 | offset = args.offset 42 | 43 | # Read the code from the file 44 | with open(args.file, "rb") as infp: 45 | code = infp.read() 46 | 47 | # Print each decoded instruction 48 | # This shows how to use the DecodeGenerator 49 | iterable = distorm3.DecodeGenerator(offset, code, args.dt) 50 | for (offset, size, instruction, hexdump) in iterable: 51 | print("%.8x: %-32s %s" % (offset, hexdump, instruction)) 52 | 53 | # It could also be used as a returned list: 54 | # l = distorm3.Decode(offset, code, options.dt) 55 | # for (offset, size, instruction, hexdump) in l: 56 | # print("%.8x: %-32s %s" % (offset, hexdump, instruction)) 57 | 58 | 59 | if __name__ == "__main__": 60 | main() 61 | -------------------------------------------------------------------------------- /python/python_module_init.c: -------------------------------------------------------------------------------- 1 | #define PY_SSIZE_T_CLEAN 2 | #include 3 | 4 | #if PY_MAJOR_VERSION == 2 5 | PyMODINIT_FUNC init_distorm3(void) 6 | { 7 | (void)Py_InitModule("_distorm3", NULL); 8 | } 9 | #else 10 | static struct PyModuleDef _distorm3_module = { 11 | PyModuleDef_HEAD_INIT, 12 | "_distorm3", 13 | NULL, 14 | -1, 15 | NULL, 16 | }; 17 | 18 | PyMODINIT_FUNC PyInit__distorm3(void) 19 | { 20 | PyObject *m; 21 | 22 | m = PyModule_Create(&_distorm3_module); 23 | if (m == NULL) 24 | return NULL; 25 | 26 | return m; 27 | } 28 | #endif 29 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [install] 2 | force=1 3 | compile=1 4 | optimize=1 5 | 6 | [bdist_wininst] 7 | user-access-control=auto 8 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | import os.path 5 | from glob import glob 6 | from setuptools import Extension, setup 7 | 8 | def main(): 9 | # Just in case we are being called from a different directory 10 | cwd = os.path.dirname(__file__) 11 | if cwd: 12 | os.chdir(cwd) 13 | 14 | distorm_module = Extension( 15 | "_distorm3", 16 | sources=sorted(glob('src/*.c')) + ["python/python_module_init.c"], 17 | include_dirs=['src', 'include'], 18 | define_macros=[('SUPPORT_64BIT_OFFSET', None), ('DISTORM_DYNAMIC', None)], 19 | ) 20 | 21 | options = { 22 | # Setup instructions 23 | 'requires' : ['ctypes'], 24 | 'provides' : ['distorm3'], 25 | 'packages' : ['distorm3'], 26 | 'package_dir' : { '' : 'python' }, 27 | 'ext_modules' : [distorm_module], 28 | # Metadata 29 | 'name' : 'distorm3', 30 | 'version' : '3.5.3', 31 | 'description' : 'The goal of diStorm3 is to decode x86/AMD64' \ 32 | ' binary streams and return a structure that' \ 33 | ' describes each instruction.', 34 | 'long_description' : ( 35 | 'Powerful Disassembler Library For AMD64\n' 36 | 'by Gil Dabah (distorm@gmail.com)\n' 37 | '\n' 38 | 'Python bindings by Mario Vilas (mvilas@gmail.com)' 39 | ), 40 | 'author' : 'Gil Dabah', 41 | 'author_email' : 'distorm@gmail.com', 42 | 'maintainer' : 'Gil Dabah', 43 | 'maintainer_email' : 'distorm@gmail.com', 44 | 'url' : 'https://github.com/gdabah/distorm/', 45 | 'download_url' : 'https://github.com/gdabah/distorm/', 46 | 'platforms' : ['cygwin', 'win', 'linux', 'macosx'], 47 | 'classifiers' : [ 48 | 'License :: OSI Approved :: BSD License', 49 | 'Development Status :: 5 - Production/Stable', 50 | 'Intended Audience :: Developers', 51 | 'Natural Language :: English', 52 | 'Operating System :: Microsoft :: Windows', 53 | 'Operating System :: MacOS :: MacOS X', 54 | 'Operating System :: POSIX :: Linux', 55 | 'Programming Language :: Python :: 3.5', 56 | 'Topic :: Software Development :: Disassemblers', 57 | 'Topic :: Software Development :: Libraries :: Python Modules', 58 | ] 59 | } 60 | 61 | # Call the setup function 62 | setup(**options) 63 | 64 | if __name__ == '__main__': 65 | main() 66 | -------------------------------------------------------------------------------- /src/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-2021 Gil Dabah 8 | This library is licensed under the BSD license. See the file COPYING. 9 | */ 10 | 11 | 12 | #ifndef CONFIG_H 13 | #define CONFIG_H 14 | 15 | /* diStorm version number. */ 16 | #define __DISTORMV__ 0x030503 17 | 18 | #include /* memset, memcpy - can be easily self implemented for libc independency. */ 19 | 20 | #include "../include/distorm.h" 21 | 22 | 23 | /* 24 | * 64 bit offsets support: 25 | * This macro should be defined from compiler command line flags, e.g: -DSUPPORT_64BIT_OFFSET 26 | * Note: make sure that the caller (library user) defines it too! 27 | */ 28 | /* #define SUPPORT_64BIT_OFFSET */ 29 | 30 | /* 31 | * If you compile diStorm as a dynamic library (.dll or .so) file, make sure you uncomment the next line. 32 | * So the interface functions will be exported, otherwise they are useable only for static library. 33 | * For example, this macro is being set for compiling diStorm as a .dll for Python with CTypes. 34 | */ 35 | /* #define DISTORM_DYNAMIC */ 36 | 37 | /* 38 | * If DISTORM_LIGHT is defined, everything involved in formatting the instructions 39 | * as text will be excluded from compilation. 40 | * distorm_decode(..) and distorm_format(..) will not be available. 41 | * This will decrease the size of the executable and leave you with decomposition functionality only. 42 | * 43 | * Note: it should be either set in the preprocessor definitions manually or in command line -D switch. 44 | * #define DISTORM_LIGHT 45 | */ 46 | 47 | /* 48 | * diStorm now supports little/big endian CPU's. 49 | * It should detect the endianness according to predefined macro's of the compiler. 50 | * If you don't use GCC/MSVC you will have to define it on your own. 51 | */ 52 | 53 | /* These macros are used in order to make the code portable. */ 54 | #ifdef __GNUC__ 55 | 56 | #include 57 | 58 | #define _DLLEXPORT_ 59 | #define _FASTCALL_ 60 | /* Keep inline as static (arrrrg) as it would break linux on some flavors otherwise. */ 61 | #define _INLINE_ static 62 | /* GCC ignores this directive... */ 63 | /*#define _FASTCALL_ __attribute__((__fastcall__))*/ 64 | 65 | /* Set endianity (supposed to be LE though): */ 66 | #ifdef __BIG_ENDIAN__ 67 | #define BE_SYSTEM 68 | #endif 69 | 70 | /* End of __GCC__ */ 71 | 72 | #elif __WATCOMC__ 73 | 74 | #include 75 | 76 | #define _DLLEXPORT_ 77 | #define _FASTCALL_ 78 | #define _INLINE_ __inline 79 | 80 | /* End of __WATCOMC__ */ 81 | 82 | #elif __DMC__ 83 | 84 | #include 85 | 86 | #define _DLLEXPORT_ 87 | #define _FASTCALL_ 88 | #define _INLINE_ __inline 89 | 90 | /* End of __DMC__ */ 91 | 92 | #elif __TINYC__ 93 | 94 | #include 95 | 96 | #define _DLLEXPORT_ 97 | #define _FASTCALL_ 98 | #define _INLINE_ static 99 | 100 | /* End of __TINYC__ */ 101 | 102 | #elif _MSC_VER 103 | 104 | /* stdint alternative is defined in distorm.h */ 105 | 106 | #define _DLLEXPORT_ __declspec(dllexport) 107 | #define _FASTCALL_ __fastcall 108 | #define _INLINE_ __inline 109 | 110 | /* Set endianity (supposed to be LE though): */ 111 | #if !defined(_M_IX86) && !defined(_M_X64) 112 | #define BE_SYSTEM 113 | #endif 114 | 115 | #endif /* #elif _MSC_VER */ 116 | 117 | /* If the library isn't compiled as a dynamic library don't export any functions. */ 118 | #ifndef DISTORM_DYNAMIC 119 | #undef _DLLEXPORT_ 120 | #define _DLLEXPORT_ 121 | #endif 122 | 123 | #ifndef FALSE 124 | #define FALSE 0 125 | #endif 126 | #ifndef TRUE 127 | #define TRUE 1 128 | #endif 129 | 130 | /* Define stream read functions for big endian systems. */ 131 | #ifdef BE_SYSTEM 132 | 133 | /* Avoid defining 'static static' for GCC. */ 134 | #ifndef __GNUC__ 135 | #define STATIC_INLINE static _INLINE_ 136 | #else 137 | #define STATIC_INLINE static 138 | #endif 139 | 140 | /* 141 | * Assumption: These functions can read from the stream safely! 142 | * Swap endianity of input to little endian. 143 | */ 144 | STATIC_INLINE int16_t RSHORT(const uint8_t *s) 145 | { 146 | return s[0] | (s[1] << 8); 147 | } 148 | STATIC_INLINE uint16_t RUSHORT(const uint8_t *s) 149 | { 150 | return s[0] | (s[1] << 8); 151 | } 152 | STATIC_INLINE int32_t RLONG(const uint8_t *s) 153 | { 154 | return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); 155 | } 156 | STATIC_INLINE uint32_t RULONG(const uint8_t *s) 157 | { 158 | return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); 159 | } 160 | STATIC_INLINE int64_t RLLONG(const uint8_t *s) 161 | { 162 | 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); 163 | } 164 | STATIC_INLINE uint64_t RULLONG(const uint8_t *s) 165 | { 166 | 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); 167 | } 168 | 169 | #undef STATIC_INLINE 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 | -------------------------------------------------------------------------------- /src/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) 2003-2021 Gil Dabah 8 | This library is licensed under the BSD license. See the file COPYING. 9 | */ 10 | 11 | 12 | #ifndef DECODER_H 13 | #define DECODER_H 14 | 15 | #include "config.h" 16 | 17 | typedef unsigned int _iflags; 18 | 19 | _DecodeResult decode_internal(_CodeInfo* _ci, int supportOldIntr, _DInst result[], unsigned int maxResultCount, unsigned int* usedInstructionsCount); 20 | 21 | #endif /* DECODER_H */ 22 | -------------------------------------------------------------------------------- /src/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-2021 Gil Dabah 9 | This library is licensed under the BSD license. See the file COPYING. 10 | */ 11 | 12 | 13 | #include "../include/distorm.h" 14 | #include "config.h" 15 | #include "decoder.h" 16 | #include "x86defs.h" 17 | #include "textdefs.h" 18 | #include "wstring.h" 19 | #include "../include/mnemonics.h" 20 | 21 | /* C DLL EXPORTS */ 22 | #ifdef SUPPORT_64BIT_OFFSET 23 | _DLLEXPORT_ _DecodeResult distorm_decompose64(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) 24 | #else 25 | _DLLEXPORT_ _DecodeResult distorm_decompose32(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) 26 | #endif 27 | { 28 | if (usedInstructionsCount == NULL) { 29 | return DECRES_SUCCESS; 30 | } 31 | 32 | if ((ci == NULL) || 33 | (ci->codeLen < 0) || 34 | ((unsigned)ci->dt > (unsigned)Decode64Bits) || 35 | (ci->code == NULL) || 36 | (result == NULL) || 37 | (maxInstructions == 0) || 38 | ((ci->features & (DF_MAXIMUM_ADDR16 | DF_MAXIMUM_ADDR32)) == (DF_MAXIMUM_ADDR16 | DF_MAXIMUM_ADDR32))) 39 | { 40 | return DECRES_INPUTERR; 41 | } 42 | 43 | return decode_internal(ci, FALSE, result, maxInstructions, usedInstructionsCount); 44 | } 45 | 46 | #ifndef DISTORM_LIGHT 47 | 48 | /* Helper function to concatenate an explicit size when it's unknown from the operands. */ 49 | static void distorm_format_size(unsigned char** str, const _DInst* di, int opNum) 50 | { 51 | int isSizingRequired = 0; 52 | /* 53 | * We only have to output the size explicitly if it's not clear from the operands. 54 | * For example: 55 | * mov al, [0x1234] -> The size is 8, we know it from the AL register operand. 56 | * mov [0x1234], 0x11 -> Now we don't know the size. Pam pam pam 57 | * 58 | * If given operand number is higher than 2, then output the size anyways. 59 | */ 60 | isSizingRequired = ((opNum >= 2) || ((opNum == 0) && (di->ops[0].type != O_REG) && (di->ops[1].type != O_REG))); 61 | 62 | /* Still not sure? Try some special instructions. */ 63 | if (!isSizingRequired) { 64 | /* 65 | * INS/OUTS are exception, because DX is a port specifier and not a real src/dst register. 66 | * A few exceptions that always requires sizing: 67 | * MOVZX, MOVSX, MOVSXD. 68 | * ROL, ROR, RCL, RCR, SHL, SHR, SAL, SAR. 69 | * SHLD, SHRD. 70 | * CVTSI2SS is also an exception. 71 | */ 72 | switch (di->opcode) 73 | { 74 | case I_INS: 75 | case I_OUTS: 76 | case I_MOVZX: 77 | case I_MOVSX: 78 | case I_MOVSXD: 79 | case I_ROL: 80 | case I_ROR: 81 | case I_RCL: 82 | case I_RCR: 83 | case I_SHL: 84 | case I_SHR: 85 | case I_SAL: 86 | case I_SAR: 87 | case I_SHLD: 88 | case I_SHRD: 89 | case I_CVTSI2SS: 90 | isSizingRequired = 1; 91 | break; 92 | default: /* Instruction doesn't require sizing. */ break; 93 | } 94 | } 95 | 96 | if (isSizingRequired) 97 | { 98 | /*case 0: break; OT_MEM's unknown size. */ 99 | switch (di->ops[opNum].size / 8) 100 | { 101 | case 1: strcat_WS(*str, "BYTE ", 8, 5); break; 102 | case 2: strcat_WS(*str, "WORD ", 8, 5); break; 103 | case 4: strcat_WS(*str, "DWORD ", 8, 6); break; 104 | case 8: strcat_WS(*str, "QWORD ", 8, 6); break; 105 | case 10: strcat_WS(*str, "TBYTE ", 8, 6); break; 106 | case 16: strcat_WS(*str, "DQWORD ", 8, 7); break; 107 | case 32: strcat_WS(*str, "YWORD ", 8, 6); break; 108 | } 109 | } 110 | } 111 | 112 | static void distorm_format_signed_disp(unsigned char** str, const _DInst* di, uint64_t addrMask) 113 | { 114 | int64_t tmpDisp64; 115 | 116 | if (di->dispSize) { 117 | if (((int64_t)di->disp < 0)) { 118 | chrcat_WS(*str, MINUS_DISP_CHR); 119 | tmpDisp64 = -(int64_t)di->disp; 120 | tmpDisp64 &= addrMask; /* Verify only for neg numbers. */ 121 | } 122 | else { 123 | chrcat_WS(*str, PLUS_DISP_CHR); 124 | tmpDisp64 = di->disp; 125 | } 126 | str_int(str, tmpDisp64); 127 | } 128 | } 129 | 130 | static uint8_t prefixTable[6][8] = { "", "LOCK ", "REPNZ ", "REPNZ ", "REP ", "REPZ " }; 131 | static unsigned int prefixSizesTable[6] = { 0, 5, 6, 6, 4, 5 }; 132 | static uint8_t suffixTable[10] = { 0, 'B', 'W', 0, 'D', 0, 0, 0, 'Q' }; 133 | 134 | /* WARNING: This function is written carefully to be able to work with same input and output buffer in-place! */ 135 | #ifdef SUPPORT_64BIT_OFFSET 136 | _DLLEXPORT_ void distorm_format64(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result) 137 | #else 138 | _DLLEXPORT_ void distorm_format32(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result) 139 | #endif 140 | { 141 | unsigned char* str; 142 | int64_t tmpDisp64; 143 | uint64_t addrMask = (uint64_t)-1; 144 | const _WMnemonic* mnemonic; 145 | int suffixSize = -1; 146 | unsigned int i; 147 | 148 | /* Set address mask, when default is for 64bits addresses. */ 149 | if (ci->features & DF_USE_ADDR_MASK) addrMask = ci->addrMask; 150 | else { 151 | if (ci->features & DF_MAXIMUM_ADDR32) addrMask = 0xffffffff; 152 | else if (ci->features & DF_MAXIMUM_ADDR16) addrMask = 0xffff; 153 | } 154 | 155 | /* Gotta have full address for (di->addr - ci->codeOffset) to work in all modes. */ 156 | str_hex(&result->instructionHex, (const uint8_t*)&ci->code[(unsigned int)(di->addr - ci->codeOffset)], di->size); 157 | 158 | if ((int)((int16_t)di->flags) == -1) { 159 | /* In-place considerations: DI is RESULT. Deref fields first. */ 160 | unsigned int size = di->size; 161 | unsigned int byte = di->imm.byte; 162 | _OffsetType offset = di->addr & addrMask; 163 | 164 | result->offset = offset; 165 | result->size = size; 166 | str = (unsigned char*)&result->mnemonic.p; 167 | strcat_WS(str, "DB ", 4, 3); 168 | str_int(&str, byte); 169 | strfinalize_WS(result->mnemonic, str); 170 | *(uint64_t*)&result->operands = 0; /* Clears length and the string at once. */ 171 | return; /* Skip to next instruction. */ 172 | } 173 | 174 | str = (unsigned char*)&result->operands.p; 175 | 176 | /* Special treatment for String (movs, cmps, stos, lods, scas) instructions. */ 177 | if ((di->opcode >= I_MOVS) && (di->opcode <= I_SCAS)) { 178 | /* 179 | * No operands are needed if the address size is the default one, 180 | * and no segment is overridden, so add the suffix letter, 181 | * to indicate size of operation and continue to next instruction. 182 | */ 183 | if ((SEGMENT_IS_DEFAULT_OR_NONE(di->segment)) && (FLAG_GET_ADDRSIZE(di->flags) == ci->dt)) { 184 | suffixSize = di->ops[0].size / 8; 185 | goto skipOperands; 186 | } 187 | suffixSize = 0; /* Marks it's a string instruction. */ 188 | } 189 | 190 | for (i = 0; i < di->opsNo; i++) { 191 | unsigned int type = di->ops[i].type; 192 | if (i > 0) strcat_WS(str, ", ", 2, 2); 193 | if (type == O_REG) { 194 | strcat_WSR(&str, &_REGISTERS[di->ops[i].index]); 195 | } 196 | else if (type == O_IMM) { 197 | /* If the instruction is 'push', show explicit size (except byte imm). */ 198 | if ((di->opcode == I_PUSH) && (di->ops[i].size != 8)) distorm_format_size(&str, di, i); 199 | /* Special fix for negative sign extended immediates. */ 200 | if ((di->flags & FLAG_IMM_SIGNED) && (di->ops[i].size == 8) && (di->imm.sbyte < 0)) { 201 | chrcat_WS(str, MINUS_DISP_CHR); 202 | tmpDisp64 = -di->imm.sbyte; 203 | str_int(&str, tmpDisp64); 204 | } 205 | else { 206 | /* Notice signedness and size of the immediate. */ 207 | if (di->ops[i].size == 0x20) str_int(&str, di->imm.dword); 208 | else str_int(&str, di->imm.qword); 209 | } 210 | } 211 | else if (type == O_PC) { 212 | #ifdef SUPPORT_64BIT_OFFSET 213 | str_int(&str, (di->size + di->imm.sqword + di->addr) & addrMask); 214 | #else 215 | tmpDisp64 = ((_OffsetType)di->imm.sdword + di->addr + di->size) & (uint32_t)addrMask; 216 | str_int(&str, tmpDisp64); 217 | #endif 218 | } 219 | else if (type == O_DISP) { 220 | distorm_format_size(&str, di, i); 221 | chrcat_WS(str, OPEN_CHR); 222 | if (!SEGMENT_IS_DEFAULT_OR_NONE(di->segment)) { 223 | strcat_WSR(&str, &_REGISTERS[SEGMENT_GET_UNSAFE(di->segment)]); 224 | chrcat_WS(str, SEG_OFF_CHR); 225 | } 226 | tmpDisp64 = di->disp & addrMask; 227 | str_int(&str, tmpDisp64); 228 | chrcat_WS(str, CLOSE_CHR); 229 | } 230 | else if (type == O_SMEM) { 231 | int isDefault; 232 | int segment; 233 | distorm_format_size(&str, di, i); 234 | chrcat_WS(str, OPEN_CHR); 235 | 236 | segment = SEGMENT_GET(di->segment); 237 | isDefault = SEGMENT_IS_DEFAULT(di->segment); 238 | 239 | /* 240 | * This is where we need to take special care for String instructions. 241 | * If we got here, it means we need to explicitly show their operands. 242 | * The problem with CMPS and MOVS is that they have two(!) memory operands. 243 | * So we have to complement(!) them ourselves, since the isntruction structure supplies only the segment that can be overridden. 244 | * And make the rest of the String operations explicit. 245 | * We ignore default ES/DS in 64 bits. 246 | * ["MOVS"], [OPT.REGI_EDI, OPT.REGI_ESI] -- DS can be overridden. 247 | * ["CMPS"], [OPT.REGI_ESI, OPT.REGI_EDI] -- DS can be overriden. 248 | * 249 | * suffixSize == 0 was set above for string opcode already. 250 | */ 251 | if (suffixSize == 0) { 252 | if (((di->opcode == I_MOVS) && (i == 0)) || ((di->opcode == I_CMPS) && (i == 1))) { 253 | if (ci->dt != Decode64Bits) { 254 | segment = R_ES; 255 | isDefault = FALSE; 256 | } 257 | else isDefault = TRUE; 258 | } 259 | else if (isDefault && ((di->opcode == I_MOVS) || (di->opcode == I_CMPS))) { 260 | if (ci->dt != Decode64Bits) { 261 | segment = R_DS; 262 | isDefault = FALSE; 263 | } 264 | } 265 | } 266 | if (!isDefault && (segment != R_NONE)) { 267 | strcat_WSR(&str, &_REGISTERS[segment]); 268 | chrcat_WS(str, SEG_OFF_CHR); 269 | } 270 | 271 | strcat_WSR(&str, &_REGISTERS[di->ops[i].index]); 272 | 273 | distorm_format_signed_disp(&str, di, addrMask); 274 | chrcat_WS(str, CLOSE_CHR); 275 | } 276 | else if (type == O_MEM) { 277 | distorm_format_size(&str, di, i); 278 | chrcat_WS(str, OPEN_CHR); 279 | if (!SEGMENT_IS_DEFAULT_OR_NONE(di->segment)) { 280 | strcat_WSR(&str, &_REGISTERS[SEGMENT_GET_UNSAFE(di->segment)]); 281 | chrcat_WS(str, SEG_OFF_CHR); 282 | } 283 | if (di->base != R_NONE) { 284 | strcat_WSR(&str, &_REGISTERS[di->base]); 285 | chrcat_WS(str, PLUS_DISP_CHR); 286 | } 287 | strcat_WSR(&str, &_REGISTERS[di->ops[i].index]); 288 | if (di->scale != 0) { 289 | switch (di->scale) 290 | { 291 | case 2: strcat_WS(str, "*2", 2, 2); break; 292 | case 4: strcat_WS(str, "*4", 2, 2); break; 293 | case 8: strcat_WS(str, "*8", 2, 2); break; 294 | } 295 | } 296 | distorm_format_signed_disp(&str, di, addrMask); 297 | chrcat_WS(str, CLOSE_CHR); 298 | } 299 | else if (type == O_PTR) { 300 | str_int(&str, di->imm.ptr.seg); 301 | chrcat_WS(str, SEG_OFF_CHR); 302 | str_int(&str, di->imm.ptr.off); 303 | } 304 | else if (type == O_IMM1) { 305 | str_int(&str, di->imm.ex.i1); 306 | } 307 | else if (type == O_IMM2) { 308 | str_int(&str, di->imm.ex.i2); 309 | } 310 | } 311 | 312 | skipOperands: 313 | 314 | /* Finalize the operands string. */ 315 | strfinalize_WS(result->operands, str); 316 | 317 | /* Not used anymore. 318 | if (di->flags & FLAG_HINT_TAKEN) strcat_WSN(str, " ;TAKEN"); 319 | else if (di->flags & FLAG_HINT_NOT_TAKEN) strcat_WSN(str, " ;NOT TAKEN"); 320 | */ 321 | { 322 | /* In-place considerations: DI is RESULT. Deref fields first. */ 323 | unsigned int opcode = di->opcode; 324 | unsigned int prefix = FLAG_GET_PREFIX(di->flags); 325 | unsigned int size = di->size; 326 | _OffsetType offset = di->addr & addrMask; 327 | str = (unsigned char*)&result->mnemonic.p; 328 | mnemonic = (const _WMnemonic*)&_MNEMONICS[opcode]; 329 | 330 | if (prefix) { 331 | /* REP prefix for CMPS and SCAS is really a REPZ. */ 332 | prefix += (opcode == I_CMPS); 333 | prefix += (opcode == I_SCAS); 334 | memcpy(str, &prefixTable[prefix][0], 8); 335 | str += prefixSizesTable[prefix]; 336 | } 337 | 338 | /* 339 | * Always copy 16 bytes from the mnemonic, we have a sentinel padding so we can read past. 340 | * This helps the compiler to remove the call to memcpy and therefore makes this copying much faster. 341 | * The longest instruction is exactly 16 chars long, so we null terminate the string below. 342 | */ 343 | memcpy((int8_t*)str, mnemonic->p, 16); 344 | str += mnemonic->length; 345 | 346 | if (suffixSize > 0) { 347 | *str++ = suffixTable[suffixSize]; 348 | } 349 | strfinalize_WS(result->mnemonic, str); 350 | 351 | result->offset = offset; 352 | result->size = size; 353 | } 354 | } 355 | 356 | #ifdef SUPPORT_64BIT_OFFSET 357 | _DLLEXPORT_ _DecodeResult distorm_decode64(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) 358 | #else 359 | _DLLEXPORT_ _DecodeResult distorm_decode32(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) 360 | #endif 361 | { 362 | _DecodeResult res; 363 | _CodeInfo ci; 364 | unsigned int i, instsCount; 365 | 366 | *usedInstructionsCount = 0; 367 | 368 | /* I use codeLen as a signed variable in order to ease detection of underflow... and besides - */ 369 | if (codeLen < 0) { 370 | return DECRES_INPUTERR; 371 | } 372 | 373 | if ((unsigned)dt > (unsigned)Decode64Bits) { 374 | return DECRES_INPUTERR; 375 | } 376 | 377 | /* Make sure there's at least one instruction in the result buffer. */ 378 | if ((code == NULL) || (result == NULL) || (maxInstructions == 0)) { 379 | return DECRES_INPUTERR; 380 | } 381 | 382 | /* 383 | * We have to format the result into text. But the interal decoder works with the new structure of _DInst. 384 | * Therefore, we will pass the result array(!) from the caller and the interal decoder will fill it in with _DInst's. 385 | * Then we will copy each result to a temporary structure, and use it to reformat that specific result. 386 | * 387 | * This is all done to save memory allocation and to work on the same result array in-place!!! 388 | * It's a bit ugly, I have to admit, but worth it. 389 | */ 390 | 391 | ci.codeOffset = codeOffset; 392 | ci.code = code; 393 | ci.codeLen = codeLen; 394 | ci.dt = dt; 395 | ci.features = DF_USE_ADDR_MASK; 396 | if (dt == Decode16Bits) ci.addrMask = 0xffff; 397 | else if (dt == Decode32Bits) ci.addrMask = 0xffffffff; 398 | else ci.addrMask = (_OffsetType)-1; 399 | 400 | res = decode_internal(&ci, TRUE, (_DInst*)result, maxInstructions, usedInstructionsCount); 401 | instsCount = *usedInstructionsCount; 402 | for (i = 0; i < instsCount; i++) { 403 | /* distorm_format is optimized and can work with same input/output buffer in-place. */ 404 | #ifdef SUPPORT_64BIT_OFFSET 405 | distorm_format64(&ci, (_DInst*)&result[i], &result[i]); 406 | #else 407 | distorm_format32(&ci, (_DInst*)&result[i], &result[i]); 408 | #endif 409 | } 410 | 411 | return res; 412 | } 413 | 414 | #endif /* DISTORM_LIGHT */ 415 | 416 | _DLLEXPORT_ unsigned int distorm_version(void) 417 | { 418 | return __DISTORMV__; 419 | } 420 | -------------------------------------------------------------------------------- /src/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-2021 Gil Dabah 8 | This library is licensed under the BSD license. See the file COPYING. 9 | */ 10 | 11 | 12 | #ifndef INSTS_H 13 | #define INSTS_H 14 | 15 | #include "instructions.h" 16 | 17 | 18 | /* Flags Table */ 19 | extern _iflags FlagsTable[]; 20 | 21 | /* Root Trie DB */ 22 | extern _InstSharedInfo InstSharedInfoTable[]; 23 | extern _InstInfo InstInfos[]; 24 | extern _InstInfoEx InstInfosEx[]; 25 | extern _InstNode InstructionsTree[]; 26 | 27 | /* 3DNow! Trie DB */ 28 | extern _InstNode Table_0F_0F; 29 | /* AVX related: */ 30 | extern _InstNode Table_0F, Table_0F_38, Table_0F_3A; 31 | 32 | /* 33 | * The inst_lookup will return on of these two instructions according to the specified decoding mode. 34 | * ARPL or MOVSXD on 64 bits is one byte instruction at index 0x63. 35 | */ 36 | extern _InstInfo II_MOVSXD; 37 | 38 | /* 39 | * 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. 40 | * If 0x90 is prefixed by a usable REX it will become XCHG, otherwise it will become a NOP. 41 | * Also note that if it's prefixed by 0xf3, it becomes a Pause. 42 | */ 43 | extern _InstInfo II_NOP; 44 | extern _InstInfo II_PAUSE; 45 | 46 | /* 47 | * RDRAND and VMPTRLD share same 2.3 bytes opcode, and then alternates on the MOD bits, 48 | * RDRAND is OT_FULL_REG while VMPTRLD is OT_MEM, and there's no such mixed type. 49 | * So a hack into the inst_lookup was added for this decision, the DB isn't flexible enough. :( 50 | */ 51 | extern _InstInfo II_RDRAND; 52 | 53 | /* 54 | * Used for letting the extract operand know the type of operands without knowing the 55 | * instruction itself yet, because of the way those instructions work. 56 | * See function instructions.c!inst_lookup_3dnow. 57 | */ 58 | extern _InstInfo II_3DNOW; 59 | 60 | /* Helper tables for pseudo compare mnemonics. */ 61 | extern uint16_t CmpMnemonicOffsets[8]; /* SSE */ 62 | extern uint16_t VCmpMnemonicOffsets[32]; /* AVX */ 63 | 64 | #endif /* INSTS_H */ 65 | -------------------------------------------------------------------------------- /src/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-2021 Gil Dabah 8 | This library is licensed under the BSD license. See the file COPYING. 9 | */ 10 | 11 | 12 | #ifndef OPERANDS_H 13 | #define OPERANDS_H 14 | 15 | #include "config.h" 16 | #include "decoder.h" 17 | #include "prefix.h" 18 | #include "instructions.h" 19 | 20 | int operands_extract(_CodeInfo* ci, _DInst* di, _InstInfo* ii, 21 | _iflags instFlags, _OpType type, 22 | unsigned int modrm, _PrefixState* ps, _DecodeType effOpSz, 23 | _DecodeType effAdrSz, _Operand* op); 24 | 25 | #endif /* OPERANDS_H */ 26 | -------------------------------------------------------------------------------- /src/prefix.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdabah/distorm/7a02caa1a936f0a653fc75f1aaea9bd3fa654603/src/prefix.c -------------------------------------------------------------------------------- /src/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-2021 Gil Dabah 8 | This library is licensed under the BSD license. See the file COPYING. 9 | */ 10 | 11 | 12 | #ifndef PREFIX_H 13 | #define PREFIX_H 14 | 15 | #include "config.h" 16 | #include "decoder.h" 17 | 18 | 19 | /* Specifies the type of the extension prefix, such as: REX, 2 bytes VEX, 3 bytes VEX. */ 20 | typedef enum {PET_NONE = 0, PET_REX, PET_VEX2BYTES, PET_VEX3BYTES} _PrefixExtType; 21 | 22 | /* Specifies an index into a table of prefixes by their type. */ 23 | typedef enum {PFXIDX_NONE = -1, PFXIDX_REX, PFXIDX_LOREP, PFXIDX_SEG, PFXIDX_OP_SIZE, PFXIDX_ADRS, PFXIDX_MAX} _PrefixIndexer; 24 | 25 | /* 26 | * This holds the prefixes state for the current instruction we decode. 27 | * decodedPrefixes includes all specific prefixes that the instruction got. 28 | * start is a pointer to the first prefix to take into account. 29 | * last is a pointer to the last byte we scanned. 30 | * Other pointers are used to keep track of prefixes positions and help us know if they appeared already and where. 31 | */ 32 | typedef struct { 33 | _iflags decodedPrefixes, usedPrefixes; 34 | /* Number of prefixes scanned for current instruction, including VEX! */ 35 | unsigned int count; 36 | uint16_t unusedPrefixesMask; 37 | /* Holds the offset to the prefix byte by its type. */ 38 | uint16_t pfxIndexer[PFXIDX_MAX]; 39 | _PrefixExtType prefixExtType; 40 | /* Indicates whether the operand size prefix (0x66) was used as a mandatory prefix. */ 41 | int isOpSizeMandatory; 42 | /* If VEX prefix is used, store the VEX.vvvv field. */ 43 | unsigned int vexV; 44 | /* The fields B/X/R/W/L of REX and VEX are stored together in this byte. */ 45 | unsigned int vrex; 46 | const uint8_t* vexPos; 47 | } _PrefixState; 48 | 49 | /* 50 | * Intel supports 6 types of prefixes, whereas AMD supports 5 types (lock is seperated from rep/nz). 51 | * REX is the fifth prefix type, this time I'm based on AMD64. 52 | * VEX is the 6th, though it can't be repeated. 53 | */ 54 | #define MAX_PREFIXES (5) 55 | 56 | extern int PrefixTables[256 * 2]; 57 | 58 | _INLINE_ int prefixes_is_valid(unsigned char ch, _DecodeType dt) 59 | { 60 | /* The predicate selects (branchlessly) second half table for 64 bits otherwise selects first half. */ 61 | return PrefixTables[ch + ((dt >> 1) << 8)]; 62 | } 63 | 64 | /* Ignore a specific prefix type. */ 65 | _INLINE_ void prefixes_ignore(_PrefixState* ps, _PrefixIndexer pi) 66 | { 67 | /* 68 | * If that type of prefix appeared already, set the bit of that *former* prefix. 69 | * Anyway, set the new index of that prefix type to the current index, so next time we know its position. 70 | */ 71 | ps->unusedPrefixesMask |= ps->pfxIndexer[pi]; 72 | } 73 | 74 | void prefixes_ignore_all(_PrefixState* ps); 75 | uint16_t prefixes_set_unused_mask(_PrefixState* ps); 76 | void prefixes_decode(_CodeInfo* ci, _PrefixState* ps); 77 | void prefixes_use_segment(_iflags defaultSeg, _PrefixState* ps, _DecodeType dt, _DInst* di); 78 | 79 | #endif /* PREFIX_H */ 80 | -------------------------------------------------------------------------------- /src/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-2021 Gil Dabah 8 | This library is licensed under the BSD license. See the file COPYING. 9 | */ 10 | 11 | 12 | #include "textdefs.h" 13 | 14 | #ifndef DISTORM_LIGHT 15 | 16 | static uint8_t Nibble2ChrTable[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 17 | #define NIBBLE_TO_CHR Nibble2ChrTable[t] 18 | 19 | void str_hex(_WString* s, const uint8_t* buf, unsigned int len) 20 | { 21 | /* 256 * 2 : 2 chars per byte value. */ 22 | static const char* TextBTable = 23 | "000102030405060708090a0b0c0d0e0f" \ 24 | "101112131415161718191a1b1c1d1e1f" \ 25 | "202122232425262728292a2b2c2d2e2f" \ 26 | "303132333435363738393a3b3c3d3e3f" \ 27 | "404142434445464748494a4b4c4d4e4f" \ 28 | "505152535455565758595a5b5c5d5e5f" \ 29 | "606162636465666768696a6b6c6d6e6f" \ 30 | "707172737475767778797a7b7c7d7e7f" \ 31 | "808182838485868788898a8b8c8d8e8f" \ 32 | "909192939495969798999a9b9c9d9e9f" \ 33 | "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" \ 34 | "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" \ 35 | "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" \ 36 | "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" \ 37 | "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" \ 38 | "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; 39 | 40 | unsigned int i = 0; 41 | /* Length is at least 1, enter loop. */ 42 | s->length = len * 2; 43 | s->p[len * 2] = 0; 44 | do { 45 | RSHORT(&s->p[i]) = RSHORT(&TextBTable[(*buf) * 2]); 46 | buf++; 47 | i += 2; 48 | } while (i < len * 2); 49 | } 50 | 51 | #ifdef SUPPORT_64BIT_OFFSET 52 | 53 | void str_int_impl(unsigned char** s, uint64_t x) 54 | { 55 | int8_t* buf; 56 | int shift = 0; 57 | OFFSET_INTEGER t = x; 58 | 59 | buf = (int8_t*)*s; 60 | 61 | *buf++ = '0'; 62 | *buf++ = 'x'; 63 | 64 | if (x == 0) { 65 | *buf = '0'; 66 | *s += 3; 67 | return; 68 | } 69 | 70 | do { 71 | t >>= 4; 72 | shift += 4; 73 | } while (t); 74 | 75 | do { 76 | shift -= 4; 77 | t = (x >> shift) & 0xf; 78 | *buf++ = NIBBLE_TO_CHR; 79 | } while (shift > 0); 80 | 81 | *s = (unsigned char*)buf; 82 | } 83 | 84 | #else 85 | 86 | void str_int_impl(unsigned char** s, uint8_t src[8]) 87 | { 88 | int8_t* buf; 89 | int i = 0, shift = 0; 90 | uint32_t x = RULONG(&src[sizeof(int32_t)]); 91 | int t; 92 | 93 | buf = (int8_t*)*s; 94 | buf[0] = '0'; 95 | buf[1] = 'x'; 96 | buf += 2; 97 | 98 | for (shift = 28; shift != -4; shift -= 4) { 99 | t = (x >> shift) & 0xf; 100 | if (i | t) buf[i++] = NIBBLE_TO_CHR; 101 | } 102 | 103 | x = RULONG(src); 104 | for (shift = 28; shift != 0; shift -= 4) { 105 | t = (x >> shift) & 0xf; 106 | if (i | t) buf[i++] = NIBBLE_TO_CHR; 107 | } 108 | t = x & 0xf; 109 | buf[i++] = NIBBLE_TO_CHR; 110 | 111 | *s += (size_t)(i + 2); 112 | } 113 | 114 | #endif /* SUPPORT_64BIT_OFFSET */ 115 | 116 | #endif /* DISTORM_LIGHT */ 117 | -------------------------------------------------------------------------------- /src/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-2021 Gil Dabah 8 | This library is licensed under the BSD license. See the file COPYING. 9 | */ 10 | 11 | 12 | #ifndef TEXTDEFS_H 13 | #define TEXTDEFS_H 14 | 15 | #include "config.h" 16 | #include "wstring.h" 17 | 18 | #ifndef DISTORM_LIGHT 19 | 20 | #define PLUS_DISP_CHR '+' 21 | #define MINUS_DISP_CHR '-' 22 | #define OPEN_CHR '[' 23 | #define CLOSE_CHR ']' 24 | #define SP_CHR ' ' 25 | #define SEG_OFF_CHR ':' 26 | 27 | /* 28 | Naming Convention: 29 | 30 | * get - returns a pointer to a string. 31 | * str - concatenates to string. 32 | 33 | * hex - means the function is used for hex dump (number is padded to required size) - Little Endian output. 34 | * code - means the function is used for disassembled instruction - Big Endian output. 35 | * off - means the function is used for 64bit offset - Big Endian output. 36 | 37 | * h - '0x' in front of the string. 38 | 39 | * b - byte 40 | * dw - double word (can be used for word also) 41 | * qw - quad word 42 | 43 | * all numbers are in HEX. 44 | */ 45 | 46 | void str_hex(_WString* s, const uint8_t* buf, unsigned int len); 47 | 48 | #ifdef SUPPORT_64BIT_OFFSET 49 | #define str_int(s, x) str_int_impl((s), (x)) 50 | void str_int_impl(unsigned char** s, uint64_t x); 51 | #else 52 | #define str_int(s, x) str_int_impl((s), (uint8_t*)&(x)) 53 | void str_int_impl(unsigned char** s, uint8_t src[8]); 54 | #endif 55 | 56 | #endif /* DISTORM_LIGHT */ 57 | 58 | #endif /* TEXTDEFS_H */ 59 | -------------------------------------------------------------------------------- /src/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-2021 Gil Dabah 8 | This library is licensed under the BSD license. See the file COPYING. 9 | */ 10 | 11 | 12 | #ifndef WSTRING_H 13 | #define WSTRING_H 14 | 15 | #include "config.h" 16 | #include "../include/mnemonics.h" 17 | 18 | #ifndef DISTORM_LIGHT 19 | 20 | _INLINE_ void strcat_WSR(unsigned char** str, const _WRegister* reg) 21 | { 22 | /* 23 | * Longest register name is YMM15 - 5 characters, 24 | * Copy 8 so compiler can do a QWORD move. 25 | * We copy nul termination and fix the length, so it's okay to copy more to the output buffer. 26 | * There's a sentinel register to make sure we don't read past the end of the registers table. 27 | */ 28 | memcpy((int8_t*)*str, (const int8_t*)reg->p, 8); 29 | *str += reg->length; 30 | } 31 | 32 | #define strfinalize_WS(s, end) do { *end = 0; s.length = (unsigned int)((size_t)end - (size_t)s.p); } while (0) 33 | #define chrcat_WS(s, ch) do { *s = ch; s += 1; } while (0) 34 | #define strcat_WS(s, buf, copylen, advancelen) do { memcpy((int8_t*)s, buf, copylen); s += advancelen; } while(0) 35 | 36 | #endif /* DISTORM_LIGHT */ 37 | 38 | #endif /* WSTRING_H */ 39 | -------------------------------------------------------------------------------- /src/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-2021 Gil Dabah 8 | This library is licensed under the BSD license. See the file COPYING. 9 | */ 10 | 11 | 12 | #ifndef X86DEFS_H 13 | #define X86DEFS_H 14 | 15 | 16 | #define SEG_REGS_MAX (6) 17 | #define CREGS_MAX (9) 18 | #define DREGS_MAX (8) 19 | 20 | /* Maximum instruction size, including prefixes */ 21 | #define INST_MAXIMUM_SIZE (15) 22 | 23 | /* Maximum range of imm8 (comparison type) of special SSE CMP instructions. */ 24 | #define INST_CMP_MAX_RANGE (8) 25 | 26 | /* Maximum range of imm8 (comparison type) of special AVX VCMP instructions. */ 27 | #define INST_VCMP_MAX_RANGE (32) 28 | 29 | /* Wait instruction byte code. */ 30 | #define INST_WAIT_INDEX (0x9b) 31 | 32 | /* Lea instruction byte code. */ 33 | #define INST_LEA_INDEX (0x8d) 34 | 35 | /* NOP/XCHG instruction byte code. */ 36 | #define INST_NOP_INDEX (0x90) 37 | 38 | /* ARPL/MOVSXD instruction byte code. */ 39 | #define INST_ARPL_INDEX (0x63) 40 | 41 | /* 42 | * Minimal MODR/M value of divided instructions. 43 | * It's 0xc0, two MSBs set, which indicates a general purpose register is used too. 44 | */ 45 | #define INST_DIVIDED_MODRM (0xc0) 46 | 47 | /* This is the escape byte value used for 3DNow! instructions. */ 48 | #define _3DNOW_ESCAPE_BYTE (0x0f) 49 | 50 | #define PREFIX_LOCK (0xf0) 51 | #define PREFIX_REPNZ (0xf2) 52 | #define PREFIX_REP (0xf3) 53 | #define PREFIX_CS (0x2e) 54 | #define PREFIX_SS (0x36) 55 | #define PREFIX_DS (0x3e) 56 | #define PREFIX_ES (0x26) 57 | #define PREFIX_FS (0x64) 58 | #define PREFIX_GS (0x65) 59 | #define PREFIX_OP_SIZE (0x66) 60 | #define PREFIX_ADDR_SIZE (0x67) 61 | #define PREFIX_VEX2b (0xc5) 62 | #define PREFIX_VEX3b (0xc4) 63 | 64 | /* REX prefix value range, 64 bits mode decoding only. */ 65 | #define PREFIX_REX_LOW (0x40) 66 | #define PREFIX_REX_HI (0x4f) 67 | /* In order to use the extended GPR's we have to add 8 to the Modr/M info values. */ 68 | #define EX_GPR_BASE (8) 69 | 70 | /* Mask for REX and VEX features: */ 71 | /* Base */ 72 | #define PREFIX_EX_B (1) 73 | /* Index */ 74 | #define PREFIX_EX_X (2) 75 | /* Register */ 76 | #define PREFIX_EX_R (4) 77 | /* Operand Width */ 78 | #define PREFIX_EX_W (8) 79 | /* Vector Lengh */ 80 | #define PREFIX_EX_L (0x10) 81 | 82 | #endif /* X86DEFS_H */ 83 | -------------------------------------------------------------------------------- /test-deps/yasm-1.3.0-win64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdabah/distorm/7a02caa1a936f0a653fc75f1aaea9bd3fa654603/test-deps/yasm-1.3.0-win64.exe --------------------------------------------------------------------------------