def gen_block_data_flow_graph(ir_arch, ad, block_flow_cb): for irblock in ir_arch.blocks.values(): print irblock dead_simp(ir_arch) irblock_0 = None for irblock in ir_arch.blocks.values(): if irblock.label.offset == ad: irblock_0 = irblock break assert(irblock_0 is not None) flow_graph = DiGraph() flow_graph.node2str = lambda n: node2str(flow_graph, n) for irblock in ir_arch.blocks.values(): block_flow_cb(ir_arch, flow_graph, irblock) for irblock in ir_arch.blocks.values(): print irblock print 'IN', [str(x) for x in irblock.in_nodes] print 'OUT', [str(x) for x in irblock.out_nodes] print '*' * 20, 'interblock', '*' * 20 inter_bloc_flow(ir_arch, flow_graph, irblock_0.label) # from graph_qt import graph_qt # graph_qt(flow_graph) open('data.dot', 'w').write(flow_graph.dot())
def gen_block_data_flow_graph(ir_arch, ad, block_flow_cb): for irblock in ir_arch.blocks.values(): print irblock dead_simp(ir_arch) irblock_0 = None for irblock in ir_arch.blocks.values(): if irblock.label.offset == ad: irblock_0 = irblock break assert (irblock_0 is not None) flow_graph = DiGraph() flow_graph.node2str = lambda n: node2str(flow_graph, n) for irblock in ir_arch.blocks.values(): block_flow_cb(ir_arch, flow_graph, irblock) for irblock in ir_arch.blocks.values(): print irblock print 'IN', [str(x) for x in irblock.in_nodes] print 'OUT', [str(x) for x in irblock.out_nodes] print '*' * 20, 'interblock', '*' * 20 inter_bloc_flow(ir_arch, flow_graph, irblock_0.label) # from graph_qt import graph_qt # graph_qt(flow_graph) open('data.dot', 'w').write(flow_graph.dot())
def gen_block_data_flow_graph(ir_arch, ad, block_flow_cb): for irblock in ir_arch.blocks.values(): print irblock dead_simp(ir_arch) irblock_0 = None for irblock in ir_arch.blocks.values(): loc_key = irblock.loc_key offset = ir_arch.loc_db.get_location_offset(loc_key) if offset == ad: irblock_0 = irblock break assert (irblock_0 is not None) flow_graph = DiGraph() flow_graph.node2str = lambda n: node2str(flow_graph, n) irb_in_nodes = {} irb_out_nodes = {} for label in ir_arch.blocks: irb_in_nodes[label] = {} irb_out_nodes[label] = {} for label, irblock in ir_arch.blocks.iteritems(): block_flow_cb(ir_arch, flow_graph, irblock, irb_in_nodes[label], irb_out_nodes[label]) for label in ir_arch.blocks: print label print 'IN', [str(x) for x in irb_in_nodes[label]] print 'OUT', [str(x) for x in irb_out_nodes[label]] print '*' * 20, 'interblock', '*' * 20 inter_block_flow(ir_arch, flow_graph, irblock_0.loc_key, irb_in_nodes, irb_out_nodes) # from graph_qt import graph_qt # graph_qt(flow_graph) open('data.dot', 'w').write(flow_graph.dot())
def gen_block_data_flow_graph(ir_arch, ircfg, ad, block_flow_cb): for irblock in ircfg.blocks.values(): print irblock dead_simp(ir_arch, ircfg) irblock_0 = None for irblock in ircfg.blocks.values(): loc_key = irblock.loc_key offset = ircfg.loc_db.get_location_offset(loc_key) if offset == ad: irblock_0 = irblock break assert(irblock_0 is not None) flow_graph = DiGraph() flow_graph.node2str = lambda n: node2str(flow_graph, n) irb_in_nodes = {} irb_out_nodes = {} for label in ircfg.blocks: irb_in_nodes[label] = {} irb_out_nodes[label] = {} for label, irblock in ircfg.blocks.iteritems(): block_flow_cb(ir_arch, ircfg, flow_graph, irblock, irb_in_nodes[label], irb_out_nodes[label]) for label in ircfg.blocks: print label print 'IN', [str(x) for x in irb_in_nodes[label]] print 'OUT', [str(x) for x in irb_out_nodes[label]] print '*' * 20, 'interblock', '*' * 20 inter_block_flow(ir_arch, ircfg, flow_graph, irblock_0.loc_key, irb_in_nodes, irb_out_nodes) # from graph_qt import graph_qt # graph_qt(flow_graph) open('data.dot', 'w').write(flow_graph.dot())
def build_graph(start_addr, type_graph, simplify=False, dontmodstack=True, loadint=False, verbose=False): machine = guess_machine(addr=start_addr) dis_engine, ira = machine.dis_engine, machine.ira class IRADelModCallStack(ira): def call_effects(self, addr, instr): assignblks, extra = super(IRADelModCallStack, self).call_effects(addr, instr) if not dontmodstack: return assignblks, extra out = [] for assignblk in assignblks: dct = dict(assignblk) dct = { dst: src for (dst, src) in dct.iteritems() if dst != self.sp } out.append(AssignBlock(dct, assignblk.instr)) return out, extra if verbose: print "Arch", dis_engine fname = idc.GetInputFile() if verbose: print fname bs = bin_stream_ida() mdis = dis_engine(bs) ir_arch = IRADelModCallStack(mdis.loc_db) # populate symbols with ida names for addr, name in idautils.Names(): if name is None: continue if (mdis.loc_db.get_offset_location(addr) or mdis.loc_db.get_name_location(name)): # Symbol alias continue mdis.loc_db.add_location(name, addr) if verbose: print "start disasm" if verbose: print hex(start_addr) asmcfg = mdis.dis_multiblock(start_addr) entry_points = set([mdis.loc_db.get_offset_location(start_addr)]) if verbose: print "generating graph" open('asm_flow.dot', 'w').write(asmcfg.dot()) print "generating IR... %x" % start_addr ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg) if verbose: print "IR ok... %x" % start_addr for irb in ircfg.blocks.itervalues(): irs = [] for assignblk in irb: new_assignblk = { expr_simp(dst): expr_simp(src) for dst, src in assignblk.iteritems() } irs.append(AssignBlock(new_assignblk, instr=assignblk.instr)) ircfg.blocks[irb.loc_key] = IRBlock(irb.loc_key, irs) if verbose: out = ircfg.dot() open(os.path.join(tempfile.gettempdir(), 'graph.dot'), 'wb').write(out) title = "Miasm IR graph" if simplify: dead_simp(ir_arch, ircfg) ircfg.simplify(expr_simp) modified = True while modified: modified = False modified |= dead_simp(ir_arch, ircfg) modified |= remove_empty_assignblks(ircfg) modified |= merge_blocks(ircfg, entry_points) title += " (simplified)" if type_graph == TYPE_GRAPH_IR: graph = GraphMiasmIR(ircfg, title, None) graph.Show() return head = list(entry_points)[0] class IRAOutRegs(ira): def get_out_regs(self, block): regs_todo = super(IRAOutRegs, self).get_out_regs(block) out = {} for assignblk in block: for dst in assignblk: reg = self.ssa_var.get(dst, None) if reg is None: continue if reg in regs_todo: out[reg] = dst return set(out.values()) # Add dummy dependency to uncover out regs affectation for loc in ircfg.leaves(): irblock = ircfg.blocks.get(loc) if irblock is None: continue regs = {} for reg in ir_arch.get_out_regs(irblock): regs[reg] = reg assignblks = list(irblock) new_assiblk = AssignBlock(regs, assignblks[-1].instr) assignblks.append(new_assiblk) new_irblock = IRBlock(irblock.loc_key, assignblks) ircfg.blocks[loc] = new_irblock ir_arch = IRAOutRegs(mdis.loc_db) ir_arch.ssa_var = {} modified = True ssa_forbidden_regs = set( [ir_arch.pc, ir_arch.IRDst, ir_arch.arch.regs.exception_flags]) head = list(entry_points)[0] heads = set([head]) all_ssa_vars = {} propagate_expr = PropagateExpr() ssa = SSADiGraph(ircfg) ssa.immutable_ids.update(ssa_forbidden_regs) ssa.ssa_variable_to_expr.update(all_ssa_vars) ssa.transform(head) all_ssa_vars.update(ssa.ssa_variable_to_expr) ir_arch.ssa_var.update(ssa.ssa_variable_to_expr) if simplify: while modified: ssa = SSADiGraph(ircfg) ssa.immutable_ids.update(ssa_forbidden_regs) ssa.ssa_variable_to_expr.update(all_ssa_vars) ssa.transform(head) all_ssa_vars.update(ssa.ssa_variable_to_expr) ir_arch.ssa_var.update(ssa.ssa_variable_to_expr) while modified: modified = False modified |= propagate_expr.propagate(ssa, head) modified |= ircfg.simplify(expr_simp) simp_modified = True while simp_modified: simp_modified = False simp_modified |= dead_simp(ir_arch, ircfg) simp_modified |= remove_empty_assignblks(ircfg) simp_modified |= load_from_int(ircfg, bs, is_addr_ro_variable) modified |= simp_modified ssa = SSADiGraph(ircfg) ssa.immutable_ids.update(ssa_forbidden_regs) ssa.ssa_variable_to_expr.update(all_ssa_vars) ssa.transform(head) all_ssa_vars.update(ssa.ssa_variable_to_expr) if type_graph == TYPE_GRAPH_IRSSA: graph = GraphMiasmIR(ssa.graph, title, None) graph.Show() return if type_graph == TYPE_GRAPH_IRSSAUNSSA: cfg_liveness = DiGraphLivenessSSA(ssa.graph) cfg_liveness.init_var_info(ir_arch) cfg_liveness.compute_liveness() UnSSADiGraph(ssa, head, cfg_liveness) if simplify: modified = True while modified: modified = False modified |= ssa.graph.simplify(expr_simp) simp_modified = True while simp_modified: simp_modified = False simp_modified |= dead_simp(ir_arch, ssa.graph) simp_modified |= remove_empty_assignblks(ssa.graph) simp_modified |= merge_blocks(ssa.graph, heads) modified |= simp_modified graph = GraphMiasmIR(ssa.graph, title, None) graph.Show()
ir_arch.add_asmblock_to_ircfg(block, ircfg) ir_arch_a.add_asmblock_to_ircfg(block, ircfg_a) log.info("Print blocks (without analyse)") for label, block in ir_arch.blocks.iteritems(): print block log.info("Gen Graph... %x" % ad) log.info("Print blocks (with analyse)") for label, block in ir_arch_a.blocks.iteritems(): print block if args.simplify > 0: log.info("dead simp...") dead_simp(ir_arch_a, ircfg_a) log.info("ok...") if args.defuse: reachings = ReachingDefinitions(ircfg_a) open('graph_defuse.dot', 'w').write(DiGraphDefUse(reachings).dot()) out = ircfg.dot() open('graph_irflow_raw.dot', 'w').write(out) out = ircfg_a.dot() open('graph_irflow.dot', 'w').write(out) if args.simplify > 1: ircfg_a.simplify(expr_simp) modified = True
ir_arch_a = ira(mdis.symbol_pool) ir_arch.blocks = {} ir_arch_a.blocks = {} for ad, all_block in all_funcs_blocks.items(): log.info("generating IR... %x" % ad) for block in all_block: ir_arch_a.add_bloc(block) ir_arch.add_bloc(block) log.info("Print blocks (without analyse)") for label, block in ir_arch.blocks.iteritems(): print block log.info("Gen Graph... %x" % ad) log.info("Print blocks (with analyse)") for label, block in ir_arch_a.blocks.iteritems(): print block if args.simplify: dead_simp(ir_arch_a) if args.defuse: reachings = ReachingDefinitions(ir_arch_a) open('graph_defuse.dot', 'w').write(DiGraphDefUse(reachings).dot()) out = ir_arch_a.graph.dot() open('graph_irflow.dot', 'w').write(out) out = ir_arch.graph.dot() open('graph_irflow_raw.dot', 'w').write(out)
''') loc_db.set_location_offset(loc_db.get_name_location("main"), 0x0) for block in asmcfg.blocks: print block print "symbols:" print loc_db patches = asmblock.asm_resolve_final(mn_x86, asmcfg, loc_db) # Translate to IR ir_arch = ir_a_x86_32(loc_db) ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg) # Display IR for lbl, irblock in ircfg.blocks.items(): print irblock # Dead propagation open('graph.dot', 'w').write(ircfg.dot()) print '*' * 80 dead_simp(ir_arch, ircfg) open('graph2.dot', 'w').write(ircfg.dot()) # Display new IR print 'new ir blocks' for lbl, irblock in ircfg.blocks.items(): print irblock
for block in all_block: ir_arch_a.add_bloc(block) ir_arch.add_bloc(block) log.info("Print blocks (without analyse)") for label, block in ir_arch.blocks.iteritems(): print block log.info("Gen Graph... %x" % ad) log.info("Print blocks (with analyse)") for label, block in ir_arch_a.blocks.iteritems(): print block if args.simplify > 0: dead_simp(ir_arch_a) if args.defuse: reachings = ReachingDefinitions(ir_arch_a) open('graph_defuse.dot', 'w').write(DiGraphDefUse(reachings).dot()) out = ir_arch_a.graph.dot() open('graph_irflow.dot', 'w').write(out) out = ir_arch.graph.dot() open('graph_irflow_raw.dot', 'w').write(out) if args.simplify > 1: ir_arch_a.simplify(expr_simp) modified = True while modified: modified = False
symbol_pool.set_offset(symbol_pool.getby_name("main"), 0x0) for block in asmcfg.blocks: print block print "symbols:" print symbol_pool patches = asmblock.asm_resolve_final(mn_x86, asmcfg, symbol_pool) # Translate to IR ir_arch = ir_a_x86_32(symbol_pool) for block in asmcfg.blocks: print 'add block' print block ir_arch.add_block(block) # Display IR for lbl, irblock in ir_arch.blocks.items(): print irblock # Dead propagation open('graph.dot', 'w').write(ir_arch.graph.dot()) print '*' * 80 dead_simp(ir_arch) open('graph2.dot', 'w').write(ir_arch.graph.dot()) # Display new IR print 'new ir blocks' for lbl, irblock in ir_arch.blocks.items(): print irblock
action="store_true", help="Apply simplifications rules (liveness, graph simplification, ...)") 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) addr = int(args.address, 0) asmcfg = mdis.dis_multiblock(addr) ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg) entry_points = set([mdis.loc_db.get_offset_location(addr)]) init_infos = ir_arch.arch.regs.regs_init cst_propag_link = propagate_cst_expr(ir_arch, ircfg, addr, init_infos) if args.simplify: ircfg.simplify(expr_simp) modified = True while modified: modified = False modified |= dead_simp(ir_arch, ircfg) modified |= remove_empty_assignblks(ircfg) modified |= merge_blocks(ircfg, entry_points) open("%s.propag.dot" % args.filename, 'w').write(ircfg.dot())
def build_graph(verbose=False, simplify=False, ssa=False, ssa_simplify=False): start_addr = idc.ScreenEA() machine = guess_machine(addr=start_addr) dis_engine, ira = machine.dis_engine, machine.ira if verbose: print "Arch", dis_engine fname = idc.GetInputFile() if verbose: print fname bs = bin_stream_ida() mdis = dis_engine(bs) ir_arch = ira(mdis.loc_db) # populate symbols with ida names for addr, name in idautils.Names(): if name is None: continue if (mdis.loc_db.get_offset_location(addr) or mdis.loc_db.get_name_location(name)): # Symbol alias continue mdis.loc_db.add_location(name, addr) if verbose: print "start disasm" if verbose: print hex(addr) asmcfg = mdis.dis_multiblock(start_addr) entry_points = set([mdis.loc_db.get_offset_location(start_addr)]) if verbose: print "generating graph" open('asm_flow.dot', 'w').write(asmcfg.dot()) print "generating IR... %x" % start_addr ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg) if verbose: print "IR ok... %x" % start_addr for irb in ircfg.blocks.itervalues(): irs = [] for assignblk in irb: new_assignblk = { expr_simp(dst): expr_simp(src) for dst, src in assignblk.iteritems() } irs.append(AssignBlock(new_assignblk, instr=assignblk.instr)) ircfg.blocks[irb.loc_key] = IRBlock(irb.loc_key, irs) if verbose: out = ircfg.dot() open(os.path.join(tempfile.gettempdir(), 'graph.dot'), 'wb').write(out) title = "Miasm IR graph" if simplify: dead_simp(ir_arch, ircfg) ircfg.simplify(expr_simp) modified = True while modified: modified = False modified |= dead_simp(ir_arch, ircfg) modified |= remove_empty_assignblks(ircfg) modified |= merge_blocks(ircfg, entry_points) title += " (simplified)" graph = GraphMiasmIR(ircfg, title, None) if ssa: if len(entry_points) != 1: raise RuntimeError("Your graph should have only one head") head = list(entry_points)[0] ssa = SSADiGraph(ircfg) ssa.transform(head) title += " (SSA)" graph = GraphMiasmIR(ssa.graph, title, None) if ssa_simplify: class IRAOutRegs(ira): def get_out_regs(self, block): regs_todo = super(self.__class__, self).get_out_regs(block) out = {} for assignblk in block: for dst in assignblk: reg = self.ssa_var.get(dst, None) if reg is None: continue if reg in regs_todo: out[reg] = dst return set(out.values()) # Add dummy dependecy to uncover out regs affectation for loc in ircfg.leaves(): irblock = ircfg.blocks.get(loc) if irblock is None: continue regs = {} for reg in ir_arch.get_out_regs(irblock): regs[reg] = reg assignblks = list(irblock) new_assiblk = AssignBlock(regs, assignblks[-1].instr) assignblks.append(new_assiblk) new_irblock = IRBlock(irblock.loc_key, assignblks) ircfg.blocks[loc] = new_irblock ir_arch = IRAOutRegs(mdis.loc_db) def is_addr_ro_variable(bs, addr, size): """ Return True if address at @addr is a read-only variable. WARNING: Quick & Dirty @addr: integer representing the address of the variable @size: size in bits """ try: _ = bs.getbytes(addr, size/8) except IOError: return False return True ir_arch.ssa_var = {} index = 0 modified = True ssa_forbidden_regs = set([ ir_arch.pc, ir_arch.IRDst, ir_arch.arch.regs.exception_flags ]) head = list(entry_points)[0] heads = set([head]) all_ssa_vars = set() propagate_expr = PropagateExpr() while modified: ssa = SSADiGraph(ircfg) ssa.immutable_ids.update(ssa_forbidden_regs) ssa.transform(head) all_ssa_vars.update(ssa._ssa_variable_to_expr) ssa_regs = [reg for reg in ssa.expressions if reg.is_id()] ssa_forbidden_regs.update(ssa_regs) ir_arch.ssa_var.update(ssa._ssa_variable_to_expr) while modified: index += 1 modified = False modified |= propagate_expr.propagate(ssa, head) modified |= ircfg.simplify(expr_simp) simp_modified = True while simp_modified: index += 1 simp_modified = False simp_modified |= dead_simp(ir_arch, ircfg) index += 1 simp_modified |= remove_empty_assignblks(ircfg) simp_modified |= merge_blocks(ircfg, heads) simp_modified |= load_from_int(ircfg, bs, is_addr_ro_variable) modified |= simp_modified index += 1 merge_blocks(ircfg, heads) ssa = SSADiGraph(ircfg) ssa.immutable_ids.update(ssa_forbidden_regs) ssa.transform(head) all_ssa_vars.update(ssa._ssa_variable_to_expr) ssa._ssa_variable_to_expr = all_ssa_vars dead_simp(ir_arch, ssa.graph) title += " (SSA Simplified)" graph = GraphMiasmIR(ssa.graph, title, None) graph.Show()
for block in asmcfg.blocks: ir_arch.add_asmblock_to_ircfg(block, ircfg) ir_arch_a.add_asmblock_to_ircfg(block, ircfg_a) log.info("Print blocks (without analyse)") for label, block in ir_arch.blocks.iteritems(): print block log.info("Gen Graph... %x" % ad) log.info("Print blocks (with analyse)") for label, block in ir_arch_a.blocks.iteritems(): print block if args.simplify > 0: dead_simp(ir_arch_a, ircfg_a) if args.defuse: reachings = ReachingDefinitions(ircfg_a) open('graph_defuse.dot', 'w').write(DiGraphDefUse(reachings).dot()) out = ircfg.dot() open('graph_irflow_raw.dot', 'w').write(out) out = ircfg_a.dot() open('graph_irflow.dot', 'w').write(out) if args.simplify > 1: ircfg_a.simplify(expr_simp) modified = True while modified:
help="Apply simplifications rules (liveness, graph simplification, ...)") 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) addr = int(args.address, 0) asmcfg = mdis.dis_multiblock(addr) for block in asmcfg.blocks: ir_arch.add_block(block) init_infos = ir_arch.arch.regs.regs_init cst_propag_link = propagate_cst_expr(ir_arch, addr, init_infos) if args.simplify: ir_arch.simplify(expr_simp) modified = True while modified: modified = False modified |= dead_simp(ir_arch) modified |= ir_arch.remove_empty_assignblks() modified |= ir_arch.remove_jmp_blocks() modified |= ir_arch.merge_blocks() open("%s.propag.dot" % args.filename, 'w').write(ir_arch.graph.dot())
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.symbol_pool) addr = int(args.address, 0) asmcfg = mdis.dis_multiblock(addr) for block in asmcfg.blocks: ir_arch.add_block(block) init_infos = ir_arch.arch.regs.regs_init cst_propag_link = propagate_cst_expr(ir_arch, addr, init_infos) if args.simplify: ir_arch.simplify(expr_simp) modified = True while modified: modified = False modified |= dead_simp(ir_arch) modified |= ir_arch.remove_empty_assignblks() modified |= ir_arch.remove_jmp_blocks() modified |= ir_arch.merge_blocks() open("%s.propag.dot" % args.filename, 'w').write(ir_arch.graph.dot())
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) addr = int(args.address, 0) asmcfg = mdis.dis_multiblock(addr) ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg) entry_points = set([mdis.loc_db.get_offset_location(addr)]) init_infos = ir_arch.arch.regs.regs_init cst_propag_link = propagate_cst_expr(ir_arch, ircfg, addr, init_infos) if args.simplify: ircfg.simplify(expr_simp) modified = True while modified: modified = False modified |= dead_simp(ir_arch, ircfg) modified |= remove_empty_assignblks(ircfg) modified |= merge_blocks(ircfg, entry_points) open("%s.propag.dot" % args.filename, 'w').write(ircfg.dot())
def build_graph(verbose=False, simplify=False): machine = guess_machine() mn, dis_engine, ira = machine.mn, machine.dis_engine, machine.ira if verbose: print "Arch", dis_engine fname = idc.GetInputFile() if verbose: print fname bs = bin_stream_ida() mdis = dis_engine(bs) ir_arch = ira(mdis.symbol_pool) # populate symbols with ida names for addr, name in idautils.Names(): # print hex(ad), repr(name) if name is None: continue if (mdis.symbol_pool.getby_offset(addr) or mdis.symbol_pool.getby_name(name)): # Symbol alias continue mdis.symbol_pool.add_location(name, addr) if verbose: print "start disasm" addr = idc.ScreenEA() if verbose: print hex(addr) asmcfg = mdis.dis_multiblock(addr) if verbose: print "generating graph" open('asm_flow.dot', 'w').write(asmcfg.dot()) print "generating IR... %x" % addr for block in asmcfg.blocks: if verbose: print 'ADD' print block ir_arch.add_block(block) if verbose: print "IR ok... %x" % addr for irb in ir_arch.blocks.itervalues(): irs = [] for assignblk in irb: new_assignblk = { expr_simp(dst): expr_simp(src) for dst, src in assignblk.iteritems() } irs.append(AssignBlock(new_assignblk, instr=assignblk.instr)) ir_arch.blocks[irb.loc_key] = IRBlock(irb.loc_key, irs) if verbose: out = ir_arch.graph.dot() open(os.path.join(tempfile.gettempdir(), 'graph.dot'), 'wb').write(out) title = "Miasm IR graph" if simplify: dead_simp(ir_arch) ir_arch.simplify(expr_simp) modified = True while modified: modified = False modified |= dead_simp(ir_arch) modified |= ir_arch.remove_empty_assignblks() modified |= ir_arch.remove_jmp_blocks() modified |= ir_arch.merge_blocks() title += " (simplified)" g = GraphMiasmIR(ir_arch, title, None) g.Show()
JZ loop RET ''') loc_db.set_location_offset(loc_db.get_name_location("main"), 0x0) for block in asmcfg.blocks: print block print "symbols:" print loc_db patches = asmblock.asm_resolve_final(mn_x86, asmcfg, loc_db) # Translate to IR ir_arch = ir_a_x86_32(loc_db) ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg) # Display IR for lbl, irblock in ircfg.blocks.items(): print irblock # Dead propagation open('graph.dot', 'w').write(ircfg.dot()) print '*' * 80 dead_simp(ir_arch, ircfg) open('graph2.dot', 'w').write(ircfg.dot()) # Display new IR print 'new ir blocks' for lbl, irblock in ircfg.blocks.items(): print irblock
def build_graph(verbose=False, simplify=False): start_addr = idc.ScreenEA() machine = guess_machine(addr=start_addr) dis_engine, ira = machine.dis_engine, machine.ira if verbose: print "Arch", dis_engine fname = idc.GetInputFile() if verbose: print fname bs = bin_stream_ida() mdis = dis_engine(bs) ir_arch = ira(mdis.loc_db) # populate symbols with ida names for addr, name in idautils.Names(): if name is None: continue if (mdis.loc_db.get_offset_location(addr) or mdis.loc_db.get_name_location(name)): # Symbol alias continue mdis.loc_db.add_location(name, addr) if verbose: print "start disasm" if verbose: print hex(addr) asmcfg = mdis.dis_multiblock(start_addr) entry_points = set([start_addr]) if verbose: print "generating graph" open('asm_flow.dot', 'w').write(asmcfg.dot()) print "generating IR... %x" % start_addr ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg) if verbose: print "IR ok... %x" % start_addr for irb in ircfg.blocks.itervalues(): irs = [] for assignblk in irb: new_assignblk = { expr_simp(dst): expr_simp(src) for dst, src in assignblk.iteritems() } irs.append(AssignBlock(new_assignblk, instr=assignblk.instr)) ircfg.blocks[irb.loc_key] = IRBlock(irb.loc_key, irs) if verbose: out = ircfg.dot() open(os.path.join(tempfile.gettempdir(), 'graph.dot'), 'wb').write(out) title = "Miasm IR graph" if simplify: dead_simp(ir_arch, ircfg) ircfg.simplify(expr_simp) modified = True while modified: modified = False modified |= dead_simp(ir_arch, ircfg) modified |= remove_empty_assignblks(ircfg) modified |= merge_blocks(ircfg, entry_points) title += " (simplified)" graph = GraphMiasmIR(ircfg, title, None) graph.Show()
def build_graph(verbose=False, simplify=False, ssa=False, ssa_simplify=False): start_addr = idc.ScreenEA() machine = guess_machine(addr=start_addr) dis_engine, ira = machine.dis_engine, machine.ira if verbose: print "Arch", dis_engine fname = idc.GetInputFile() if verbose: print fname bs = bin_stream_ida() mdis = dis_engine(bs) ir_arch = ira(mdis.loc_db) # populate symbols with ida names for addr, name in idautils.Names(): if name is None: continue if (mdis.loc_db.get_offset_location(addr) or mdis.loc_db.get_name_location(name)): # Symbol alias continue mdis.loc_db.add_location(name, addr) if verbose: print "start disasm" if verbose: print hex(addr) asmcfg = mdis.dis_multiblock(start_addr) entry_points = set([mdis.loc_db.get_offset_location(start_addr)]) if verbose: print "generating graph" open('asm_flow.dot', 'w').write(asmcfg.dot()) print "generating IR... %x" % start_addr ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg) if verbose: print "IR ok... %x" % start_addr for irb in ircfg.blocks.itervalues(): irs = [] for assignblk in irb: new_assignblk = { expr_simp(dst): expr_simp(src) for dst, src in assignblk.iteritems() } irs.append(AssignBlock(new_assignblk, instr=assignblk.instr)) ircfg.blocks[irb.loc_key] = IRBlock(irb.loc_key, irs) if verbose: out = ircfg.dot() open(os.path.join(tempfile.gettempdir(), 'graph.dot'), 'wb').write(out) title = "Miasm IR graph" if simplify: dead_simp(ir_arch, ircfg) ircfg.simplify(expr_simp) modified = True while modified: modified = False modified |= dead_simp(ir_arch, ircfg) modified |= remove_empty_assignblks(ircfg) modified |= merge_blocks(ircfg, entry_points) title += " (simplified)" graph = GraphMiasmIR(ircfg, title, None) if ssa: if len(entry_points) != 1: raise RuntimeError("Your graph should have only one head") head = list(entry_points)[0] ssa = SSADiGraph(ircfg) ssa.transform(head) title += " (SSA)" graph = GraphMiasmIR(ssa.graph, title, None) if ssa_simplify: class IRAOutRegs(ira): def get_out_regs(self, block): regs_todo = super(self.__class__, self).get_out_regs(block) out = {} for assignblk in block: for dst in assignblk: reg = self.ssa_var.get(dst, None) if reg is None: continue if reg in regs_todo: out[reg] = dst return set(out.values()) # Add dummy dependency to uncover out regs affectation for loc in ircfg.leaves(): irblock = ircfg.blocks.get(loc) if irblock is None: continue regs = {} for reg in ir_arch.get_out_regs(irblock): regs[reg] = reg assignblks = list(irblock) new_assiblk = AssignBlock(regs, assignblks[-1].instr) assignblks.append(new_assiblk) new_irblock = IRBlock(irblock.loc_key, assignblks) ircfg.blocks[loc] = new_irblock ir_arch = IRAOutRegs(mdis.loc_db) def is_addr_ro_variable(bs, addr, size): """ Return True if address at @addr is a read-only variable. WARNING: Quick & Dirty @addr: integer representing the address of the variable @size: size in bits """ try: _ = bs.getbytes(addr, size / 8) except IOError: return False return True ir_arch.ssa_var = {} index = 0 modified = True ssa_forbidden_regs = set( [ir_arch.pc, ir_arch.IRDst, ir_arch.arch.regs.exception_flags]) head = list(entry_points)[0] heads = set([head]) all_ssa_vars = set() propagate_expr = PropagateExpr() while modified: ssa = SSADiGraph(ircfg) ssa.immutable_ids.update(ssa_forbidden_regs) ssa.transform(head) all_ssa_vars.update(ssa._ssa_variable_to_expr) ssa_regs = [reg for reg in ssa.expressions if reg.is_id()] ssa_forbidden_regs.update(ssa_regs) ir_arch.ssa_var.update(ssa._ssa_variable_to_expr) while modified: index += 1 modified = False modified |= propagate_expr.propagate(ssa, head) modified |= ircfg.simplify(expr_simp) simp_modified = True while simp_modified: index += 1 simp_modified = False simp_modified |= dead_simp(ir_arch, ircfg) index += 1 simp_modified |= remove_empty_assignblks(ircfg) simp_modified |= merge_blocks(ircfg, heads) simp_modified |= load_from_int(ircfg, bs, is_addr_ro_variable) modified |= simp_modified index += 1 merge_blocks(ircfg, heads) ssa = SSADiGraph(ircfg) ssa.immutable_ids.update(ssa_forbidden_regs) ssa.transform(head) all_ssa_vars.update(ssa._ssa_variable_to_expr) ssa._ssa_variable_to_expr = all_ssa_vars dead_simp(ir_arch, ssa.graph) title += " (SSA Simplified)" graph = GraphMiasmIR(ssa.graph, title, None) graph.Show()
for block in all_block: ir_arch_a.add_bloc(block) ir_arch.add_bloc(block) log.info("Print blocks (without analyse)") for label, block in ir_arch.blocks.iteritems(): print block log.info("Gen Graph... %x" % ad) log.info("Print blocks (with analyse)") for label, block in ir_arch_a.blocks.iteritems(): print block if args.simplify > 0: dead_simp(ir_arch_a) if args.defuse: reachings = ReachingDefinitions(ir_arch_a) open('graph_defuse.dot', 'w').write(DiGraphDefUse(reachings).dot()) out = ir_arch_a.graph.dot() open('graph_irflow.dot', 'w').write(out) out = ir_arch.graph.dot() open('graph_irflow_raw.dot', 'w').write(out) if args.simplify > 1: ir_arch_a.simplify(expr_simp) modified = True while modified: modified = False
]): open('graph_%d.dot' % test_nb, 'w').write(ircfg.dot()) # Save a copy of ircfg ircfg_orig = IRCFG(IRDst, loc_db) for irblock in ircfg.blocks.values(): ircfg_orig.add_irblock(irblock) # SSA head = LBL0 ssa = SSADiGraph(ircfg) ssa.transform(head) ir_arch_a.ssa_var = ssa.ssa_variable_to_expr dead_simp(ir_arch_a, ssa.graph) open("ssa_%d.dot" % test_nb, "wb").write(ssa.graph.dot()) # Un SSA ir_arch_a.ssa_var = ssa.ssa_variable_to_expr propagate_expr = PropagateExpr() modified = True while modified: modified = False modified |= propagate_expr.propagate(ssa, head) open('tmp_%d.dot' % test_nb, 'w').write(ssa.graph.dot())