-
Notifications
You must be signed in to change notification settings - Fork 17
/
call_graph.py
59 lines (47 loc) · 1.68 KB
/
call_graph.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
import idc
import idautils
import idaapi
import time
from sets import Set
import pydot
out_file = "call_graph.png"
def generate_graph():
callees = dict()
# Loop through all the functions in the binary
for function_ea in idautils.Functions():
f_name = GetFunctionName(function_ea)
# For each of the incoming references
for ref_ea in CodeRefsTo(function_ea, 0):
# Get the name of the referring function
caller_name = GetFunctionName(ref_ea)
# Add the current function to the list of functions
# called by the referring function
callees[caller_name] = callees.get(caller_name, Set())
callees[caller_name].add(f_name)
return callees
#Visit functions called by our starting point recursively
def walk_graph(g,seen,callees,start):
if start in callees.keys() and start not in seen: #Who needs recursion?
seen.add(start)
next = callees[start]
for i in next:
g.add_edge(pydot.Edge(start, i))
walk_graph(g,seen,callees,i)
start_time = time.time()
print "---- Generating Callgraph ----"
# Create graph
g = pydot.Dot(type='"digraph"')
# Set some defaults
g.set_rankdir('LR')
g.set_size('100,100')
g.add_node(pydot.Node('node', shape='ellipse', color='lightblue', style='filled'))
g.add_node(pydot.Node('edge', color='lightgrey'))
#Generate full control flow graph
callees = generate_graph()
seen = Set()
#walk the graph from start/main/_main/whatever so that only functions which are actually reachable are included
walk_graph(g,seen,callees,'start')
#write_ps to write postscript, write to write a dot file etc
g.write_png(out_file)
print("---- Callgraph complete - saved as: " + out_file +" ----")
print("---- Ran in: %s seconds ----" % (time.time() - start_time))