about summary refs log tree commit diff stats
path: root/example/symbol_exec/depgraph.py
blob: 260d62ab483851eb40c496711d603505c90740d6 (plain) (blame)
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
from argparse import ArgumentParser
from pdb import pm
import json

from miasm2.analysis.machine import Machine
from miasm2.analysis.binary import Container
from miasm2.analysis.depgraph import DependencyGraph
from miasm2.expression.expression import ExprMem, ExprId, ExprInt

parser = ArgumentParser("Dependency grapher")
parser.add_argument("filename", help="Binary to analyse")
parser.add_argument("func_addr", help="Function address")
parser.add_argument("target_addr", help="Address to start")
parser.add_argument("element", nargs="+", help="Elements to track")
parser.add_argument("-m", "--architecture",
                    help="Architecture (%s)" % Machine.available_machine())
parser.add_argument("-i", "--implicit", help="Use implicit tracking",
                    action="store_true")
parser.add_argument("--unfollow-mem", help="Stop on memory statements",
                    action="store_true")
parser.add_argument("--unfollow-call", help="Stop on call statements",
                    action="store_true")
parser.add_argument("--do-not-simplify", help="Do not simplify expressions",
                    action="store_true")
parser.add_argument("--rename-args",
                    help="Rename common arguments (@32[ESP_init] -> Arg1)",
                    action="store_true")
parser.add_argument("--json",
                    help="Output solution in JSON",
                    action="store_true")
args = parser.parse_args()

# Get architecture
with open(args.filename, "rb") as fstream:
    cont = Container.from_stream(fstream)

arch = args.architecture if args.architecture else cont.arch
machine = Machine(arch)

# Check elements
elements = set()
regs = machine.mn.regs.all_regs_ids_byname
for element in args.element:
    try:
        elements.add(regs[element])
    except KeyError:
        raise ValueError("Unknown element '%s'" % element)

mdis = machine.dis_engine(cont.bin_stream, dont_dis_nulstart_bloc=True)
ir_arch = machine.ira(mdis.loc_db)

# Common argument forms
init_ctx = {}
if args.rename_args:
    if arch == "x86_32":
        # StdCall example
        for i in xrange(4):
            e_mem = ExprMem(ExprId("ESP_init", 32) + ExprInt(4 * (i + 1), 32), 32)
            init_ctx[e_mem] = ExprId("arg%d" % i, 32)

# Disassemble the targeted function
asmcfg = mdis.dis_multiblock(int(args.func_addr, 0))

# Generate IR
ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg)

# Get the instance
dg = DependencyGraph(
    ircfg, implicit=args.implicit,
    apply_simp=not args.do_not_simplify,
    follow_mem=not args.unfollow_mem,
    follow_call=not args.unfollow_call
)

# Build information
target_addr = int(args.target_addr, 0)
current_block = list(ircfg.getby_offset(target_addr))[0]
assignblk_index = 0
for assignblk_index, assignblk in enumerate(current_block):
    if assignblk.instr.offset == target_addr:
        break

# Enumerate solutions
json_solutions = []
for sol_nb, sol in enumerate(dg.get(current_block.loc_key, elements, assignblk_index, set())):
    fname = "sol_%d.dot" % sol_nb
    with open(fname, "w") as fdesc:
            fdesc.write(sol.graph.dot())

    results = sol.emul(ir_arch, ctx=init_ctx)
    tokens = {str(k): str(v) for k, v in results.iteritems()}
    if not args.json:
        result = ", ".join("=".join(x) for x in tokens.iteritems())
        print "Solution %d: %s -> %s" % (sol_nb,
                                         result,
                                         fname)
        if sol.has_loop:
            print '\tLoop involved'

    if args.implicit:
        sat = sol.is_satisfiable
        constraints = {}
        if sat:
            for element in sol.constraints:
                try:
                    result = '0x%x' % sol.constraints[element].as_long()
                except AttributeError:
                    result = str(sol.constraints[element])
                constraints[element] = result
        if args.json:
            tokens["satisfiability"] = sat
            tokens["constraints"] = {str(k): str(v)
                                     for k, v in constraints.iteritems()}
        else:
            print "\tSatisfiability: %s %s" % (sat, constraints)

    if args.json:
        tokens["has_loop"] = sol.has_loop
        json_solutions.append(tokens)


if args.json:
    print json.dumps(json_solutions)