1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
"""
:[diStorm64 1.7.27}:
Copyright RageStorm (C) 2007, Gil Dabah
diStorm is licensed under the BSD license.
http://ragestorm.net/distorm/
---
Python binding of diStorm64 library written by Victor Stinner
"""
from ctypes import cdll, c_long, c_ulong, c_int, c_uint, c_char, POINTER, Structure, addressof, byref, c_void_p, create_string_buffer, sizeof, cast
# Define (u)int32_t and (u)int64_t types
int32_t = c_int
uint32_t = c_uint
if sizeof(c_ulong) == 8:
int64_t = c_long
uint64_t = c_ulong
else:
from ctypes import c_longlong, c_ulonglong
assert sizeof(c_longlong) == 8
assert sizeof(c_ulonglong) == 8
int64_t = c_longlong
uint64_t = c_ulonglong
SUPPORT_64BIT_OFFSET = True
if SUPPORT_64BIT_OFFSET:
_OffsetType = uint64_t
else:
_OffsetType = uint32_t
LIB_FILENAME = 'libdistorm64.so'
distorm = cdll.LoadLibrary(LIB_FILENAME)
Decode16Bits = 0
Decode32Bits = 1
Decode64Bits = 2
DECODERS = (Decode16Bits, Decode32Bits, Decode64Bits)
internal_decode = distorm.internal_decode
DECRES_NONE = 0
DECRES_SUCCESS = 1
DECRES_MEMORYERR = 2
DECRES_INPUTERR = 3
MAX_INSTRUCTIONS = 100
MAX_TEXT_SIZE = 60
class _WString(Structure):
_fields_ = (
("pos", c_uint),
("p", c_char * MAX_TEXT_SIZE),
)
def __str__(self):
# FIXME: Use pos?
return self.p
class _DecodedInst(Structure):
_fields_ = (
("mnemonic", _WString),
("operands", _WString),
("instructionHex", _WString),
("size", c_uint),
("offset", _OffsetType),
)
def __str__(self):
return "%s %s" % (self.mnemonic, self.operands)
internal_decode.argtypes = (_OffsetType, c_void_p,
c_int, c_int, c_void_p, c_uint, POINTER(c_uint))
def Decode(codeOffset, code, dt=Decode32Bits):
"""
Errors: TypeError, IndexError, MemoryError, ValueError
"""
# Check arguments
if not isinstance(codeOffset, int):
raise TypeError("codeOffset have to be an integer")
if not isinstance(code, bytes):
raise TypeError("code have to be a bytes, not %s"
% (type(code).__name__,))
if dt not in DECODERS:
raise IndexError(
"Decoding-type must be either Decode16Bits, Decode32Bits or Decode64Bits.")
# Allocate memory for decoder
code_buffer = create_string_buffer(code)
decodedInstructionsCount = c_uint()
result = create_string_buffer(sizeof(_DecodedInst) * MAX_INSTRUCTIONS)
# Prepare arguments
codeLen = len(code)
code = addressof(code_buffer)
while codeLen:
# Call internal decoder
res = internal_decode(codeOffset, code, codeLen, dt, result,
MAX_INSTRUCTIONS, byref(decodedInstructionsCount))
# Check for errors
if res == DECRES_INPUTERR:
raise ValueError("Invalid argument")
count = decodedInstructionsCount.value
if res == DECRES_MEMORYERR and not count:
raise MemoryError()
# No more instruction
if not count:
break
# Yield instruction and compute decoded size
size = 0
instr_array = cast(result, POINTER(_DecodedInst))
for index in range(count):
instr = instr_array[index]
size += instr.size
yield instr
# Update parameters to move to next instructions
code += size
codeOffset += size
codeLen -= size
|