-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpydistorm.py.original
129 lines (109 loc) · 3.51 KB
/
pydistorm.py.original
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
128
"""
:[diStorm64 1.7.29}:
Copyright RageStorm (C) 2007, Gil Dabah
diStorm is licensed under the BSD license.
http://ragestorm.net/distorm/
---
Python binding for diStorm64 written by Victor Stinner
"""
import platform
from ctypes import cdll, c_long, c_ulong, c_int, c_uint, c_char, c_char_p, POINTER, c_byte, 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
osVer = platform.system()
if osVer == "Windows":
LIB_FILENAME = "distorm64.dll"
else:
LIB_FILENAME = 'libdistorm64.so'
distorm = cdll.LoadLibrary(LIB_FILENAME)
Decode16Bits = 0
Decode32Bits = 1
Decode64Bits = 2
DECODERS = (Decode16Bits, Decode32Bits, Decode64Bits)
if osVer == "Windows":
if SUPPORT_64BIT_OFFSET:
decode_func = distorm.distorm_decode64
else:
decode_func = distorm.distorm_decode32
else:
decode_func = 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), # Unused.
("p", c_char * MAX_TEXT_SIZE),
)
def __str__(self):
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)
decode_func.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, long)):
raise TypeError("codeOffset have to be an integer")
if not isinstance(code, str):
raise TypeError("code have to be a string")
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 = decode_func(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 xrange(count):
instr = instr_array[index]
size += instr.size
yield instr
# Update parameters to move to next instructions
code += size
codeOffset += size
codeLen -= size