def symbolic_exec(): from miasm2.ir.symbexec import SymbolicExecutionEngine from miasm2.core.bin_stream_ida import bin_stream_ida from utils import guess_machine bs = bin_stream_ida() machine = guess_machine() mdis = machine.dis_engine(bs) start, end = idc.SelStart(), idc.SelEnd() mdis.dont_dis = [end] asmcfg = mdis.dis_multiblock(start) ira = machine.ira(symbol_pool=mdis.symbol_pool) for block in asmcfg.blocks: ira.add_block(block) print "Run symbolic execution..." sb = SymbolicExecutionEngine(ira, machine.mn.regs.regs_init) sb.run_at(start) modified = {} for dst, src in sb.modified(init_state=machine.mn.regs.regs_init): modified[dst] = src view = symbolicexec_t() all_views.append(view) if not view.Create(modified, machine, mdis.symbol_pool, "Symbolic Execution - 0x%x to 0x%x" % (start, end)): return view.Show()
def symbolic_exec(): from miasm2.ir.symbexec import SymbolicExecutionEngine from miasm2.core.bin_stream_ida import bin_stream_ida from utils import guess_machine bs = bin_stream_ida() machine = guess_machine() mdis = machine.dis_engine(bs) start, end = idc.SelStart(), idc.SelEnd() mdis.dont_dis = [end] blocks = mdis.dis_multiblock(start) ira = machine.ira() for block in blocks: ira.add_block(block) print "Run symbolic execution..." sb = SymbolicExecutionEngine(ira, machine.mn.regs.regs_init) sb.emul_ir_blocks(start) modified = {} for ident in sb.symbols.symbols_id: if ident in sb.ir_arch.arch.regs.regs_init and \ ident in sb.symbols.symbols_id and \ sb.symbols.symbols_id[ident] == sb.ir_arch.arch.regs.regs_init[ident]: continue modified[ident] = sb.symbols.symbols_id[ident] for ident in sb.symbols.symbols_mem: modified[sb.symbols.symbols_mem[ident][0]] = sb.symbols.symbols_mem[ident][1] view = symbolicexec_t() all_views.append(view) if not view.Create(modified, machine, "Symbolic Execution - 0x%x to 0x%x" % (start, end)): return view.Show()
def symbolic_exec(): from miasm2.ir.symbexec import symbexec from miasm2.core.bin_stream_ida import bin_stream_ida from utils import guess_machine bs = bin_stream_ida() machine = guess_machine() mdis = machine.dis_engine(bs) start, end = SelStart(), SelEnd() mdis.dont_dis = [end] blocs = mdis.dis_multibloc(start) ira = machine.ira() for bloc in blocs: ira.add_bloc(bloc) print "Run symbolic execution..." sb = symbexec(ira, machine.mn.regs.regs_init) sb.emul_ir_blocks(start) modified = {} for ident in sb.symbols.symbols_id: if ident in sb.ir_arch.arch.regs.regs_init and \ ident in sb.symbols.symbols_id and \ sb.symbols.symbols_id[ident] == sb.ir_arch.arch.regs.regs_init[ident]: continue modified[ident] = sb.symbols.symbols_id[ident] for ident in sb.symbols.symbols_mem: modified[sb.symbols.symbols_mem[ident][0]] = sb.symbols.symbols_mem[ident][1] view = symbolicexec_t() if not view.Create(modified, machine, "Symbolic Execution - 0x%x to 0x%x" % (start, end)): return view.Show()
def symbolic_exec(): from miasm2.ir.symbexec import SymbolicExecutionEngine from miasm2.core.bin_stream_ida import bin_stream_ida from utils import guess_machine start, end = idc.SelStart(), idc.SelEnd() bs = bin_stream_ida() machine = guess_machine(addr=start) mdis = machine.dis_engine(bs) if start == idc.BADADDR and end == idc.BADADDR: start = idc.ScreenEA() end = idc.next_head(start) # Get next instruction address mdis.dont_dis = [end] asmcfg = mdis.dis_multiblock(start) ira = machine.ira(loc_db=mdis.loc_db) for block in asmcfg.blocks: ira.add_block(block) print "Run symbolic execution..." sb = SymbolicExecutionEngine(ira, machine.mn.regs.regs_init) sb.run_at(start) modified = {} for dst, src in sb.modified(init_state=machine.mn.regs.regs_init): modified[dst] = src view = symbolicexec_t() all_views.append(view) if not view.Create( modified, machine, mdis.loc_db, "Symbolic Execution - 0x%x to 0x%x" % (start, idc.prev_head(end))): return view.Show()
def symbolic_exec(): from miasm.ir.symbexec import SymbolicExecutionEngine from miasm.core.bin_stream_ida import bin_stream_ida from utils import guess_machine start, end = idc.read_selection_start(), idc.read_selection_end() loc_db = LocationDB() bs = bin_stream_ida() machine = guess_machine(addr=start) mdis = machine.dis_engine(bs, loc_db=loc_db) if start == idc.BADADDR and end == idc.BADADDR: start = idc.get_screen_ea() end = idc.next_head(start) # Get next instruction address mdis.dont_dis = [end] asmcfg = mdis.dis_multiblock(start) ira = machine.ira(loc_db=loc_db) ircfg = ira.new_ircfg_from_asmcfg(asmcfg) print("Run symbolic execution...") sb = SymbolicExecutionEngine(ira, machine.mn.regs.regs_init) sb.run_at(ircfg, start) modified = {} for dst, src in sb.modified(init_state=machine.mn.regs.regs_init): modified[dst] = src view = symbolicexec_t() all_views.append(view) if not view.Create( modified, machine, loc_db, "Symbolic Execution - 0x%x to 0x%x" % (start, idc.prev_head(end))): return view.Show()
def symbolic_exec(): from miasm2.ir.symbexec import SymbolicExecutionEngine from miasm2.core.bin_stream_ida import bin_stream_ida from utils import guess_machine start, end = idc.SelStart(), idc.SelEnd() bs = bin_stream_ida() machine = guess_machine(addr=start) mdis = machine.dis_engine(bs) if start == idc.BADADDR and end == idc.BADADDR: start = idc.ScreenEA() end = idc.next_head(start) # Get next instruction address mdis.dont_dis = [end] asmcfg = mdis.dis_multiblock(start) ira = machine.ira(loc_db=mdis.loc_db) ircfg = ira.new_ircfg_from_asmcfg(asmcfg) print "Run symbolic execution..." sb = SymbolicExecutionEngine(ira, machine.mn.regs.regs_init) sb.run_at(ircfg, start) modified = {} for dst, src in sb.modified(init_state=machine.mn.regs.regs_init): modified[dst] = src view = symbolicexec_t() all_views.append(view) if not view.Create(modified, machine, mdis.loc_db, "Symbolic Execution - 0x%x to 0x%x" % (start, idc.prev_head(end))): return view.Show()
def launch_depgraph(): global graphs, comments, sol_nb, settings, addr, ir_arch # Init machine = guess_machine() mn, dis_engine, ira = machine.mn, machine.dis_engine, machine.ira bs = bin_stream_ida() mdis = dis_engine(bs, dont_dis_nulstart_bloc=True) ir_arch = ira(mdis.symbol_pool) # Populate symbols with ida names for ad, name in idautils.Names(): if name is None: continue mdis.symbol_pool.add_label(name, ad) # Get the current function addr = idc.ScreenEA() func = ida_funcs.get_func(addr) blocks = mdis.dis_multiblock(func.startEA) # Generate IR for block in blocks: ir_arch.add_block(block) # Get settings settings = depGraphSettingsForm(ir_arch) settings.Execute() label, elements, line_nb = settings.label, settings.elements, settings.line_nb # Simplify affectations for irb in ir_arch.blocks.values(): irs = [] fix_stack = irb.label.offset is not None and settings.unalias_stack for assignblk in irb.irs: if fix_stack: stk_high = m2_expr.ExprInt(idc.GetSpd(assignblk.instr.offset), ir_arch.sp.size) fix_dct = {ir_arch.sp: mn.regs.regs_init[ir_arch.sp] + stk_high} new_assignblk = {} for dst, src in assignblk.iteritems(): if fix_stack: src = src.replace_expr(fix_dct) if dst != ir_arch.sp: dst = dst.replace_expr(fix_dct) dst, src = expr_simp(dst), expr_simp(src) new_assignblk[dst] = src irs.append(AssignBlock(new_assignblk, instr=assignblk.instr)) ir_arch.blocks[irb.label] = IRBlock(irb.label, irs) # Get dependency graphs dg = settings.depgraph graphs = dg.get(label, elements, line_nb, set([ir_arch.symbol_pool.getby_offset(func.startEA)])) # Display the result comments = {} sol_nb = 0 # Register and launch ida_kernwin.add_hotkey("Shift-N", next_element) treat_element()
def launch_depgraph(): global graphs, comments, sol_nb, settings, addr, ir_arch, ircfg # Get the current function addr = idc.ScreenEA() func = ida_funcs.get_func(addr) # Init machine = guess_machine(addr=func.startEA) mn, dis_engine, ira = machine.mn, machine.dis_engine, machine.ira bs = bin_stream_ida() mdis = dis_engine(bs, dont_dis_nulstart_bloc=True) ir_arch = ira(mdis.loc_db) # Populate symbols with ida names for ad, name in idautils.Names(): if name is None: continue mdis.loc_db.add_location(name, ad) asmcfg = mdis.dis_multiblock(func.startEA) # Generate IR ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg) # Get settings settings = depGraphSettingsForm(ir_arch, ircfg) settings.Execute() loc_key, elements, line_nb = settings.loc_key, settings.elements, settings.line_nb # Simplify affectations for irb in ircfg.blocks.values(): irs = [] offset = ir_arch.loc_db.get_location_offset(irb.loc_key) fix_stack = offset is not None and settings.unalias_stack for assignblk in irb: if fix_stack: stk_high = m2_expr.ExprInt(idc.GetSpd(assignblk.instr.offset), ir_arch.sp.size) fix_dct = {ir_arch.sp: mn.regs.regs_init[ir_arch.sp] + stk_high} new_assignblk = {} for dst, src in assignblk.iteritems(): if fix_stack: src = src.replace_expr(fix_dct) if dst != ir_arch.sp: dst = dst.replace_expr(fix_dct) dst, src = expr_simp(dst), expr_simp(src) new_assignblk[dst] = src irs.append(AssignBlock(new_assignblk, instr=assignblk.instr)) ircfg.blocks[irb.loc_key] = IRBlock(irb.loc_key, irs) # Get dependency graphs dg = settings.depgraph graphs = dg.get(loc_key, elements, line_nb, set([ir_arch.loc_db.get_offset_location(func.startEA)])) # Display the result comments = {} sol_nb = 0 # Register and launch ida_kernwin.add_hotkey("Shift-N", next_element) treat_element()
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()
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 viewitems(dct) if dst != self.sp } out.append(AssignBlock(dct, assignblk.instr)) return out, extra if verbose: print("Arch", dis_engine) fname = idc.get_root_filename() 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 list(viewvalues(ircfg.blocks)): irs = [] for assignblk in irb: new_assignblk = { expr_simp(dst): expr_simp(src) for dst, src in viewitems(assignblk) } 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" head = list(entry_points)[0] if simplify: ircfg_simplifier = IRCFGSimplifierCommon(ir_arch) ircfg_simplifier.simplify(ircfg, head) title += " (simplified)" if type_graph == TYPE_GRAPH_IR: graph = GraphMiasmIR(ircfg, title, None) graph.Show() return 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(viewvalues(out)) # 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 class CustomIRCFGSimplifierSSA(IRCFGSimplifierSSA): def do_simplify(self, ssa, head): modified = super(CustomIRCFGSimplifierSSA, self).do_simplify(ssa, head) if loadint: modified |= load_from_int(ssa.graph, bs, is_addr_ro_variable) return modified def simplify(self, ircfg, head): ssa = self.ircfg_to_ssa(ircfg, head) ssa = self.do_simplify_loop(ssa, head) if type_graph == TYPE_GRAPH_IRSSA: ret = ssa.graph elif type_graph == TYPE_GRAPH_IRSSAUNSSA: ircfg = self.ssa_to_unssa(ssa, head) ircfg_simplifier = IRCFGSimplifierCommon(self.ir_arch) ircfg_simplifier.simplify(ircfg, head) ret = ircfg else: raise ValueError("Unknown option") return ret head = list(entry_points)[0] simplifier = CustomIRCFGSimplifierSSA(ir_arch) ircfg = simplifier.simplify(ircfg, head) open('final.dot', 'w').write(ircfg.dot()) graph = GraphMiasmIR(ircfg, title, None) graph.Show()
def launch_depgraph(): global graphs, comments, sol_nb, settings, addr, ir_arch, ircfg # Get the current function addr = idc.get_screen_ea() func = ida_funcs.get_func(addr) # Init machine = guess_machine(addr=func.start_ea) mn, dis_engine, ira = machine.mn, machine.dis_engine, machine.ira bs = bin_stream_ida() mdis = dis_engine(bs, dont_dis_nulstart_bloc=True) ir_arch = ira(mdis.loc_db) # Populate symbols with ida names for ad, name in idautils.Names(): if name is None: continue mdis.loc_db.add_location(name, ad) asmcfg = mdis.dis_multiblock(func.start_ea) # Generate IR ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg) # Get settings settings = depGraphSettingsForm(ir_arch, ircfg, mn) settings.Execute() loc_key, elements, line_nb = settings.loc_key, settings.elements, settings.line_nb # Simplify assignments for irb in list(viewvalues(ircfg.blocks)): irs = [] offset = ir_arch.loc_db.get_location_offset(irb.loc_key) fix_stack = offset is not None and settings.unalias_stack for assignblk in irb: if fix_stack: stk_high = m2_expr.ExprInt(idc.get_spd(assignblk.instr.offset), ir_arch.sp.size) fix_dct = {ir_arch.sp: mn.regs.regs_init[ir_arch.sp] + stk_high} new_assignblk = {} for dst, src in viewitems(assignblk): if fix_stack: src = src.replace_expr(fix_dct) if dst != ir_arch.sp: dst = dst.replace_expr(fix_dct) dst, src = expr_simp(dst), expr_simp(src) new_assignblk[dst] = src irs.append(AssignBlock(new_assignblk, instr=assignblk.instr)) ircfg.blocks[irb.loc_key] = IRBlock(irb.loc_key, irs) # Get dependency graphs dg = settings.depgraph graphs = dg.get(loc_key, elements, line_nb, set([ir_arch.loc_db.get_offset_location(func.start_ea)])) # Display the result comments = {} sol_nb = 0 # Register and launch ida_kernwin.add_hotkey("Shift-N", next_element) treat_element()
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 viewitems(dct) 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 list(viewvalues(ircfg.blocks)): irs = [] for assignblk in irb: new_assignblk = { expr_simp(dst): expr_simp(src) for dst, src in viewitems(assignblk) } 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" head = list(entry_points)[0] if simplify: ircfg_simplifier = IRCFGSimplifierCommon(ir_arch) ircfg_simplifier.simplify(ircfg, head) title += " (simplified)" if type_graph == TYPE_GRAPH_IR: graph = GraphMiasmIR(ircfg, title, None) graph.Show() return 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(viewvalues(out)) # 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 class CustomIRCFGSimplifierSSA(IRCFGSimplifierSSA): def do_simplify(self, ssa, head): modified = super(CustomIRCFGSimplifierSSA, self).do_simplify(ssa, head) if loadint: modified |= load_from_int(ssa.graph, bs, is_addr_ro_variable) return modified def simplify(self, ircfg, head): ssa = self.ircfg_to_ssa(ircfg, head) ssa = self.do_simplify_loop(ssa, head) if type_graph == TYPE_GRAPH_IRSSA: ret = ssa.graph elif type_graph == TYPE_GRAPH_IRSSAUNSSA: ircfg = self.ssa_to_unssa(ssa, head) ircfg_simplifier = IRCFGSimplifierCommon(self.ir_arch) ircfg_simplifier.simplify(ircfg, head) ret = ircfg else: raise ValueError("Unknown option") return ret head = list(entry_points)[0] simplifier = CustomIRCFGSimplifierSSA(ir_arch) ircfg = simplifier.simplify(ircfg, head) open('final.dot', 'w').write(ircfg.dot()) graph = GraphMiasmIR(ircfg, title, None) graph.Show()
def OnCommand(self, cmd_id): if self.cmd_test == cmd_id: print 'TEST!' return print "command:", cmd_id def Show(self): if not GraphViewer.Show(self): return False self.cmd_test = self.AddCommand("Test", "F2") if self.cmd_test == 0: print "Failed to add popup menu item!" return True machine = guess_machine() mn, dis_engine, ira = machine.mn, machine.dis_engine, machine.ira print "Arch", dis_engine fname = GetInputFile() print fname bs = bin_stream_ida() mdis = dis_engine(bs) ir_arch = ira(mdis.symbol_pool) # populate symbols with ida names for ad, name in Names(): # print hex(ad), repr(name) if name is None:
def analyse_function(): # Init machine = guess_machine() mn, dis_engine, ira = machine.mn, machine.dis_engine, machine.ira bs = bin_stream_ida() mdis = dis_engine(bs, dont_dis_nulstart_bloc=True) iraCallStackFixer = get_ira_call_fixer(ira) ir_arch = iraCallStackFixer(mdis.symbol_pool) # Get settings settings = TypePropagationForm(ir_arch) ret = settings.Execute() if not ret: return if settings.cScope.value == 0: addr = settings.functionAddr.value else: addr = settings.startAddr.value if settings.cScope.value == 2: end = settings.endAddr mdis.dont_dis = [end] blocks = mdis.dis_multiblock(addr) # Generate IR for block in blocks: ir_arch.add_block(block) cst_propag_link = {} if settings.cUnalias.value: init_infos = {ir_arch.sp: ir_arch.arch.regs.regs_init[ir_arch.sp] } cst_propag_link = propagate_cst_expr(ir_arch, addr, init_infos) types_mngr = get_types_mngr(settings.headerFile.value, settings.arch.value) mychandler = MyCHandler(types_mngr, {}) infos_types = {} infos_types_raw = [] if settings.cTypeFile.value: infos_types_raw = open(settings.typeFile.value).read().split('\n') else: infos_types_raw = settings.strTypesInfo.value.split('\n') for line in infos_types_raw: if not line: continue expr_str, ctype_str = line.split(':') expr_str, ctype_str = expr_str.strip(), ctype_str.strip() expr = str_to_expr(expr_str) ast = mychandler.types_mngr.types_ast.parse_c_type( ctype_str) ctype = mychandler.types_mngr.types_ast.ast_parse_declaration(ast.ext[0]) objc = types_mngr.get_objc(ctype) print '=' * 20 print expr, objc infos_types[expr] = set([objc]) # Add fake head lbl_real_start = ir_arch.symbol_pool.getby_offset(addr) lbl_head = ir_arch.symbol_pool.getby_name_create("start") first_block = blocks.label2block(lbl_real_start) assignblk_head = AssignBlock([ExprAff(ir_arch.IRDst, ExprId(lbl_real_start, ir_arch.IRDst.size)), ExprAff( ir_arch.sp, ir_arch.arch.regs.regs_init[ir_arch.sp]) ], first_block.lines[0]) irb_head = IRBlock(lbl_head, [assignblk_head]) ir_arch.blocks[lbl_head] = irb_head ir_arch.graph.add_uniq_edge(lbl_head, lbl_real_start) state = TypePropagationEngine.StateEngine(infos_types) states = {lbl_head: state} todo = set([lbl_head]) done = set() while todo: lbl = todo.pop() state = states[lbl] if (lbl, state) in done: continue done.add((lbl, state)) if lbl not in ir_arch.blocks: continue symbexec_engine = TypePropagationEngine(ir_arch, types_mngr, state) addr = symbexec_engine.run_block_at(lbl) symbexec_engine.del_mem_above_stack(ir_arch.sp) ir_arch._graph = None sons = ir_arch.graph.successors(lbl) for son in sons: add_state(ir_arch, todo, states, son, symbexec_engine.get_state()) for lbl, state in states.iteritems(): if lbl not in ir_arch.blocks: continue symbexec_engine = CTypeEngineFixer(ir_arch, types_mngr, state, cst_propag_link) addr = symbexec_engine.run_block_at(lbl) symbexec_engine.del_mem_above_stack(ir_arch.sp)
def analyse_function(): # Get settings settings = TypePropagationForm() ret = settings.Execute() if not ret: return end = None if settings.cScope.value == 0: addr = settings.functionAddr.value else: addr = settings.startAddr.value if settings.cScope.value == 2: end = settings.endAddr # Init machine = guess_machine(addr=addr) mn, dis_engine, lifter_model_call = machine.mn, machine.dis_engine, machine.lifter_model_call bs = bin_stream_ida() loc_db = LocationDB() mdis = dis_engine(bs, loc_db=loc_db, dont_dis_nulstart_bloc=True) if end is not None: mdis.dont_dis = [end] lifter_model_callCallStackFixer = get_lifter_model_call_call_fixer( lifter_model_call) lifter = lifter_model_callCallStackFixer(loc_db) asmcfg = mdis.dis_multiblock(addr) # Generate IR ircfg = lifter.new_ircfg_from_asmcfg(asmcfg) cst_propag_link = {} if settings.cUnalias.value: init_infos = {lifter.sp: lifter.arch.regs.regs_init[lifter.sp]} cst_propag_link = propagate_cst_expr(lifter, ircfg, addr, init_infos) types_mngr = get_types_mngr(settings.headerFile.value, settings.arch.value) mychandler = MyCHandler(types_mngr, {}) infos_types = {} infos_types_raw = [] if settings.cTypeFile.value: infos_types_raw = open(settings.typeFile.value).read().split('\n') else: infos_types_raw = settings.strTypesInfo.value.split('\n') for line in infos_types_raw: if not line: continue expr_str, ctype_str = line.split(':') expr_str, ctype_str = expr_str.strip(), ctype_str.strip() expr = str_to_expr(expr_str) ast = mychandler.types_mngr.types_ast.parse_c_type(ctype_str) ctype = mychandler.types_mngr.types_ast.ast_parse_declaration( ast.ext[0]) objc = types_mngr.get_objc(ctype) print('=' * 20) print(expr, objc) infos_types[expr] = set([objc]) # Add fake head lbl_real_start = loc_db.get_offset_location(addr) lbl_head = loc_db.get_or_create_name_location("start") first_block = asmcfg.loc_key_to_block(lbl_real_start) assignblk_head = AssignBlock([ ExprAssign(lifter.IRDst, ExprLoc(lbl_real_start, lifter.IRDst.size)), ExprAssign(lifter.sp, lifter.arch.regs.regs_init[lifter.sp]) ], first_block.lines[0]) irb_head = IRBlock(loc_db, lbl_head, [assignblk_head]) ircfg.blocks[lbl_head] = irb_head ircfg.add_uniq_edge(lbl_head, lbl_real_start) state = TypePropagationEngine.StateEngine(infos_types) states = {lbl_head: state} todo = set([lbl_head]) done = set() while todo: lbl = todo.pop() state = states[lbl] if (lbl, state) in done: continue done.add((lbl, state)) if lbl not in ircfg.blocks: continue symbexec_engine = TypePropagationEngine(lifter, types_mngr, state) symbexec_engine.run_block_at(ircfg, lbl) symbexec_engine.del_mem_above_stack(lifter.sp) sons = ircfg.successors(lbl) for son in sons: add_state(ircfg, todo, states, son, symbexec_engine.get_state()) for lbl, state in viewitems(states): if lbl not in ircfg.blocks: continue symbexec_engine = CTypeEngineFixer(lifter, types_mngr, state, cst_propag_link) symbexec_engine.run_block_at(ircfg, lbl) symbexec_engine.del_mem_above_stack(lifter.sp)
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()
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 analyse_function(): # Init machine = guess_machine() mn, dis_engine, ira = machine.mn, machine.dis_engine, machine.ira bs = bin_stream_ida() mdis = dis_engine(bs, dont_dis_nulstart_bloc=True) iraCallStackFixer = get_ira_call_fixer(ira) ir_arch = iraCallStackFixer(mdis.symbol_pool) # Get the current function func = ida_funcs.get_func(idc.ScreenEA()) addr = func.startEA blocks = mdis.dis_multiblock(addr) # Generate IR for block in blocks: ir_arch.add_block(block) # Get settings settings = TypePropagationForm(ir_arch) ret = settings.Execute() if not ret: return cst_propag_link = {} if settings.cUnalias.value: init_infos = {ir_arch.sp: ir_arch.arch.regs.regs_init[ir_arch.sp]} cst_propag_link = propagate_cst_expr(ir_arch, addr, init_infos) types_mngr = get_types_mngr(settings.headerFile.value, settings.arch.value) mychandler = MyCHandler(types_mngr, {}) infos_types = {} for line in settings.strTypesInfo.value.split('\n'): if not line: continue expr_str, ctype_str = line.split(':') expr_str, ctype_str = expr_str.strip(), ctype_str.strip() expr = str_to_expr(expr_str) ast = mychandler.types_mngr.types_ast.parse_c_type(ctype_str) ctype = mychandler.types_mngr.types_ast.ast_parse_declaration( ast.ext[0]) objc = types_mngr.get_objc(ctype) print '=' * 20 print expr, objc infos_types[expr] = set([objc]) # Add fake head lbl_real_start = ir_arch.symbol_pool.getby_offset(addr) lbl_head = ir_arch.symbol_pool.getby_name_create("start") first_block = blocks.label2block(lbl_real_start) assignblk_head = AssignBlock([ ExprAff(ir_arch.IRDst, ExprId(lbl_real_start, ir_arch.IRDst.size)), ExprAff(ir_arch.sp, ir_arch.arch.regs.regs_init[ir_arch.sp]) ], first_block.lines[0]) irb_head = IRBlock(lbl_head, [assignblk_head]) ir_arch.blocks[lbl_head] = irb_head ir_arch.graph.add_uniq_edge(lbl_head, lbl_real_start) state = TypePropagationEngine.StateEngine(infos_types) states = {lbl_head: state} todo = set([lbl_head]) done = set() while todo: lbl = todo.pop() state = states[lbl] if (lbl, state) in done: continue done.add((lbl, state)) if lbl not in ir_arch.blocks: continue symbexec_engine = TypePropagationEngine(ir_arch, types_mngr, state) addr = symbexec_engine.emul_ir_block(lbl) symbexec_engine.del_mem_above_stack(ir_arch.sp) ir_arch._graph = None sons = ir_arch.graph.successors(lbl) for son in sons: add_state(ir_arch, todo, states, son, symbexec_engine.get_state()) for lbl, state in states.iteritems(): if lbl not in ir_arch.blocks: continue symbexec_engine = CTypeEngineFixer(ir_arch, types_mngr, state, cst_propag_link) addr = symbexec_engine.emul_ir_block(lbl) symbexec_engine.del_mem_above_stack(ir_arch.sp)
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()
def dataflow_analysis(addr, block_items, DG): machine = guess_machine() mn, dis_engine, ira = machine.mn, machine.dis_engine, machine.ira # # print "Arch", dis_engine # # fname = idc.GetInputFile() # print "file name : ",fname # print "machine",machine bs = bin_stream_ida() mdis = dis_engine(bs) mdis.dont_dis_retcall_funcs = [] mdis.dont_dis = [] ir_arch = ira(mdis.symbol_pool) blocks = mdis.dis_multiblock(addr) for block in blocks: ir_arch.add_block(block) # print ">>asm block",block IRs = {} for lbl, irblock in ir_arch.blocks.items(): insr = [] for assignblk in irblock: for dst, src in assignblk.iteritems(): insr.append(str(dst) + "=" + str(src)) # print ">>ir",(str(lbl)+"L"),insr IRs[str(lbl).split(' ')[0] + "L"] = insr # print "IRs.keys()",IRs.keys() IR_blocks = {} no_ir = {} # print "block_items",block_items for block in blocks: # print "block.label",block.label isFind = False item = str(block.label).split(' ')[0] + "L" # item = "0x"+(str(block.label).split(' ')[0].split(':')[1][2:]).lstrip('0') + "L" # print "block line number",item for block_item in block_items: # print block_item if item.endswith(block_item): isFind = True # for irlabel in IRs.keys(): # print irlabel,item # if irlabel.endswith(item): # itrm = irlabel # print item,IRs[str(block.label) + "L"] if IRs.has_key(item): if isFind: IR_blocks[item] = IRs[item] else: IR_blocks[item] = IRs[item] no_ir[item] = IRs[item] # print "yes_ir : ",list(IR_blocks.keys()) no_keys = list(no_ir.keys()) # print "no_ir : ",no_keys for cur_label in no_keys: cur_block = None # print "" # print "" # print "find no_ir label is : ",cur_label for block in blocks: # 去除loc_0000000000413D4C:0x00413d4cL callXXX的情况 temp_index = str(block.label).split(' ')[0] + "L" # print block.label,temp_index if temp_index.endswith(cur_label): cur_block = block if not cur_block is None: # print "find no_ir ",cur_block IR_blocks, no_ir = rebuild_graph(cur_block, blocks, IR_blocks, no_ir) # print len(no_ir) # # save_file = "C:/AppData/Setup/IDA_Pro_v6.8/" + idc.GetFunctionName(addr) + ".txt" # fp = open(save_file, 'w') # print "**********result*************" # # fp.write( str(DG.edges()) + "\n") # for in_label, in_value in IR_blocks.items(): # fp.write(in_label+"\n") # for i in in_value: # fp.write("\t\t"+i+"\n") IR_blocks_toDFG = {} for key, value in IR_blocks.items(): if len(key.split(':')) > 1: key = key.split(':')[0] + ":0x" + key.split( ':')[1].strip()[2:].lstrip('0') # print "dg to dfg : ",key IR_blocks_toDFG[key] = value # print "IR_blocks_toDFG",IR_blocks_toDFG # print "CFG edges <<",DG.number_of_edges(),">> :",DG.edges() dfg = build_dfg(DG, IR_blocks_toDFG) dfg.add_nodes_from(DG.nodes()) print "CFG edges <<", DG.number_of_edges(), ">> :", DG.edges() print "DFG edges <<", dfg.number_of_edges(), ">> :", dfg.edges() print "DFG nodes : ", dfg.number_of_nodes() return dfg
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()