diff options
Diffstat (limited to 'example/disasm')
| -rw-r--r-- | example/disasm/file.py | 19 | ||||
| -rw-r--r-- | example/disasm/full.py | 183 | ||||
| -rw-r--r-- | example/disasm/function.py | 18 | ||||
| -rw-r--r-- | example/disasm/single_instr.py | 12 |
4 files changed, 232 insertions, 0 deletions
diff --git a/example/disasm/file.py b/example/disasm/file.py new file mode 100644 index 00000000..5bae0e89 --- /dev/null +++ b/example/disasm/file.py @@ -0,0 +1,19 @@ +import sys +from miasm2.arch.x86.disasm import dis_x86_32 +from miasm2.core.asmbloc import bloc2graph +from miasm2.analysis.binary import Container + +if len(sys.argv) != 3: + print 'Example:' + print "%s samples/box_upx.exe 0x410f90" % sys.argv[0] + sys.exit(0) + +addr = int(sys.argv[2], 16) +cont = Container.from_stream(open(sys.argv[1])) +mdis = dis_x86_32(cont.bin_stream) +# Inform the engine to avoid disassembling null instructions +mdis.dont_dis_nulstart_bloc = True +blocs = mdis.dis_multibloc(addr) + +graph = bloc2graph(blocs) +open('graph.txt', 'w').write(graph) 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) diff --git a/example/disasm/function.py b/example/disasm/function.py new file mode 100644 index 00000000..0d443c26 --- /dev/null +++ b/example/disasm/function.py @@ -0,0 +1,18 @@ +from miasm2.arch.x86.disasm import dis_x86_32 +from miasm2.core.asmbloc import bloc2graph + +# MOV EAX, 0x1337BEEF +# MOV ECX, 0x4 +# loop: +# ROL EAX, 0x8 +# LOOP loop +# RET +shellcode = '\xb8\xef\xbe7\x13\xb9\x04\x00\x00\x00\xc1\xc0\x08\xe2\xfb\xc3' +mdis = dis_x86_32(shellcode) +blocs = mdis.dis_multibloc(0) + +for bloc in blocs: + print bloc + +graph = bloc2graph(blocs) +open('graph.txt', 'w').write(graph) diff --git a/example/disasm/single_instr.py b/example/disasm/single_instr.py new file mode 100644 index 00000000..0e29dcee --- /dev/null +++ b/example/disasm/single_instr.py @@ -0,0 +1,12 @@ +from miasm2.arch.x86.arch import mn_x86 +from miasm2.arch.x86.regs import EDX + +l = mn_x86.fromstring('MOV EAX, EBX', 32) +print "instruction:", l +print "arg:", l.args[0] +x = mn_x86.asm(l) +print x +l.args[0] = EDX +y = mn_x86.asm(l) +print y +print mn_x86.dis(y[0], 32) |