From 9206458e0f4b815e4af68f8978d96d14632a087f Mon Sep 17 00:00:00 2001 From: Camille Mougey Date: Sun, 18 Jan 2015 18:44:44 +0100 Subject: Example: Move disasm's examples to a `disasm` directory --- example/disasm/file.py | 19 +++++ example/disasm/full.py | 183 +++++++++++++++++++++++++++++++++++++++++ example/disasm/function.py | 18 ++++ example/disasm/single_instr.py | 12 +++ example/disasm_file.py | 19 ----- example/disasm_full.py | 183 ----------------------------------------- example/disasm_function.py | 18 ---- example/disasm_single_instr.py | 12 --- 8 files changed, 232 insertions(+), 232 deletions(-) create mode 100644 example/disasm/file.py create mode 100644 example/disasm/full.py create mode 100644 example/disasm/function.py create mode 100644 example/disasm/single_instr.py delete mode 100644 example/disasm_file.py delete mode 100644 example/disasm_full.py delete mode 100644 example/disasm_function.py delete mode 100644 example/disasm_single_instr.py (limited to 'example') 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) diff --git a/example/disasm_file.py b/example/disasm_file.py deleted file mode 100644 index 5bae0e89..00000000 --- a/example/disasm_file.py +++ /dev/null @@ -1,19 +0,0 @@ -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 deleted file mode 100644 index f7ca6780..00000000 --- a/example/disasm_full.py +++ /dev/null @@ -1,183 +0,0 @@ -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 deleted file mode 100644 index 0d443c26..00000000 --- a/example/disasm_function.py +++ /dev/null @@ -1,18 +0,0 @@ -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 deleted file mode 100644 index 0e29dcee..00000000 --- a/example/disasm_single_instr.py +++ /dev/null @@ -1,12 +0,0 @@ -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) -- cgit 1.4.1