Commit 113b4151 authored by Sophie Brun's avatar Sophie Brun

Imported Upstream version 3.0

parent ccadabd8
COPYING
setup.cfg
setup.py
include\distorm.h
include\mnemonics.h
python\distorm3\__init__.py
python\distorm3\sample.py
src\config.h
src\decoder.c
src\decoder.h
src\distorm.c
src\instructions.c
src\instructions.h
src\insts.c
src\insts.h
src\mnemonics.c
src\operands.c
src\operands.h
src\prefix.c
src\prefix.h
src\textdefs.c
src\textdefs.h
src\wstring.c
src\wstring.h
src\x86defs.h
include COPYING setup.cfg setup.py
recursive-include src *.c *.h
recursive-include include *.c *.h
recursive-include . *.py
\ No newline at end of file
Metadata-Version: 1.1
Name: distorm3
Version: 3
Summary: The goal of diStorm3 is to decode x86/AMD64 binary streams and return a structure that describes each instruction.
Home-page: http://code.google.com/p/distorm/
Author: Gil Dabah
Author-email: arkon@ragestorm.net
License: UNKNOWN
Download-URL: http://code.google.com/p/distorm/
Description: Powerful Disassembler Library For AMD64
by Gil Dabah (arkon@ragestorm.net)
Python bindings by Mario Vilas (mvilas@gmail.com)
Platform: cygwin
Platform: win
Platform: linux
Platform: macosx
Classifier: License :: OSI Approved :: GPLv3 License
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Natural Language :: English
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Topic :: Software Development :: Disassemblers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires: ctypes
Provides: distorm3
This diff is collapsed.
This diff is collapsed.
#
# x86header.py
#
# Copyright (C) 2009 Gil Dabah, http://ragestorm.net/disops/
#
class OperandType:
""" Types of possible operands in an opcode.
Refer to the diStorm's documentation or diStorm's instructions.h
for more explanation about every one of them. """
(NONE,
IMM8,
IMM16,
IMM_FULL,
IMM32,
SEIMM8,
IMM16_1, # NEW
IMM8_1, # NEW
IMM8_2, # NEW
REG8,
REG16,
REG_FULL,
REG32,
REG32_64,
FREG32_64_RM,
RM8,
RM16,
RM_FULL,
RM32_64,
RM16_32,
FPUM16,
FPUM32,
FPUM64,
FPUM80,
R32_M8,
R32_M16,
R32_64_M8,
R32_64_M16,
RFULL_M16,
CREG,
DREG,
SREG,
SEG,
ACC8,
ACC16,
ACC_FULL,
ACC_FULL_NOT64,
MEM16_FULL,
PTR16_FULL,
MEM16_3264,
RELCB,
RELC_FULL,
MEM,
MEM_OPT, # NEW
MEM32,
MEM32_64, # NEW
MEM64,
MEM128,
MEM64_128,
MOFFS8,
MOFFS_FULL,
CONST1,
REGCL,
IB_RB,
IB_R_FULL,
REGI_ESI,
REGI_EDI,
REGI_EBXAL,
REGI_EAX,
REGDX,
REGECX,
FPU_SI,
FPU_SSI,
FPU_SIS,
MM,
MM_RM,
MM32,
MM64,
XMM,
XMM_RM,
XMM16,
XMM32,
XMM64,
XMM128,
REGXMM0,
# Below new for AVX:
RM32,
REG32_64_M8,
REG32_64_M16,
WREG32_64,
WRM32_64,
WXMM32_64,
VXMM,
XMM_IMM,
YXMM,
YXMM_IMM,
YMM,
YMM256,
VYMM,
VYXMM,
YXMM64_256,
YXMM128_256,
LXMM64_128,
LMEM128_256) = range(93)
class OpcodeLength:
""" The length of the opcode in bytes.
Where a suffix of '3' means we have to read the REG field of the ModR/M byte (REG size is 3 bits).
Suffix of 'd' means it's a Divided instruction (see documentation),
tells the disassembler to read the REG field or the whole next byte.
OL_33 and OL_4 are used in raw opcode bytes, they include the mandatory prefix,
therefore when they are defined in the instruction tables, the mandatory prefix table is added,
and they become OL_23 and OL_3 correspondingly. There is no effective opcode which is more than 3 bytes. """
(OL_1, # 0
OL_13, # 1
OL_1d, # 2 - Can be prefixed (only by WAIT/9b)
OL_2, # 3 - Can be prefixed
OL_23, # 4 - Can be prefixed
OL_2d, # 5
OL_3, # 6 - Can be prefixed
OL_33, # 7 - Internal only
OL_4 # 8 - Internal only
) = range(9)
""" Next-Opcode-Length dictionary is used in order to recursively build the instructions' tables dynamically.
It is used in such a way that it indicates how many more nested tables
we have to build and link starting from a given OL. """
NextOL = {OL_13: OL_1, OL_1d: OL_1, OL_2: OL_1, OL_23: OL_13,
OL_2d: OL_1d, OL_3: OL_2, OL_33: OL_23, OL_4: OL_3}
class InstFlag:
""" Instruction Flag contains all bit mask constants for describing an instruction.
You can bitwise-or the flags. See diStorm's documentation for more explanation.
The GEN_BLOCK is a special flag, it is used in the tables generator only;
See GenBlock class inside x86db.py. """
FLAGS_EX_START_INDEX = 32
INST_FLAGS_NONE = 0
(MODRM_REQUIRED, # 0
NOT_DIVIDED, # 1
_16BITS, # 2
_32BITS, # 3
PRE_LOCK, # 4
PRE_REPNZ, # 5
PRE_REP, # 6
PRE_CS, # 7
PRE_SS, # 8
PRE_DS, # 9
PRE_ES, # 10
PRE_FS, # 11
PRE_GS, # 12
PRE_OP_SIZE, # 13
PRE_ADDR_SIZE, # 14
NATIVE, # 15
USE_EXMNEMONIC, # 16
USE_OP3, # 17
USE_OP4, # 18
MNEMONIC_MODRM_BASED, # 19
MODRR_REQUIRED, # 20
_3DNOW_FETCH, # 21
PSEUDO_OPCODE, # 22
INVALID_64BITS, # 23
_64BITS, # 24
PRE_REX, # 25
USE_EXMNEMONIC2, # 26
_64BITS_FETCH, # 27
FORCE_REG0, # 28
PRE_VEX, # 29
MODRM_INCLUDED, # 30
DST_WR, # 31
VEX_L, # 32 From here on: flagsEx.
VEX_W, # 33
MNEMONIC_VEXW_BASED, # 34
MNEMONIC_VEXL_BASED, # 35
FORCE_VEXL, # 36
MODRR_BASED, # 37
VEX_V_UNUSED, # 38
GEN_BLOCK, # 39 From here on: internal to disOps.
EXPORTED # 40
) = [1 << i for i in xrange(41)]
# Nodes are extended if they have any of the following flags:
EXTENDED = (PRE_VEX | USE_EXMNEMONIC | USE_EXMNEMONIC2 | USE_OP3 | USE_OP4)
SEGMENTS = (PRE_CS | PRE_SS | PRE_DS | PRE_ES | PRE_FS | PRE_FS)
class ISetClass:
""" Instruction-Set-Class indicates to which set the instruction belongs.
These types are taken from the documentation of Intel/AMD. """
(INTEGER,
FPU,
P6,
MMX,
SSE,
SSE2,
SSE3,
SSSE3,
SSE4_1,
SSE4_2,
SSE4_A,
_3DNOW,
_3DNOWEXT,
VMX,
SVM,
AVX,
FMA,
CLMUL,
AES) = range(1, 20)
class FlowControl:
""" The flow control instruction will be flagged in the lo nibble of the 'meta' field in _InstInfo of diStorm.
They are used to distinguish between flow control instructions (such as: ret, call, jmp, jz, etc) to normal ones. """
(CALL,
RET,
SYS,
UNC_BRANCH,
CND_BRANCH,
INT,
CMOV) = range(1, 8)
class NodeType:
""" A node can really be an object holder for an instruction-info object or
another table (list) with a different size.
GROUP - 8 entries in the table
FULL - 256 entries in the table.
Divided - 72 entries in the table (ranges: 0x0-0x7, 0xc0-0xff).
Prefixed - 12 entries in the table (none, 0x66, 0xf2, 0xf3). """
(NONE, # 0
INFO, # 1
INFOEX, # 2
LIST_GROUP, # 3
LIST_FULL, # 4
LIST_DIVIDED, # 5
LIST_PREFIXED # 6
) = range(0, 7)
class CPUFlags:
""" Specifies all the flags that the x86/x64 CPU supports. """
(ZF, # 0
SF, # 1
CF, # 2
OF, # 3
PF, # 4
AF, # 5
DF, # 6
IF # 7
) = [1 << i for i in xrange(8)]
This source diff could not be displayed because it is too large. You can view the blob instead.
diStorm3 for Ring 0
Gil Dabah Aug 2010
http://ragestorm.net/distorm/
Tested sample with DDK 7600.16385.1 using WinXPSP2.
Steps of how to build the diStorm64 sample using the DDK.
Warning - Make sure the path you extracted diStorm to does not include any spaces, otherwise you will get an error from the build.
1) Open the DDK's build environment, for example: "Win XP Free Build Environment",
which readies the evnrionment variables for building a driver. Or run the SETENV.BAT in console.
2) Launch "build", once you're in the directory of the /ddkproj.
3) If everything worked smoothly, you should see a new file named "distorm.sys" under objfre_wxp_x86\i386
(that's if you use WinXP and the Free Environment).
- If you experienced any errors, try moving the whole distorm directory to c:\winddk\src\
(or any other directory tree which doesn't contain spaces in its name).
4) Now you will have to register the new driver:
a. Copy the distorm.sys file to \windows\system32\drivers\.
b. Use the DDK's regini.exe with the supplied distorm.ini.
c. Restart Windows for the effect to take place. :(
**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.
5) Now open your favorite debug-strings monitor (mine is DebugView).
Make sure you monitor kernel debug-strings.
6) Launching "net start distorm" from command line, will run the DriverEntry code in "main.c",
which will disassemble a few instructions from the KeBugcheck routine and dump it using DbgPrint.
NOTES:
-+----
The sample uses the stack for storing the results from the decode function.
If you have too many structures on the stack, you better allocate memory before calling the decode function,
and later on free that memory. Don't use the NONPAGED pool if you don't really need it.
_OffsetType is the type of the DecodedInstruction.Offset field, which defaults to 64bits,
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.
Notice that we call directly distorm_decode64, since we SUPPORT_64BIT_OFFSET and because we don't have the macros of distorm.h.
diStorm can be really compiled for all IRQL, it doesn't use any resource or the standard C library at all.
Although the sample uses diStorm at PASSIVE level.
\registry\machine\system\currentcontrolset\services\distorm
ImagePath = system32\drivers\distorm.sys
DisplayName = "distorm"
Type = REG_DWORD 0x1
Start = REG_DWORD 0x3
Group = Extended base
ErrorControl = REG_DWORD 0x1
\registry\machine\system\currentcontrolset\services\distorm\Parameters
BreakOnEntry = REG_DWORD 0x0
DebugMask = REG_DWORD 0x0
LogEvents = REG_DWORD 0x0
\ No newline at end of file
// Since the DDK's nmake is limited with directories, we will bypass that with this simple hack.
// Thanks to Razvan Hobeanu.
// Sep 2009.
#include "../src/mnemonics.c"
#include "../src/wstring.c"
#include "../src/textdefs.c"
#include "../src/x86defs.c"
#include "../src/prefix.c"
#include "../src/operands.c"
#include "../src/insts.c"
#include "../src/instructions.c"
#include "../src/distorm.c"
#include "../src/decoder.c"
/*
* main.c
* Sample kernel driver to show how diStorm can be easily compiled and used in Ring 0.
*
* /// Follow the README file in order to compile diStorm using the DDK. \\\
*
* Izik, Gil Dabah
* Jan 2007
* http://ragestorm.net/distorm/
*/
#include <ntddk.h>
#include "../include/distorm.h"
#include "dummy.c"
// The number of the array of instructions the decoder function will use to return the disassembled instructions.
// Play with this value for performance...
#define MAX_INSTRUCTIONS (15)
void DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
UNICODE_STRING pFcnName;
// Holds the result of the decoding.
_DecodeResult res;
// Decoded instruction information.
_DecodedInst decodedInstructions[MAX_INSTRUCTIONS];
// next is used for instruction's offset synchronization.
// decodedInstructionsCount holds the count of filled instructions' array by the decoder.
unsigned int decodedInstructionsCount = 0, i, next;
// Default decoding mode is 32 bits, could be set by command line.
_DecodeType dt = Decode32Bits;
// Default offset for buffer is 0, could be set in command line.
_OffsetType offset = 0;
char* errch = NULL;
// Buffer to disassemble.
unsigned char *buf;
int len = 100;
// Register unload routine
DriverObject->DriverUnload = DriverUnload;
DbgPrint("diStorm Loaded!\n");
// Get address of KeBugCheck
RtlInitUnicodeString(&pFcnName, L"KeBugCheck");
buf = (char *)MmGetSystemRoutineAddress(&pFcnName);
offset = (unsigned) (_OffsetType)buf;
DbgPrint("Resolving KeBugCheck @ 0x%08x\n", buf);
// Decode the buffer at given offset (virtual address).
while (1) {
res = distorm_decode64(offset, (const unsigned char*)buf, len, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount);
if (res == DECRES_INPUTERR) {
DbgPrint(("NULL Buffer?!\n"));
break;
}
for (i = 0; i < decodedInstructionsCount; i++) {
// Note that we print the offset as a 64 bits variable!!!
// It might be that you'll have to change it to %08X...
DbgPrint("%08I64x (%02d) %s %s %s\n", decodedInstructions[i].offset, decodedInstructions[i].size,
(char*)decodedInstructions[i].instructionHex.p,
(char*)decodedInstructions[i].mnemonic.p,
(char*)decodedInstructions[i].operands.p);
}
if (res == DECRES_SUCCESS || decodedInstructionsCount == 0) {
break; // All instructions were decoded.
}
// Synchronize:
next = (unsigned int)(decodedInstructions[decodedInstructionsCount-1].offset - offset);
next += decodedInstructions[decodedInstructionsCount-1].size;
// Advance ptr and recalc offset.
buf += next;
len -= next;
offset += next;
}
DbgPrint(("Done!\n"));
return STATUS_UNSUCCESSFUL; // Make sure the driver doesn't stay resident, so we can recompile and run again!
}
!INCLUDE $(NTMAKEENV)\makefile.def
\ No newline at end of file
TARGETNAME = distorm
TARGETPATH = obj
TARGETTYPE = DRIVER
C_DEFINES = $(C_DEFINES) -DSUPPORT_64BIT_OFFSET -DLIBDISTORM
INCLUDES = %BUILD%\inc;..\src;
LIBS = %BUILD%\lib
SOURCES = main.c
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="output" path="bin"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>distorm</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
#Sun Oct 31 17:27:29 IST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6
import java.nio.ByteBuffer;
import diStorm3.distorm3.*;
import diStorm3.CodeInfo;
import diStorm3.DecodedInst;
import diStorm3.OpcodeEnum;
import diStorm3.distorm3;
import diStorm3.DecodedResult;
import diStorm3.DecomposedResult;
import diStorm3.DecomposedInst;
public class Main {
public static void main(String[] args) {
byte[] buf = new byte[4];
buf[0] = (byte)0xc3;
buf[1] = (byte)0x33;
buf[2] = (byte)0xc0;
buf[3] = (byte)0xc3;
CodeInfo ci = new CodeInfo((long)0x1000, buf, DecodeType.Decode32Bits, 0);
DecodedResult dr = new DecodedResult(10);
distorm3.Decode(ci, dr);
for (DecodedInst x : dr.mInstructions) {
String s = String.format("%x %s %s", x.getOffset(), x.getMnemonic(), x.getOperands());
System.out.println(s);
}
DecomposedResult dr2 = new DecomposedResult(10);
distorm3.Decompose(ci, dr2);
for (DecomposedInst y: dr2.mInstructions) {
if (y.getOpcode() != OpcodeEnum.RET) {
DecodedInst x = distorm3.Format(ci, y);
String s = String.format("%x %s %s", x.getOffset(), x.getMnemonic(), x.getOperands());
System.out.println(s);
}
}
}
}
package diStorm3;
import java.nio.ByteBuffer;
public class CodeInfo {
public CodeInfo(long codeOffset, ByteBuffer code, distorm3.DecodeType dt, int features) {
mCodeOffset = codeOffset;
mCode = code;
mDecodeType = dt.ordinal();
mFeatures = features;
}
public CodeInfo(long codeOffset, byte[] rawCode, distorm3.DecodeType dt, int features) {
mCode = ByteBuffer.allocateDirect(rawCode.length);
mCode.put(rawCode);
mCodeOffset = codeOffset;
mDecodeType = dt.ordinal();
mFeatures = features;
}
private long mCodeOffset;
private long mNextOffset;
private ByteBuffer mCode;
private int mDecodeType;
private int mFeatures;
}
\ No newline at end of file
package diStorm3;
public class DecodedInst {
DecodedInst()
{
}
private String mMnemonic;
private String mOperands;
private String mHex;
private int mSize;
private long mOffset;
public String getMnemonic() {
return mMnemonic;
}
public String getOperands() {
return mOperands;
}
public String getHex() {
return mHex;
}
public int getSize() {
return mSize;
}
public long getOffset() {
return mOffset;
}
}
\ No newline at end of file
package diStorm3;
public class DecodedResult {
public DecodedResult(int maxInstructions) {
mMaxInstructions = maxInstructions;
mInstructions = null;
}
public DecodedInst[] mInstructions;
private int mMaxInstructions;
}
\ No newline at end of file
package diStorm3;
import diStorm3.Operand;
import diStorm3.Opcodes;
public class DecomposedInst {
private class ImmVariant {
private long mValue;
private int mSize;
public long getImm() {
return mValue;
}
public int getSize() {
return mSize;
}
}
private class DispVariant {
private long mDisplacement;
private int mSize;
public long getDisplacement() {
return mDisplacement;
}
public int getSize() {
return mSize;
}
}
private long mAddr;
private int mSize;
private int mFlags;
private int mSegment;
private int mBase, mScale;
private int mOpcode;
public Operand[] mOperands;
public DispVariant mDisp;
public ImmVariant mImm;
private int mUnusedPrefixesMask;
private int mMeta;
private int mRegistersMask;
private int mModifiedFlagsMask;
private int mTestedFlagsMask;
private int mUndefinedFlagsMask;
public long getAddress() {
return mAddr;
}
public int getSize() {
return mSize;
}
public OpcodeEnum getOpcode() {
return Opcodes.lookup(mOpcode);
}
public int getSegment() {
return mSegment & 0x7f;
}
public boolean isSegmentDefault() {
return (mSegment & 0x80) == 0x80;
}
public int getBase() {
return mBase;
}
public int getScale() {
return mScale;
}
public int getUnusedPrefixesMask() {