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