def ExecuteSymbolicSingleStep(addr, state=INIT_REG): size = idc.ItemSize(addr) code = idc.GetManyBytes(addr, size) loc_db = LocationDB() base = addr try: ins = mn_x86.dis(bin_stream_str(code, base_address=base), 64, base) except: return state.copy() ira = machine.ira(loc_db) ircfg = ira.new_ircfg() try: ira.add_instr_to_ircfg(ins, ircfg) sb = SymbolicExecutionEngine(ira, state) symbolic_pc = sb.run_at(ircfg, base) except: return state.copy() ret = state.copy() for key, value in sb.modified(): if isinstance(value, ExprOp) and value.op == "call_func_ret": value = ExprInt(0, 64) ret[key] = value return ret
def parse(self, data, vm=None, addr=0, **kwargs): self._bin_stream = bin_stream_str(data, base_address=addr) if vm is not None: vm.add_memory_page( addr, PAGE_READ, data ) self._executable = None self._entry_point = 0
def dis(cls, bs_o, mode_o = None, offset=0): if not isinstance(bs_o, bin_stream): bs_o = bin_stream_str(bs_o) bs_o.enter_atomic_mode() offset_o = offset try: pre_dis_info, bs, mode, offset, prefix_len = cls.pre_dis( bs_o, mode_o, offset) except: bs_o.leave_atomic_mode() raise candidates = cls.guess_mnemo(bs, mode, pre_dis_info, offset) if not candidates: bs_o.leave_atomic_mode() raise Disasm_Exception('cannot disasm (guess) at %X' % offset) out = [] out_c = [] if hasattr(bs, 'getlen'): bs_l = bs.getlen() else: bs_l = len(bs) alias = False for c in candidates: log.debug("*" * 40, mode, c.mode) log.debug(c.fields) c = cls.all_mn_inst[c][0] c.reset_class() c.mode = mode if not c.add_pre_dis_info(pre_dis_info): continue todo = {} getok = True fname_values = dict(pre_dis_info) offset_b = offset * 8 total_l = 0 for i, f in enumerate(c.fields_order): if f.flen is not None: l = f.flen(mode, fname_values) else: l = f.l if l is not None: total_l += l f.l = l f.is_present = True log.debug("FIELD %s %s %s %s", f.__class__, f.fname, offset_b, l) if bs_l * 8 - offset_b < l: getok = False break try: bv = cls.getbits(bs, mode, offset_b, l) except: bs_o.leave_atomic_mode() raise offset_b += l if not f.fname in fname_values: fname_values[f.fname] = bv todo[i] = bv else: f.is_present = False todo[i] = None if not getok: continue c.l = prefix_len + total_l // 8 for i in c.to_decode: f = c.fields_order[i] if f.is_present: ret = f.decode(todo[i]) if not ret: log.debug("cannot decode %r", f) break if not ret: continue for a in c.args: a.expr = expr_simp(a.expr) c.b = cls.getbytes(bs, offset_o, c.l) c.offset = offset_o c = c.post_dis() if c is None: continue c_args = [a.expr for a in c.args] instr = cls.instruction(c.name, mode, c_args, additional_info=c.additional_info()) instr.l = prefix_len + total_l // 8 instr.b = cls.getbytes(bs, offset_o, instr.l) instr.offset = offset_o instr.get_info(c) if c.alias: alias = True out.append(instr) out_c.append(c) bs_o.leave_atomic_mode() if not out: raise Disasm_Exception('cannot disasm at %X' % offset_o) if len(out) != 1: if not alias: log.warning('dis multiple args ret default') for i, o in enumerate(out_c): if o.alias: return out[i] raise NotImplementedError( 'Multiple disas: \n' + "\n".join(str(x) for x in out) ) return out[0]
mn = Machine('x86_64') # Create an intermediate representation object loc_db = LocationDB() ira = mn.ira(loc_db) # create an empty ircfg ircfg = ira.new_ircfg() # Binary path and offset of the target function offset = 0x1150 fname = "bin/simple_test.bin" # Get Miasm's binary stream bin_file = open(fname).read() bin_stream = bin_stream_str(bin_file) # Disassemble blocks of the function at 'offset' mdis = mn.dis_engine(bin_stream) disasm = mdis.dis_multiblock(offset) ircfg = ira.new_ircfg_from_asmcfg(disasm) entry_points = set([mdis.loc_db.get_offset_location(offset)]) # Create target IR object and add all basic blocks to it ir = ir_a_x86_64(mdis.symbol_pool) for bbl in disasm.blocks: print(bbl.to_string(disasm.loc_db)) ira.add_asmblock_to_ircfg(bbl, ircfg) init_infos = ira.arch.regs.regs_init
def get_graph(self): simplify = self.simplify dontmodstack = self.dontmodstack loadmemint = self.loadmemint type_graph = self.type_graph bin_str = "" for s in self.data.segments: bin_str += self.data.read(s.start, len(s)) # add padding between each segment if s.end != self.data.end: bin_str += '\x00' * (((s.end | 0xfff) + 1) - s.end) bs = bin_stream_str(input_str=bin_str, base_address=self.data.start) machine = Machine(archs[self.data.arch.name]) mdis = machine.dis_engine(bs) asmcfg = mdis.dis_multiblock(self.function.start) entry_points = set( [mdis.loc_db.get_offset_location(self.function.start)]) class IRADelModCallStack(machine.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 ir_arch = IRADelModCallStack(mdis.loc_db) ircfg = ir_arch.new_ircfg_from_asmcfg(asmcfg) 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) head = list(entry_points)[0] if simplify: ircfg_simplifier = IRCFGSimplifierCommon(ir_arch) ircfg_simplifier.simplify(ircfg, head) if type_graph == TYPE_GRAPH_IR: return MiasmIRGraph(self.add_names(ircfg)) class IRAOutRegs(machine.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 loadmemint: 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 # dirty patch to synchronize nodes and blocks lists in ircfg nodes_to_del = [ node for node in ircfg.nodes() if not node in ircfg.blocks ] for node in nodes_to_del: ircfg.del_node(node) head = list(entry_points)[0] simplifier = CustomIRCFGSimplifierSSA(ir_arch) ircfg = simplifier.simplify(ircfg, head) return MiasmIRGraph(self.add_names(ircfg))