-
Notifications
You must be signed in to change notification settings - Fork 3
/
CFG.py
68 lines (49 loc) · 1.38 KB
/
CFG.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
from capstone import *
from capstone.x86 import *
MAX_INST_LEN = 15
md = Cs(CS_ARCH_X86, CS_MODE_64)
md.detail = True
def op_str(op):
return '0x{:x}: {} {}'.format(op.address, op.mnemonic, op.op_str)
def get_jmp_target(op):
target = op.operands[0]
if target.type == X86_OP_IMM:
return target.imm
else:
raise Exception
def succ(op):
addrs = []
if op.id not in [X86_INS_RET, X86_INS_RETF, X86_INS_RETFQ, X86_INS_JMP]:
addrs.append(op.address + op.size)
if X86_GRP_JUMP in op.groups:
addrs.append(get_jmp_target(op))
return addrs
def construct_cfg(elf, start_addr):
cfg = {}
work_queue = [start_addr]
while len(work_queue) > 0:
addr = work_queue.pop()
if addr in cfg:
continue
code = elf.read(addr, MAX_INST_LEN)
op = next(md.disasm(code, addr))
op.succs = succ(op)
cfg[addr] = op
work_queue += op.succs
return cfg
class CFG(object):
def __init__(self, elf, start_addr):
self.start_addr = start_addr
self.ops = construct_cfg(elf, start_addr)
self.end_addr = max(self.ops)
def __getitem__(self, key):
if isinstance(key, (int, long)):
return self.ops[key]
@property
def start(self):
return self[self.start_addr]
@property
def end(self):
return self[self.end_addr]
def __repr__(self):
return '{}(0x{:x})'.format(self.__class__.__name__, self.start_addr)