diff options
| -rw-r--r-- | example/disasm/callback.py | 15 | ||||
| -rw-r--r-- | example/disasm/dis_binary.py | 29 | ||||
| -rw-r--r-- | example/disasm/dis_binary_ir.py | 35 | ||||
| -rw-r--r-- | example/disasm/dis_binary_ira.py | 37 | ||||
| -rw-r--r-- | example/disasm/dis_x86_string.py | 22 | ||||
| -rw-r--r-- | example/disasm/file.py | 18 | ||||
| -rw-r--r-- | example/disasm/function.py | 16 | ||||
| -rw-r--r-- | example/expression/constant_propagation.py | 6 | ||||
| -rw-r--r-- | example/expression/graph_dataflow.py | 24 | ||||
| -rw-r--r-- | example/expression/solve_condition_stp.py | 9 | ||||
| -rw-r--r-- | example/samples/test_x86_32_dis.S | 12 | ||||
| -rw-r--r-- | example/symbol_exec/single_instr.py | 8 | ||||
| -rw-r--r-- | test/core/asmblock.py | 9 | ||||
| -rwxr-xr-x | test/test_all.py | 29 |
14 files changed, 189 insertions, 80 deletions
diff --git a/example/disasm/callback.py b/example/disasm/callback.py index b9a09c09..02416b38 100644 --- a/example/disasm/callback.py +++ b/example/disasm/callback.py @@ -1,6 +1,6 @@ -from miasm2.core.bin_stream import bin_stream_str +from miasm2.analysis.binary import Container +from miasm2.analysis.machine import Machine from miasm2.core.asmblock import AsmConstraint -from miasm2.arch.x86.disasm import dis_x86_32, cb_x86_funcs def cb_x86_callpop(cur_bloc, loc_db, *args, **kwargs): @@ -45,17 +45,18 @@ shellcode = ''.join(["\xe8\x00\x00\x00\x00", # CALL $ "X", # POP EAX "\xc3", # RET ]) -bin_stream = bin_stream_str(shellcode) -mdis = dis_x86_32(bin_stream) + +# Instantiate a x86 32 bit architecture +machine = Machine("x86_32") +cont = Container.from_string(shellcode) +mdis = machine.dis_engine(cont.bin_stream, loc_db=cont.loc_db) print "Without callback:\n" asmcfg = mdis.dis_multiblock(0) print "\n".join(str(block) for block in asmcfg.blocks) # Enable callback -cb_x86_funcs.append(cb_x86_callpop) -## Other method: -## mdis.dis_block_callback = cb_x86_callpop +mdis.dis_block_callback = cb_x86_callpop print "=" * 40 print "With callback:\n" diff --git a/example/disasm/dis_binary.py b/example/disasm/dis_binary.py new file mode 100644 index 00000000..3e12ca91 --- /dev/null +++ b/example/disasm/dis_binary.py @@ -0,0 +1,29 @@ +import sys +from miasm2.analysis.binary import Container +from miasm2.analysis.machine import Machine + +fdesc = open(sys.argv[1], 'rb') + +# The Container will provide a *bin_stream*, bytes source for the disasm engine +# It will prodive a view from a PE or an ELF. +cont = Container.from_stream(fdesc) + +# The Machine, instantiated with the detected architecture, will provide tools +# (disassembler, etc.) to work with this architecture +machine = Machine(cont.arch) + +# Instantiate a disassembler engine, using the previous bin_stream and its +# associated location DB. The assembly listing will use the binary symbols +mdis = machine.dis_engine(cont.bin_stream, loc_db=cont.loc_db) + +# Run a recursive traversal disassembling from the entry point +# (do not follow sub functions by default) +addr = cont.entry_point +asmcfg = mdis.dis_multiblock(addr) + +# Display each basic blocks +for block in asmcfg.blocks: + print block + +# Output control flow graph in a dot file +open('bin_cfg.dot', 'w').write(asmcfg.dot()) diff --git a/example/disasm/dis_binary_ir.py b/example/disasm/dis_binary_ir.py new file mode 100644 index 00000000..6d98d692 --- /dev/null +++ b/example/disasm/dis_binary_ir.py @@ -0,0 +1,35 @@ +import sys +from miasm2.analysis.binary import Container +from miasm2.analysis.machine import Machine + +##################################### +# Common section from dis_binary.py # +##################################### + +fdesc = open(sys.argv[1], 'rb') + +cont = Container.from_stream(fdesc) + +machine = Machine(cont.arch) + +mdis = machine.dis_engine(cont.bin_stream, loc_db=cont.loc_db) + +addr = cont.entry_point +asmcfg = mdis.dis_multiblock(addr) + +##################################### +# End common section # +##################################### + +# Get an IR convertor +ir_arch = machine.ir(mdis.loc_db) + +# Get the IR of the asmcfg +ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg) + +# Display each IR basic blocks +for irblock in ircfg.blocks.values(): + print irblock + +# Output ir control flow graph in a dot file +open('bin_ir_cfg.dot', 'w').write(ircfg.dot()) diff --git a/example/disasm/dis_binary_ira.py b/example/disasm/dis_binary_ira.py new file mode 100644 index 00000000..c1bd5dc0 --- /dev/null +++ b/example/disasm/dis_binary_ira.py @@ -0,0 +1,37 @@ +import sys +from miasm2.analysis.binary import Container +from miasm2.analysis.machine import Machine + +##################################### +# Common section from dis_binary.py # +##################################### + +fdesc = open(sys.argv[1], 'rb') + +cont = Container.from_stream(fdesc) + +machine = Machine(cont.arch) + +mdis = machine.dis_engine(cont.bin_stream, loc_db=cont.loc_db) + +addr = cont.entry_point +asmcfg = mdis.dis_multiblock(addr) + +##################################### +# End common section # +##################################### + +# Get an IRA convertor +# The sub call are modelised by default operators +# call_func_ret and call_func_stack +ir_arch_analysis = machine.ira(mdis.loc_db) + +# Get the IR of the asmcfg +ircfg_analysis = ir_arch_analysis.new_ircfg_from_asmcfg(asmcfg) + +# Display each IR basic blocks +for irblock in ircfg_analysis.blocks.values(): + print irblock + +# Output ir control flow graph in a dot file +open('bin_ira_cfg.dot', 'w').write(ircfg_analysis.dot()) diff --git a/example/disasm/dis_x86_string.py b/example/disasm/dis_x86_string.py new file mode 100644 index 00000000..8f919e4e --- /dev/null +++ b/example/disasm/dis_x86_string.py @@ -0,0 +1,22 @@ +from miasm2.analysis.binary import Container +from miasm2.analysis.machine import Machine + +# The Container will provide a *bin_stream*, bytes source for the disasm engine +cont = Container.from_string("\x83\xf8\x10\x74\x07\x89\xc6\x0f\x47\xc3\xeb\x08\x89\xc8\xe8\x31\x33\x22\x11\x40\xc3") + +# Instantiate a x86 32 bit architecture +machine = Machine("x86_32") + +# Instantiate a disassembler engine, using the previous bin_stream and its +# associated location DB. +mdis = machine.dis_engine(cont.bin_stream, loc_db=cont.loc_db) + +# Run a recursive traversal disassembling from address 0 +asmcfg = mdis.dis_multiblock(0) + +# Display each basic blocks +for block in asmcfg.blocks: + print block + +# Output control flow graph in a dot file +open('str_cfg.dot', 'w').write(asmcfg.dot()) diff --git a/example/disasm/file.py b/example/disasm/file.py deleted file mode 100644 index 196e1b1a..00000000 --- a/example/disasm/file.py +++ /dev/null @@ -1,18 +0,0 @@ -import sys -from miasm2.arch.x86.disasm import dis_x86_32 -from miasm2.analysis.binary import Container -from pdb import pm - -if len(sys.argv) != 3: - print 'Example:' - print "%s samples/box_upx.exe 0x407570" % sys.argv[0] - sys.exit(0) - -addr = int(sys.argv[2], 0) -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 -asmcfg = mdis.dis_multiblock(addr) - -open('graph.dot', 'w').write(asmcfg.dot()) diff --git a/example/disasm/function.py b/example/disasm/function.py deleted file mode 100644 index 10495dbc..00000000 --- a/example/disasm/function.py +++ /dev/null @@ -1,16 +0,0 @@ -from miasm2.arch.x86.disasm import dis_x86_32 - -# 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) -asmcfg = mdis.dis_multiblock(0) - -for block in asmcfg.blocks: - print block - -open('graph.dot', 'w').write(asmcfg.dot()) diff --git a/example/expression/constant_propagation.py b/example/expression/constant_propagation.py index 0798c404..e70f8163 100644 --- a/example/expression/constant_propagation.py +++ b/example/expression/constant_propagation.py @@ -6,7 +6,6 @@ A "constant expression" is an expression based on constants or init regs. from argparse import ArgumentParser -from miasm2.arch.x86.disasm import dis_x86_32 as dis_engine from miasm2.analysis.machine import Machine from miasm2.analysis.binary import Container from miasm2.analysis.cst_propag import propagate_cst_expr @@ -27,9 +26,8 @@ args = parser.parse_args() machine = Machine("x86_32") cont = Container.from_stream(open(args.filename)) -ira, dis_engine = machine.ira, machine.dis_engine -mdis = dis_engine(cont.bin_stream) -ir_arch = ira(mdis.loc_db) +mdis = machine.dis_engine(cont.bin_stream, loc_db=cont.loc_db) +ir_arch = machine.ira(mdis.loc_db) addr = int(args.address, 0) asmcfg = mdis.dis_multiblock(addr) diff --git a/example/expression/graph_dataflow.py b/example/expression/graph_dataflow.py index 0951cc1e..92bcf249 100644 --- a/example/expression/graph_dataflow.py +++ b/example/expression/graph_dataflow.py @@ -1,10 +1,8 @@ from argparse import ArgumentParser -from pdb import pm -from pprint import pprint +from miasm2.analysis.binary import Container +from miasm2.analysis.machine import Machine from miasm2.expression.expression import get_expr_mem -from miasm2.arch.x86.ira import ir_a_x86_32 -from miasm2.arch.x86.disasm import dis_x86_32 from miasm2.analysis.data_analysis import intra_block_flow_raw, inter_block_flow from miasm2.core.graph import DiGraph from miasm2.ir.symbexec import SymbolicExecutionEngine @@ -82,7 +80,7 @@ def intra_block_flow_symb(ir_arch, _, flow_graph, irblock, in_nodes, out_nodes): flow_graph.add_uniq_edge(node_n_r, node_n_w) -def node2str(self, node): +def node2str(node): out = "%s,%s\\l\\\n%s" % node return out @@ -101,9 +99,9 @@ def gen_block_data_flow_graph(ir_arch, ircfg, ad, block_flow_cb): if offset == ad: irblock_0 = irblock break - assert(irblock_0 is not None) + assert irblock_0 is not None flow_graph = DiGraph() - flow_graph.node2str = lambda n: node2str(flow_graph, n) + flow_graph.node2str = node2str irb_in_nodes = {} @@ -128,19 +126,21 @@ def gen_block_data_flow_graph(ir_arch, ircfg, ad, block_flow_cb): open('data.dot', 'w').write(flow_graph.dot()) -data = open(args.filename).read() ad = int(args.addr, 16) print 'disasm...' -mdis = dis_x86_32(data) +cont = Container.from_stream(open(args.filename)) +machine = Machine("x86_32") + +mdis = machine.dis_engine(cont.bin_stream, loc_db=cont.loc_db) mdis.follow_call = True asmcfg = mdis.dis_multiblock(ad) print 'ok' print 'generating dataflow graph for:' -ir_arch = ir_a_x86_32(mdis.loc_db) -ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg) +ir_arch_analysis = machine.ira(mdis.loc_db) +ircfg = ir_arch_analysis.new_ircfg_from_asmcfg(asmcfg) for irblock in ircfg.blocks.values(): print irblock @@ -151,7 +151,7 @@ if args.symb: else: block_flow_cb = intra_block_flow_raw -gen_block_data_flow_graph(ir_arch, ircfg, ad, block_flow_cb) +gen_block_data_flow_graph(ir_arch_analysis, ircfg, ad, block_flow_cb) print '*' * 40 print """ diff --git a/example/expression/solve_condition_stp.py b/example/expression/solve_condition_stp.py index 6962e2ef..c79dd0b8 100644 --- a/example/expression/solve_condition_stp.py +++ b/example/expression/solve_condition_stp.py @@ -4,13 +4,13 @@ from optparse import OptionParser from pdb import pm from miasm2.analysis.machine import Machine +from miasm2.analysis.binary import Container from miasm2.expression.expression import ExprInt, ExprCond, ExprId, \ get_expr_ids, ExprAssign, ExprLoc from miasm2.core.bin_stream import bin_stream_str from miasm2.ir.symbexec import SymbolicExecutionEngine, get_block from miasm2.expression.simplifications import expr_simp from miasm2.core import parse_asm -from miasm2.arch.x86.disasm import dis_x86_32 as dis_engine from miasm2.ir.translators.translator import Translator machine = Machine("x86_32") @@ -78,14 +78,11 @@ def emul_symb(ir_arch, ircfg, mdis, states_todo, states_done): if __name__ == '__main__': translator_smt2 = Translator.to_language("smt2") - data = open(args[0]).read() - bs = bin_stream_str(data) - - mdis = dis_engine(bs) addr = int(options.address, 16) - + cont = Container.from_stream(open(args[0])) + mdis = machine.dis_engine(cont.bin_stream, loc_db=cont.loc_db) ir_arch = machine.ir(mdis.loc_db) ircfg = ir_arch.new_ircfg() symbexec = SymbolicExecutionEngine(ir_arch) diff --git a/example/samples/test_x86_32_dis.S b/example/samples/test_x86_32_dis.S new file mode 100644 index 00000000..d2e77bf9 --- /dev/null +++ b/example/samples/test_x86_32_dis.S @@ -0,0 +1,12 @@ +main: + CMP EAX, 0x10 + JZ lbl2 + MOV ESI, EAX + CMOVA EAX, EBX + JMP end +lbl2: + MOV EAX, ECX + CALL 0x11223344 + INC EAX +end: + RET diff --git a/example/symbol_exec/single_instr.py b/example/symbol_exec/single_instr.py index c78f1f7f..2de2a72e 100644 --- a/example/symbol_exec/single_instr.py +++ b/example/symbol_exec/single_instr.py @@ -1,7 +1,7 @@ # Minimalist Symbol Exec example -from miasm2.core.bin_stream import bin_stream_str -from miasm2.ir.symbexec import SymbolicExecutionEngine +from miasm2.analysis.binary import Container from miasm2.analysis.machine import Machine +from miasm2.ir.symbexec import SymbolicExecutionEngine from miasm2.core.locationdb import LocationDB START_ADDR = 0 @@ -14,8 +14,8 @@ line = machine.mn.fromstring("MOV EAX, EBX", loc_db, 32) asm = machine.mn.asm(line)[0] # Get back block -bin_stream = bin_stream_str(asm) -mdis = machine.dis_engine(bin_stream, loc_db=loc_db) +cont = Container.from_string(asm, loc_db = loc_db) +mdis = machine.dis_engine(cont.bin_stream, loc_db=loc_db) mdis.lines_wd = 1 asm_block = mdis.dis_block(START_ADDR) diff --git a/test/core/asmblock.py b/test/core/asmblock.py index cd1d262a..c3e1d11d 100644 --- a/test/core/asmblock.py +++ b/test/core/asmblock.py @@ -1,6 +1,6 @@ from pdb import pm -from miasm2.arch.x86.disasm import dis_x86_32 +from miasm2.analysis.machine import Machine from miasm2.analysis.binary import Container from miasm2.core.asmblock import AsmCFG, AsmConstraint, AsmBlock, \ AsmBlockBad, AsmConstraintTo, AsmConstraintNext, \ @@ -13,7 +13,8 @@ data = "5589e583ec10837d08007509c745fc01100000eb73837d08017709c745fc02100000eb64 cont = Container.from_string(data) # Test Disasm engine -mdis = dis_x86_32(cont.bin_stream) +machine = Machine("x86_32") +mdis = machine.dis_engine(cont.bin_stream, loc_db=cont.loc_db) ## Disassembly of one block first_block = mdis.dis_block(0) assert len(first_block.lines) == 5 @@ -215,7 +216,7 @@ asmcfg.sanity_check() # Test block_merge data2 = "31c0eb0c31c9750c31d2eb0c31ffebf831dbebf031edebfc31f6ebf031e4c3".decode("hex") cont2 = Container.from_string(data2) -mdis = dis_x86_32(cont2.bin_stream) +mdis = machine.dis_engine(cont2.bin_stream, loc_db=cont2.loc_db) ## Elements to merge asmcfg = mdis.dis_multiblock(0) ## Block alone @@ -301,7 +302,7 @@ assert asmcfg.edges2constraint[(tob.loc_key, lbl_newb)] == AsmConstraint.c_to # Check double block split data = "74097405b8020000007405b803000000b804000000c3".decode('hex') cont = Container.from_string(data) -mdis = dis_x86_32(cont.bin_stream) +mdis = machine.dis_engine(cont.bin_stream, loc_db=cont.loc_db) asmcfg = mdis.dis_multiblock(0) ## Check resulting disasm assert len(asmcfg.nodes()) == 6 diff --git a/test/test_all.py b/test/test_all.py index 42843e90..459d529e 100755 --- a/test/test_all.py +++ b/test/test_all.py @@ -538,6 +538,11 @@ test_x86_32_if_reg = ExampleShellcode(['x86_32', 'x86_32_if_reg.S', "x86_32_if_r test_x86_32_seh = ExampleShellcode(["x86_32", "x86_32_seh.S", "x86_32_seh.bin", "--PE"]) test_x86_32_dead = ExampleShellcode(['x86_32', 'x86_32_dead.S', "x86_32_dead.bin"]) +test_x86_32_dis = ExampleShellcode( + [ + "x86_32", "test_x86_32_dis.S", "test_x86_32_dis.bin", "--PE" + ] +) test_human = ExampleShellcode(["x86_64", "human.S", "human.bin"]) @@ -557,6 +562,7 @@ testset += test_x86_32_if_reg testset += test_x86_32_seh testset += test_x86_32_dead testset += test_human +testset += test_x86_32_dis class ExampleDisassembler(Example): """Disassembler examples specificities: @@ -565,15 +571,20 @@ class ExampleDisassembler(Example): example_dir = "disasm" -for script, prods in [(["single_instr.py"], []), - (["callback.py"], []), - (["function.py"], ["graph.dot"]), - (["file.py", Example.get_sample("box_upx.exe"), - "0x407570"], ["graph.dot"]), - (["full.py", Example.get_sample("box_upx.exe")], - ["graph_execflow.dot", "lines.dot"]), - ]: - testset += ExampleDisassembler(script, products=prods) +for script, prods, depends in [ + (["single_instr.py"], [], []), + (["callback.py"], [], []), + (["dis_x86_string.py"], ["str_cfg.dot"], []), + (["dis_binary.py", Example.get_sample("test_x86_32_dis.bin"), + ], ["bin_cfg.dot"], [test_x86_32_dis]), + (["dis_binary_ir.py", Example.get_sample("test_x86_32_dis.bin"), + ], ["bin_ir_cfg.dot"], [test_x86_32_dis]), + (["dis_binary_ira.py", Example.get_sample("test_x86_32_dis.bin"), + ], ["bin_ira_cfg.dot"], [test_x86_32_dis]), + (["full.py", Example.get_sample("box_upx.exe")], + ["graph_execflow.dot", "lines.dot"], []), +]: + testset += ExampleDisassembler(script, products=prods, depends=depends) class ExampleDisasmFull(ExampleDisassembler): |