about summary refs log tree commit diff stats
path: root/example/test_dis.py
diff options
context:
space:
mode:
authorserpilliere <devnull@localhost>2014-06-03 10:27:56 +0200
committerserpilliere <devnull@localhost>2014-06-03 10:27:56 +0200
commited5c3668cc9f545b52674ad699fc2b0ed1ccb575 (patch)
tree07faf97d7e4d083173a1f7e1bfd249baed2d74f9 /example/test_dis.py
parenta183e1ebd525453710306695daa8c410fd0cb2af (diff)
downloadmiasm-ed5c3668cc9f545b52674ad699fc2b0ed1ccb575.tar.gz
miasm-ed5c3668cc9f545b52674ad699fc2b0ed1ccb575.zip
Miasm v2
* API has changed, so old scripts need updates
* See example for API usage
* Use tcc or llvm for jit emulation
* Go to test and run test_all.py to check install

Enjoy !
Diffstat (limited to 'example/test_dis.py')
-rw-r--r--example/test_dis.py266
1 files changed, 266 insertions, 0 deletions
diff --git a/example/test_dis.py b/example/test_dis.py
new file mode 100644
index 00000000..4400ec14
--- /dev/null
+++ b/example/test_dis.py
@@ -0,0 +1,266 @@
+import sys
+import os
+import time
+
+from miasm2.core.bin_stream import bin_stream_elf, bin_stream_pe, bin_stream_str
+from elfesteem import *
+from miasm2.core.asmbloc import *
+from miasm2.expression.simplifications import expr_simp
+from optparse import OptionParser
+from miasm2.core.cpu import dum_arg
+import cProfile
+from miasm2.expression.expression import *
+from miasm2.core.interval import interval
+from miasm2.core.utils import hexdump
+
+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)
+
+
+# log_asmbloc.setLevel(logging.DEBUG)
+filename = os.environ.get('PYTHONSTARTUP')
+if filename and os.path.isfile(filename):
+    execfile(filename)
+
+
+parser = OptionParser(usage="usage: %prog [options] file address")
+parser.add_option('-m', "--architecture", dest="machine", metavar="MACHINE",
+                  help="architecture: arm, x86_16, x86_32, x86_64, msp430")
+parser.add_option('-f', "--followcall", dest="followcall", action="store_true",
+                  default=False,
+                  help="follow call")
+
+parser.add_option('-b', "--blocwatchdog", dest="bw",
+                  default=None,
+                  help="address to disasemble")
+
+parser.add_option('-n', "--funcsnumwatchdog", dest="funcswd",
+                  default=None,
+                  help="max func to disasm")
+
+parser.add_option(
+    '-r', "--recurfunctions", dest="recurfunctions", action="store_true",
+    default=False,
+    help="disasm found functions")
+
+parser.add_option('-v', "--verbose", dest="verbose", action="store_true",
+                  default=False,
+                  help="verbose")
+
+parser.add_option('-g', "--gen_ir", dest="gen_ir", action="store_true",
+                  default=False,
+                  help="gen intermediate representation")
+
+parser.add_option('-z', "--dis_nulstart_bloc", dest="dis_nulstart_bloc",
+                  action="store_true", default=False,
+                  help="dont_dis_nulstart_bloc")
+parser.add_option('-l', "--dontdis_retcall", dest="dontdis_retcall",
+                  action="store_true", default=False,
+                  help="only disasm call dst")
+
+parser.add_option('-s', "--simplify", dest="simplify", action="store_true",
+                  default=False,
+                  help="for test purpose")
+
+parser.add_option('-o', "--shiftoffset", dest="shiftoffset",
+                  default="0",
+                  help="shift input str by offset")
+
+parser.add_option(
+    '-a', "--trydisasmall", dest="trydisasmall", action="store_true",
+    default=False,
+    help="try disasm all binary")
+
+parser.add_option('-i', "--image", dest="image", action="store_true",
+                  default=False,
+                  help="display image representation of disasm")
+
+(options, args) = parser.parse_args(sys.argv[1:])
+if not args:
+    parser.print_help()
+    sys.exit(0)
+fname = args[0]
+
+if options.verbose:
+    log_asmbloc.setLevel(logging.DEBUG)
+
+log.info("import machine...")
+mode = None
+dis_cb = None
+
+
+if options.machine == "arm":
+    from miasm2.arch.arm.disasm import dis_arm as dis_engine
+    from miasm2.arch.arm.arch import mn_arm as mn
+    from miasm2.arch.arm.ira import ir_a_arm as ira
+elif options.machine == "armt":
+    from miasm2.arch.arm.disasm import dis_armt as dis_engine
+    from miasm2.arch.arm.arch import mn_armt as mn
+    from miasm2.arch.arm.ira import ir_a_armt as ira
+elif options.machine == "sh4":
+    from miasm2.arch.sh4.disasm import dis_sha4 as dis_engine
+    from miasm2.arch.sh4.arch import mn_sh4 as mn
+    from miasm2.arch.sh4.ira import ir_a_sh4 as ira
+elif options.machine == "x86_16":
+    from miasm2.arch.x86.disasm import dis_x86_16 as dis_engine
+    from miasm2.arch.x86.arch import mn_x86 as mn
+    from miasm2.arch.x86.ira import ir_a_x86_16 as ira
+elif options.machine == "x86_32":
+    from miasm2.arch.x86.disasm import dis_x86_32 as dis_engine
+    from miasm2.arch.x86.arch import mn_x86 as mn
+    from miasm2.arch.x86.ira import ir_a_x86_32 as ira
+elif options.machine == "x86_64":
+    from miasm2.arch.x86.disasm import dis_x86_64 as dis_engine
+    from miasm2.arch.x86.arch import mn_x86 as mn
+    from miasm2.arch.x86.ira import ir_a_x86_64 as ira
+elif options.machine == "msp430":
+    from miasm2.arch.msp430.disasm import dis_msp430 as dis_engine
+    from miasm2.arch.msp430.arch import mn_msp430 as mn
+    from miasm2.arch.msp430.ira import ir_a_msp430 as ira
+else:
+    raise ValueError('unknown machine')
+log.info('ok')
+
+if options.bw != None:
+    options.bw = int(options.bw)
+if options.funcswd != None:
+    options.funcswd = int(options.funcswd)
+machine = options.machine
+
+log.info('load binary')
+b = open(fname).read()
+
+default_addr = 0
+bs = None
+if b.startswith('MZ'):
+    e = pe_init.PE(b)
+    if e.isPE() and e.NTsig.signature_value == 0x4550:
+        bs = bin_stream_pe(e.virt)
+        default_addr = e.rva2virt(e.Opthdr.AddressOfEntryPoint)
+elif b.startswith('\x7fELF'):
+    e = elf_init.ELF(b)
+    bs = bin_stream_elf(e.virt)
+    default_addr = e.Ehdr.entry
+
+if bs is None:
+    shift = int(options.shiftoffset, 16)
+    log.warning('fallback to string input (offset=%s)' % hex(shift))
+    bs = bin_stream_str(b, shift=shift)
+
+
+log.info('ok')
+mdis = dis_engine(bs)
+# configure disasm engine
+mdis.dontdis_retcall = options.dontdis_retcall
+mdis.blocs_wd = options.bw
+mdis.dont_dis_nulstart_bloc = not options.dis_nulstart_bloc
+
+todo = []
+addrs = [int(a, 16) for a in args[1:]]
+
+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 options.funcswd is not None:
+            options.funcswd -= 1
+        if options.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 options.funcswd is not None and options.funcswd <= 0:
+            finish = True
+
+    if options.trydisasmall:
+        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 options.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 options.gen_ir:
+    log.info("generating IR")
+
+    my_ir = ira(mdis.symbol_pool)
+    my_ir.blocs = {}
+    for ad, all_bloc in all_funcs_blocs.items():
+        log.info("generating IR... %x" % ad)
+        for b in all_bloc:
+            my_ir.add_bloc(b)
+
+    log.info("Gen Graph... %x" % ad)
+
+    my_ir.gen_graph()
+
+    if options.simplify:
+        my_ir.dead_simp()
+
+    out = my_ir.graph()
+    open('graph_irflow.txt', 'w').write(out)