-
Notifications
You must be signed in to change notification settings - Fork 0
/
unravel_base.py
94 lines (86 loc) · 2.91 KB
/
unravel_base.py
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
"""
* Unravel
* Interactive Disassembler
* (c) 2013 Tiago Rezende
*
* Base types, classes and algorithms
"""
class CodeGraphNode:
def __init__(self, at, read_as="code"):
self.at = at
self.read_as = read_as
def trace(self, code, deep = False):
operation = code.decode(at)
self.op = operation
self.flow_goto = []
self.flow_call = []
self.flow_data = []
for arrow in operation.arrows:
if arrow.type is "goto":
self.flow_goto += [code.node_at(arrow.dest, deep),]
elif arrow.type is "call":
self.flow_call += [code.node_at(arrow.dest, deep),]
elif arrow.type is "data":
flow = code.node_at(arrow.dest, False)
flow.set_read_as(arrow.read_as)
self.flow_data += [flow,]
class Arrow:
def __init__(self, type_, dest, read_as=None):
self.type = type_
self.dest = dest
self.read_as = read_as
class Insn:
def __init__(self, mnemo, tags, at, size, info, arrows):
self.size = size
self.mnemonic = mnemo
self.tags = tags
self.info = info
if arrows:
self.arrows = arrows
else:
self.arrows = [Arrow('goto', at+size)]
class InsnDecoder:
def __init__(self, image, arch, entry_addresses):
self.image = image
self.entry_addresses = entry_addresses
self.arch = arch
self.entry_nodes = {}
self.traced_nodes = {}
def make_flow_graph(self):
for point in self.starting_points:
node = CodeGraphNode(point)
self.entry_nodes[point] = node
node.trace(self, True)
def decode(self, at):
return self.arch.decode(self.image, at)
def node_at(self, at, follow = False):
if at in self.traced_nodes:
return self.traced_nodes[at]
else:
node = CodeGraphNode(at)
if follow:
self.traced_nodes[at] = node
node.trace(self, True)
return node
class ArchBigEndian:
def read8(self, image, at):
return image.read_byte(at)
def read16(self, image, at):
return self.read8(image, at)*256 + self.read8(image, at+1)
def read32(self, image, at):
return self.read16(image, at)*65536 + self.read16(image, at+2)
def decode(self, image, at):
return Insn('halt', None, [])
class ArchLittleEndian:
def read8(self, image, at):
return image.read_byte(at)
def read16(self, image, at):
return self.read8(image, at) + self.read8(image, at+1)*256
def read32(self, image, at):
return self.read16(image, at) + self.read16(image, at+2)*65536
def decode(self, image, at):
return Insn('halt', None, [])
def TableMatch(op, at, image, table):
for row in table:
if (op & row['mask']) == row['match']:
return row['fn'](op, at, image, row)