def emul(self, ctx=None, step=False): """Symbolic execution of relevant nodes according to the history Return the values of input nodes' elements @ctx: (optional) Initial context as dictionary @step: (optional) Verbose execution Warning: The emulation is not sound if the input nodes depend on loop variant. """ # Init ctx_init = self._ira.arch.regs.regs_init if ctx is not None: ctx_init.update(ctx) depnodes = self.relevant_nodes affects = [] # Build a single affectation block according to history for label in self.relevant_labels[::-1]: affected_lines = set(depnode.line_nb for depnode in depnodes if depnode.label == label) irs = self._ira.blocs[label].irs for line_nb in sorted(affected_lines): affects.append(irs[line_nb]) # Eval the block temp_label = asm_label("Temp") symb_exec = symbexec(self._ira, ctx_init) symb_exec.emulbloc(irbloc(temp_label, affects), step=step) # Return only inputs values (others could be wrongs) return { depnode.element: symb_exec.symbols[depnode.element] for depnode in self.input }
def emul(self, ctx=None, step=False): """Symbolic execution of relevant nodes according to the history Return the values of input nodes' elements @ctx: (optional) Initial context as dictionnary @step: (optional) Verbose execution /!\ The emulation is not safe if there is a loop in the relevant labels """ # Init ctx_init = self._ira.arch.regs.regs_init if ctx is not None: ctx_init.update(ctx) depnodes = self.relevant_nodes affects = [] # Build a single affectation block according to history for label in self.relevant_labels[::-1]: affected_lines = set(depnode.line_nb for depnode in depnodes if depnode.label == label) irs = self._ira.blocs[label].irs for line_nb in sorted(affected_lines): affects.append(irs[line_nb]) # Eval the block temp_label = asm_label("Temp") sb = symbexec(self._ira, ctx_init) sb.emulbloc(irbloc(temp_label, affects), step=step) # Return only inputs values (others could be wrongs) return {depnode.element: sb.symbols[depnode.element] for depnode in self.input}
def emul(self, ctx=None, step=False): """Symbolic execution of relevant nodes according to the history Return the values of inputs nodes' elements @ctx: (optional) Initial context as dictionnary @step: (optional) Verbose execution Warning: The emulation is not sound if the inputs nodes depend on loop variant. """ # Init ctx_init = self._ira.arch.regs.regs_init if ctx is not None: ctx_init.update(ctx) assignblks = [] # Build a single affectation block according to history last_index = len(self.relevant_labels) for index, label in enumerate(reversed(self.relevant_labels), 1): if index == last_index and label == self.initial_state.label: line_nb = self.initial_state.line_nb else: line_nb = None assignblks += self.irblock_slice(self._ira.blocs[label], line_nb).irs # Eval the block temp_label = asm_label("Temp") symb_exec = symbexec(self._ira, ctx_init) symb_exec.emulbloc(irbloc(temp_label, assignblks), step=step) # Return only inputs values (others could be wrongs) return {element: symb_exec.symbols[element] for element in self.inputs}
def emul(self, ctx=None, step=False): """Symbolic execution of relevant nodes according to the history Return the values of inputs nodes' elements @ctx: (optional) Initial context as dictionnary @step: (optional) Verbose execution Warning: The emulation is not sound if the inputs nodes depend on loop variant. """ # Init ctx_init = self._ira.arch.regs.regs_init if ctx is not None: ctx_init.update(ctx) assignblks = [] # Build a single affectation block according to history for label in self.relevant_labels[::-1]: assignblks += self.irblock_slice(self._ira.blocs[label]).irs # Eval the block temp_label = asm_label("Temp") symb_exec = symbexec(self._ira, ctx_init) symb_exec.emulbloc(irbloc(temp_label, assignblks), step=step) # Return only inputs values (others could be wrongs) return {element: symb_exec.symbols[element] for element in self.inputs}
def emul(self, step=False): """Symbolic execution of relevant nodes according to the history Return the values of input nodes' elements /!\ The emulation is not safe if there is a loop in the relevant labels """ # Init depnodes = self.relevant_nodes affects = [] # Build a single affectation block according to history for label in self.relevant_labels[::-1]: affected_lines = set(depnode.line_nb for depnode in depnodes if depnode.label == label) irs = self._ira.blocs[label].irs for line_nb in sorted(affected_lines): affects.append(irs[line_nb]) # Eval the block temp_label = asm_label("Temp") sb = symbexec(self._ira, self._ira.arch.regs.regs_init) sb.emulbloc(irbloc(temp_label, affects), step=step) # Return only inputs values (others could be wrongs) return { depnode.element: sb.symbols[depnode.element] for depnode in self.input }
def id_from_size(self, size, value): """Transform a string into ExprId. * if @size is None, use provided id2expr * else, use @size to generate id @size: size of id; None if not forced. @value: string representing the id """ value = self.id2expr(value) if isinstance(value, m2_expr.Expr): return value if size is None: size = self.default_size assert value is not None return m2_expr.ExprId(asmbloc.asm_label(value), size)
def emul(self, ctx=None, step=False): # Init ctx_init = self._ira.arch.regs.regs_init if ctx is not None: ctx_init.update(ctx) depnodes = self.relevant_nodes solver = z3.Solver() symb_exec = symbexec(self._ira, ctx_init) temp_label = asm_label("Temp") history = self.relevant_labels[::-1] history_size = len(history) for hist_nb, label in enumerate(history): # Build block with relevant lines only affected_lines = set(depnode.line_nb for depnode in depnodes if depnode.label == label) irs = self._ira.blocs[label].irs affects = [] for line_nb in sorted(affected_lines): affects.append(irs[line_nb]) # Emul the block and get back destination dst = symb_exec.emulbloc(irbloc(temp_label, affects), step=step) # Add constraint if hist_nb + 1 < history_size: next_label = history[hist_nb + 1] expected = symb_exec.eval_expr(m2_expr.ExprId(next_label, 32)) constraint = m2_expr.ExprAff(dst, expected) solver.add(Translator.to_language("z3").from_expr(constraint)) # Save the solver self._solver = solver # Return only inputs values (others could be wrongs) return { depnode.element: symb_exec.symbols[depnode.element] for depnode in self.input }
def emul(self, ctx=None, step=False): # Init ctx_init = self._ira.arch.regs.regs_init if ctx is not None: ctx_init.update(ctx) depnodes = self.relevant_nodes solver = z3.Solver() sb = symbexec(self._ira, ctx_init) temp_label = asm_label("Temp") history = self.relevant_labels[::-1] history_size = len(history) for hist_nb, label in enumerate(history): # Build block with relevant lines only affected_lines = set(depnode.line_nb for depnode in depnodes if depnode.label == label) irs = self._ira.blocs[label].irs affects = [] for line_nb in sorted(affected_lines): affects.append(irs[line_nb]) # Emul the block and get back destination dst = sb.emulbloc(irbloc(temp_label, affects), step=step) # Add constraint if hist_nb + 1 < history_size: next_label = history[hist_nb + 1] expected = sb.eval_expr(m2_expr.ExprId(next_label, 32)) constraint = m2_expr.ExprAff(dst, expected) solver.add(Translator.to_language("z3").from_expr(constraint)) # Save the solver self._solver = solver # Return only inputs values (others could be wrongs) return {depnode.element: sb.symbols[depnode.element] for depnode in self.input}
dg = DiGraphSimplifier() dg.enable_passes([remove_useless_blocks]) blocks = dg(blocks) ### Only two blocks should remain assert len(blocks) == 2 assert first_block in blocks assert last_block in blocks ## Graph the final output open("graph2.dot", "w").write(blocks.dot()) # Test helper methods ## Label2block should always be updated assert blocks.label2block(first_block.label) == first_block my_block = asm_bloc(asm_label("testlabel")) blocks.add_node(my_block) assert len(blocks) == 3 assert blocks.label2block(first_block.label) == first_block assert blocks.label2block(my_block.label) == my_block ## Bad blocks assert len(list(blocks.get_bad_blocks())) == 0 assert len(list(blocks.get_bad_blocks_predecessors())) == 0 ### Add a bad block, not linked my_bad_block = asm_block_bad(asm_label("testlabel_bad")) blocks.add_node(my_bad_block) assert list(blocks.get_bad_blocks()) == [my_bad_block] assert len(list(blocks.get_bad_blocks_predecessors())) == 0 ### Link the bad block and update edges ### Indeed, a sub-element has been modified (bto from a block from blocks)
def get_next_label(self, _): return asm_label("NEXT")
def ast_id2expr(t): if not t in mn_msp430.regs.all_regs_ids_byname: r = ExprId(asm_label(t), 16) else: r = mn_msp430.regs.all_regs_ids_byname[t] return r
c = ExprId("c") d = ExprId("d") a_init = ExprId("a_init") b_init = ExprId("b_init") c_init = ExprId("c_init") d_init = ExprId("d_init") pc = ExprId("pc") sp = ExprId("sp") cst1 = ExprInt32(0x11) cst2 = ExprInt32(0x12) cst3 = ExprInt32(0x13) lbl0 = asm_label("lbl0") lbl1 = asm_label("lbl1") lbl2 = asm_label("lbl2") lbl3 = asm_label("lbl3") lbl4 = asm_label("lbl4") lbl5 = asm_label("lbl5") lbl6 = asm_label("lbl6") def gen_irbloc(lbl, exprs): lines = [None for i in xrange(len(exprs))] irb = irbloc(lbl, exprs, lines) return irb class Regs(object):
def gen_label(self): return asm_label("GEN")
def ast_id2expr(t): if not t in mn_mips32.regs.all_regs_ids_byname: r = ExprId(asm_label(t)) else: r = mn_mips32.regs.all_regs_ids_byname[t] return r
r = ExprId("r") a_init = ExprId("a_init") b_init = ExprId("b_init") c_init = ExprId("c_init") d_init = ExprId("d_init") r_init = ExprId("r_init") # Return register pc = ExprId("pc") sp = ExprId("sp") CST1 = ExprInt32(0x11) CST2 = ExprInt32(0x12) CST3 = ExprInt32(0x13) LBL0 = asm_label("lbl0") LBL1 = asm_label("lbl1") LBL2 = asm_label("lbl2") LBL3 = asm_label("lbl3") LBL4 = asm_label("lbl4") LBL5 = asm_label("lbl5") LBL6 = asm_label("lbl6") def gen_irbloc(label, exprs_list): lines = [None for _ in xrange(len(exprs_list))] irs = [] for exprs in exprs_list: if isinstance(exprs, AssignBlock): irs.append(exprs) else:
c = ExprId("c") d = ExprId("d") a_init = ExprId("a_init") b_init = ExprId("b_init") c_init = ExprId("c_init") d_init = ExprId("d_init") pc = ExprId("pc") sp = ExprId("sp") cst1 = ExprInt32(0x11) cst2 = ExprInt32(0x12) cst3 = ExprInt32(0x13) lbl0 = asm_label("lbl0") lbl1 = asm_label("lbl1") lbl2 = asm_label("lbl2") lbl3 = asm_label("lbl3") lbl4 = asm_label("lbl4") lbl5 = asm_label("lbl5") lbl6 = asm_label("lbl6") def gen_irbloc(lbl, exprs): lines = [None for i in xrange(len(exprs))] irb = irbloc(lbl, exprs, lines) return irb
for miasm_int, res in [(five, 1), (four, 0), (seven, 0), (one0seven, 0)]: e6 = ExprOp('parity', miasm_int) ez3 = Translator.to_language('z3').from_expr(e6) z3_e6 = z3.BitVecVal(res, 1) assert equiv(ez3, z3_e6) # -------------------------------------------------------------------------- # '-' for miasm_int, res in [(five, -5), (four, -4)]: e6 = ExprOp('-', miasm_int) ez3 = Translator.to_language('z3').from_expr(e6) z3_e6 = z3.BitVecVal(res, 32) assert equiv(ez3, z3_e6) # -------------------------------------------------------------------------- e7 = ExprId(asm_label("label_histoire", 0xdeadbeef), 32) ez3 = Translator.to_language('z3').from_expr(e7) z3_e7 = z3.BitVecVal(0xdeadbeef, 32) assert equiv(ez3, z3_e7) # Should just not throw anything to pass e8 = ExprId(asm_label("label_jambe"), 32) ez3 = Translator.to_language('z3').from_expr(e8) assert not equiv(ez3, z3_e7) # -------------------------------------------------------------------------- # bsr, bsf # bsf(0x1138) == 3 bsf1 = Translator.to_language('z3').from_expr( ExprOp("bsf", ExprInt(0x1138, 32)))
r = ExprId("r") a_init = ExprId("a_init") b_init = ExprId("b_init") c_init = ExprId("c_init") d_init = ExprId("d_init") r_init = ExprId("r_init") # Return register pc = ExprId("pc") sp = ExprId("sp") CST1 = ExprInt32(0x11) CST2 = ExprInt32(0x12) CST3 = ExprInt32(0x13) LBL0 = asm_label("lbl0") LBL1 = asm_label("lbl1") LBL2 = asm_label("lbl2") LBL3 = asm_label("lbl3") LBL4 = asm_label("lbl4") LBL5 = asm_label("lbl5") LBL6 = asm_label("lbl6") def gen_irbloc(label, exprs): lines = [None for _ in xrange(len(exprs))] irbl = irbloc(label, exprs, lines) return irbl
for miasm_int, res in [(five, 1), (four, 0), (seven, 0), (one0seven, 0)]: e6 = ExprOp('parity', miasm_int) ez3 = Translator.to_language('z3').from_expr(e6) z3_e6 = z3.BitVecVal(res, 1) assert equiv(ez3, z3_e6) # -------------------------------------------------------------------------- # '-' for miasm_int, res in [(five, -5), (four, -4)]: e6 = ExprOp('-', miasm_int) ez3 = Translator.to_language('z3').from_expr(e6) z3_e6 = z3.BitVecVal(res, 32) assert equiv(ez3, z3_e6) # -------------------------------------------------------------------------- e7 = ExprId(asm_label("label_histoire", 0xdeadbeef), 32) ez3 = Translator.to_language('z3').from_expr(e7) z3_e7 = z3.BitVecVal(0xdeadbeef, 32) assert equiv(ez3, z3_e7) # Should just not throw anything to pass e8 = ExprId(asm_label("label_jambe"), 32) ez3 = Translator.to_language('z3').from_expr(e8) assert not equiv(ez3, z3_e7) # -------------------------------------------------------------------------- # bsr, bsf # bsf(0x1138) == 3 bsf1 = Translator.to_language('z3').from_expr(ExprOp("bsf", ExprInt(0x1138, 32))) bsf2 = z3.BitVecVal(3, 32)