about summary refs log tree commit diff stats
path: root/example/disasm/full.py
diff options
context:
space:
mode:
authorCamille Mougey <camille.mougey@cea.fr>2015-01-18 18:44:44 +0100
committerCamille Mougey <camille.mougey@cea.fr>2015-01-23 17:24:43 +0100
commit9206458e0f4b815e4af68f8978d96d14632a087f (patch)
tree49482f48f187f558493b82bee6fd904912b52f3f /example/disasm/full.py
parent663b49b712b4309d44e2ae77e37f26861c4906b7 (diff)
downloadmiasm-9206458e0f4b815e4af68f8978d96d14632a087f.tar.gz
miasm-9206458e0f4b815e4af68f8978d96d14632a087f.zip
Example: Move disasm's examples to a `disasm` directory
Diffstat (limited to 'example/disasm/full.py')
-rw-r--r--example/disasm/full.py183
1 files changed, 183 insertions, 0 deletions
diff --git a/example/disasm/full.py b/example/disasm/full.py
new file mode 100644
index 00000000..f7ca6780
--- /dev/null
+++ b/example/disasm/full.py
@@ -0,0 +1,183 @@
+import os
+import logging
+from argparse import ArgumentParser
+from pdb import pm
+
+from miasm2.analysis.binary import Container
+from miasm2.core.asmbloc import log_asmbloc, asm_label, bloc2graph
+from miasm2.expression.expression import ExprId
+from miasm2.core.interval import interval
+from miasm2.analysis.machine import Machine
+
+log = logging.getLogger("dis")
+console_handler = logging.StreamHandler()
+console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
+log.addHandler(console_handler)
+log.setLevel(logging.INFO)
+
+filename = os.environ.get('PYTHONSTARTUP')
+if filename and os.path.isfile(filename):
+    execfile(filename)
+
+
+parser = ArgumentParser("Disassemble a binary")
+parser.add_argument('architecture', help="architecture: " + \
+                        ",".join(Machine.available_machine()))
+parser.add_argument('filename', help="File to disassemble")
+parser.add_argument('address', help="Starting address for disassembly engine",
+                    nargs="+")
+parser.add_argument('-f', "--followcall", action="store_true",
+                    help="Follow call instructions")
+parser.add_argument('-b', "--blockwatchdog", default=None, type=int,
+                    help="Maximum number of basic block to disassemble")
+parser.add_argument('-n', "--funcswatchdog", default=None, type=int,
+                    help="Maximum number of function to disassemble")
+parser.add_argument('-r', "--recurfunctions", action="store_true",
+                    help="Disassemble founded functions")
+parser.add_argument('-v', "--verbose", action="store_true", help="Verbose mode")
+parser.add_argument('-g', "--gen_ir", action="store_true",
+                    help="Compute the intermediate representation")
+parser.add_argument('-z', "--dis-nulstart-block", action="store_true",
+                    help="Do not disassemble NULL starting block")
+parser.add_argument('-l', "--dontdis-retcall", action="store_true",
+                    help="If set, disassemble only call destinations")
+parser.add_argument('-s', "--simplify", action="store_true",
+                    help="Use the liveness analysis pass")
+parser.add_argument('-o', "--shiftoffset", default=None, type=int,
+                    help="Shift input binary by an offset")
+parser.add_argument('-a', "--try-disasm-all", action="store_true",
+                    help="Try to disassemble the whole binary")
+parser.add_argument('-i', "--image", action="store_true",
+                    help="Display image representation of disasm")
+
+args = parser.parse_args()
+
+if args.verbose:
+    log_asmbloc.setLevel(logging.DEBUG)
+
+log.info("import machine...")
+machine = Machine(args.architecture)
+mn, dis_engine, ira = machine.mn, machine.dis_engine, machine.ira
+log.info('ok')
+
+log.info('Load binary')
+with open(args.filename) as fdesc:
+    cont = Container.from_stream(fdesc, addr=args.shiftoffset)
+
+default_addr = cont.entry_point
+bs = cont.bin_stream
+e = cont.executable
+
+log.info('ok')
+mdis = dis_engine(bs)
+# configure disasm engine
+mdis.dontdis_retcall = args.dontdis_retcall
+mdis.blocs_wd = args.blockwatchdog
+mdis.dont_dis_nulstart_bloc = not args.dis_nulstart_block
+
+todo = []
+addrs = [int(a, 16) for a in args.address]
+
+if len(addrs) == 0 and default_addr is not None:
+    addrs.append(default_addr)
+for ad in addrs:
+    todo = [(mdis, None, ad)]
+
+done = set()
+all_funcs = set()
+all_funcs_blocs = {}
+
+
+done_interval = interval()
+finish = False
+
+# Main disasm loop
+while not finish and todo:
+    while not finish and todo:
+        mdis, caller, ad = todo.pop(0)
+        if ad in done:
+            continue
+        done.add(ad)
+        ab = mdis.dis_multibloc(ad)
+
+        log.info('func ok %.16x (%d)' % (ad, len(all_funcs)))
+
+        all_funcs.add(ad)
+        all_funcs_blocs[ad] = ab
+        for b in ab:
+            for l in b.lines:
+                done_interval += interval([(l.offset, l.offset + l.l)])
+
+        if args.funcswatchdog is not None:
+            args.funcswatchdog -= 1
+        if args.recurfunctions:
+            for b in ab:
+                i = b.get_subcall_instr()
+                if not i:
+                    continue
+                for d in i.getdstflow(mdis.symbol_pool):
+                    if not (isinstance(d, ExprId) and isinstance(d.name, asm_label)):
+                        continue
+                    todo.append((mdis, i, d.name.offset))
+
+        if args.funcswatchdog is not None and args.funcswatchdog <= 0:
+            finish = True
+
+    if args.try_disasm_all:
+        for a, b in done_interval.intervals:
+            if b in done:
+                continue
+            log.debug('add func %s' % hex(b))
+            todo.append((mdis, None, b))
+
+
+# Generate dotty graph
+all_blocs = []
+for blocs in all_funcs_blocs.values():
+    all_blocs += blocs
+    # for b in blocs:
+    #    print b
+
+log.info('generate graph file')
+g = bloc2graph(all_blocs, True)
+open('graph_execflow.txt', 'w').write(g)
+
+log.info('generate intervals')
+
+all_lines = []
+total_l = 0
+
+print done_interval
+if args.image:
+    log.info('build img')
+    done_interval.show()
+
+for i, j in done_interval.intervals:
+    log.debug((hex(i), "->", hex(j)))
+
+
+all_lines.sort(key=lambda x: x.offset)
+open('lines.txt', 'w').write('\n'.join([str(l) for l in all_lines]))
+log.info('total lines %s' % total_l)
+
+
+# Bonus, generate IR graph
+if args.gen_ir:
+    log.info("generating IR")
+
+    ir_arch = ira(mdis.symbol_pool)
+    ir_arch.blocs = {}
+    for ad, all_bloc in all_funcs_blocs.items():
+        log.info("generating IR... %x" % ad)
+        for b in all_bloc:
+            ir_arch.add_bloc(b)
+
+    log.info("Gen Graph... %x" % ad)
+
+    ir_arch.gen_graph()
+
+    if args.simplify:
+        ir_arch.dead_simp()
+
+    out = ir_arch.graph()
+    open('graph_irflow.txt', 'w').write(out)