def post_add_bloc(self, bloc, ir_blocs): ir.post_add_bloc(self, bloc, ir_blocs) for irb in ir_blocs: pc_val = None lr_val = None for exprs in irb.irs: for e in exprs: if e.dst == PC: pc_val = e.src if e.dst == LR: lr_val = e.src if pc_val is None or lr_val is None: continue if not isinstance(lr_val, ExprInt): continue l = bloc.lines[-1] if lr_val.arg != l.offset + l.l: continue lbl = bloc.get_next() new_lbl = self.gen_label() irs = self.call_effects(pc_val) irs.append([ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))]) nbloc = irbloc(new_lbl, irs) nbloc.lines = [l] * len(irs) self.blocs[new_lbl] = nbloc irb.dst = ExprId(new_lbl, size=self.pc.size)
def post_add_bloc(self, bloc, ir_blocs): ir.post_add_bloc(self, bloc, ir_blocs) # flow_graph = DiGraph() l = bloc.lines[-1] if not l.is_subcall(): return for irb in ir_blocs: # print 'X'*40 # print irb pc_val = None for exprs in irb.irs: for e in exprs: if e.dst == PC: pc_val = e.src if pc_val is None: continue l = bloc.lines[-1] # print str(l), 'IS CALL!' lbl = bloc.get_next() new_lbl = self.gen_label() irs = self.call_effects(pc_val) irs.append([ExprAff(IRDst, ExprId(lbl, size=self.pc.size))]) nbloc = irbloc(new_lbl, irs) nbloc.lines = [l] self.blocs[new_lbl] = nbloc irb.dst = ExprId(new_lbl, size=self.pc.size)
def post_add_bloc(self, bloc, ir_blocs): ir.post_add_bloc(self, bloc, ir_blocs) for irb in ir_blocs: pc_val = None lr_val = None for assignblk in irb.irs: pc_val = assignblk.get(PC, pc_val) lr_val = assignblk.get(LR, lr_val) if pc_val is None or lr_val is None: continue if not isinstance(lr_val, ExprInt): continue l = bloc.lines[-1] if lr_val.arg != l.offset + l.l: continue # CALL lbl = bloc.get_next() new_lbl = self.gen_label() irs = self.call_effects(pc_val) irs.append(AssignBlock([ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))])) nbloc = irbloc(new_lbl, irs) nbloc.lines = [l] * len(irs) self.blocs[new_lbl] = nbloc irb.dst = ExprId(new_lbl, size=self.pc.size)
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 post_add_bloc(self, bloc, ir_blocs): ir.post_add_bloc(self, bloc, ir_blocs) if not bloc.lines: return l = bloc.lines[-1] sub_call_dst = None if not l.is_subcall(): return sub_call_dst = l.args[0] if expr_is_label(sub_call_dst): sub_call_dst = sub_call_dst.name for b in ir_blocs: l = b.lines[-1] sub_call_dst = None if not l.is_subcall(): continue sub_call_dst = l.args[0] if expr_is_label(sub_call_dst): sub_call_dst = sub_call_dst.name lbl = bloc.get_next() new_lbl = self.gen_label() irs = self.call_effects(l.args[0]) irs.append([ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))]) nbloc = irbloc(new_lbl, irs) nbloc.lines = [l] self.blocs[new_lbl] = nbloc b.dst = ExprId(new_lbl, size=self.pc.size) return
def post_add_bloc(self, bloc, ir_blocs): ir.post_add_bloc(self, bloc, ir_blocs) if not bloc.lines: return l = bloc.lines[-1] sub_call_dst = None if not l.is_subcall(): return sub_call_dst = l.args[0] if expr_is_label(sub_call_dst): sub_call_dst = sub_call_dst.name for irb in ir_blocs: l = irb.lines[-1] sub_call_dst = None if not l.is_subcall(): continue sub_call_dst = l.args[0] if expr_is_label(sub_call_dst): sub_call_dst = sub_call_dst.name lbl = bloc.get_next() new_lbl = self.gen_label() irs = self.call_effects(l.args[0]) irs.append( AssignBlock( [ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))])) nbloc = irbloc(new_lbl, irs) nbloc.lines = [l] * len(irs) self.blocs[new_lbl] = nbloc irb.dst = ExprId(new_lbl, size=self.pc.size) return
def post_add_bloc(self, bloc, ir_blocs): ir.post_add_bloc(self, bloc, ir_blocs) for irb in ir_blocs: pc_val = None lr_val = None for assignblk in irb.irs: pc_val = assignblk.get(PC, pc_val) lr_val = assignblk.get(LR, lr_val) if pc_val is None or lr_val is None: continue if not isinstance(lr_val, ExprInt): continue l = bloc.lines[-1] if lr_val.arg != l.offset + l.l: continue # CALL lbl = bloc.get_next() new_lbl = self.gen_label() irs = self.call_effects(pc_val, l) irs.append( AssignBlock( [ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))])) nbloc = irbloc(new_lbl, irs) nbloc.lines = [l] * len(irs) self.blocs[new_lbl] = nbloc irb.dst = ExprId(new_lbl, size=self.pc.size)
def post_add_bloc(self, bloc, ir_blocs): ir.post_add_bloc(self, bloc, ir_blocs) # flow_graph = DiGraph() for irb in ir_blocs: # print 'X'*40 # print irb pc_val = None lr_val = None for exprs in irb.irs: for e in exprs: if e.dst == PC: pc_val = e.src if e.dst == LR: lr_val = e.src if pc_val is None or lr_val is None: continue if not isinstance(lr_val, ExprInt): continue l = bloc.lines[-1] if lr_val.arg != l.offset + l.l: continue # print 'IS CALL!' lbl = bloc.get_next() new_lbl = self.gen_label() irs = self.call_effects(pc_val) irs.append([ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))]) nbloc = irbloc(new_lbl, irs) nbloc.lines = [l]*len(irs) self.blocs[new_lbl] = nbloc irb.set_dst(ExprId(new_lbl, size=self.pc.size)) """
def post_add_bloc(self, bloc, ir_blocs): ir.post_add_bloc(self, bloc, ir_blocs) for irb in ir_blocs: pc_val = None lr_val = None for assignblk in irb.irs: pc_val = assignblk.get(PC, pc_val) lr_val = assignblk.get(RA, lr_val) if pc_val is None or lr_val is None: continue if not expr_is_int_or_label(lr_val): continue if expr_is_label(lr_val): lr_val = ExprInt32(lr_val.name.offset) l = bloc.lines[-2] if lr_val.arg != l.offset + 8: raise ValueError("Wrong arg") # CALL lbl = bloc.get_next() new_lbl = self.gen_label() irs = self.call_effects(pc_val) irs.append( AssignBlock( [ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))])) nbloc = irbloc(new_lbl, irs) nbloc.lines = [l] * len(irs) self.blocs[new_lbl] = nbloc irb.dst = ExprId(new_lbl, size=self.pc.size)
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, 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 post_add_bloc(self, bloc, ir_blocs): ir.post_add_bloc(self, bloc, ir_blocs) for irb in ir_blocs: pc_val = None lr_val = None for assignblk in irb.irs: pc_val = assignblk.get(PC, pc_val) lr_val = assignblk.get(RA, lr_val) if pc_val is None or lr_val is None: continue if not expr_is_int_or_label(lr_val): continue if expr_is_label(lr_val): lr_val = ExprInt32(lr_val.name.offset) l = bloc.lines[-2] if lr_val.arg != l.offset + 8: raise ValueError("Wrong arg") # CALL lbl = bloc.get_next() new_lbl = self.gen_label() irs = self.call_effects(pc_val) irs.append(AssignBlock([ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))])) nbloc = irbloc(new_lbl, irs) nbloc.lines = [l] * len(irs) self.blocs[new_lbl] = nbloc irb.dst = ExprId(new_lbl, size=self.pc.size)
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, 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 movz(ir, instr, a, b, c): lbl_do = m2_expr.ExprId(ir.gen_label(), 32) lbl_skip = m2_expr.ExprId(ir.get_next_instr(instr), 32) e_do = [] e_do.append(m2_expr.ExprAff(a, b)) e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip)) e = [] e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(c, lbl_skip, lbl_do))) return e, [irbloc(lbl_do.name, [e_do], [])]
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: irs.append(AssignBlock(exprs)) irbl = irbloc(label, irs, lines) return irbl
def assignblk_to_irbloc(self, instr, assignblk): """ Ensure IRDst is always set in the head @assignblk of the @instr @assignblk: Assignblk instance @instr: an instruction instance """ if self.ir_arch.IRDst not in assignblk: assignblk[self.ir_arch.IRDst] = m2_expr.ExprInt( instr.offset + instr.l, self.ir_arch.IRDst.size) return irbloc(self.ir_arch.get_instr_label(instr), [assignblk])
def gen_irbloc(label, exprs_list): """ Returns an IRBlock with empty lines. Used only for tests purpose """ lines = [None for _ in xrange(len(exprs_list))] irs = [] for exprs in exprs_list: if isinstance(exprs, AssignBlock): irs.append(exprs) else: irs.append(AssignBlock(exprs)) irbl = irbloc(label, irs, lines) return irbl
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 irblock_slice(self, irb): """Slice of the dependency nodes on the irblock @irb @irb: irbloc instance """ assignblks = [] line2elements = {} for depnode in self.relevant_nodes: if depnode.label != irb.label: continue line2elements.setdefault(depnode.line_nb, set()).add(depnode.element) for line_nb, elements in sorted(line2elements.iteritems()): assignblk = AssignBlock() for element in elements: if element in irb.irs[line_nb]: # constants, label, ... are not in destination assignblk[element] = irb.irs[line_nb][element] assignblks.append(assignblk) return irbloc(irb.label, assignblks)
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}
def post_add_bloc(self, bloc, ir_blocs): ir.post_add_bloc(self, bloc, ir_blocs) l = bloc.lines[-1] if not l.is_subcall(): return for irb in ir_blocs: pc_val = None for assignblk in irb.irs: pc_val = assignblk.get(PC, pc_val) if pc_val is None: continue l = bloc.lines[-1] lbl = bloc.get_next() new_lbl = self.gen_label() irs = self.call_effects(pc_val) irs.append(AssignBlock([ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))])) nbloc = irbloc(new_lbl, irs) nbloc.lines = [l] * len(irs) self.blocs[new_lbl] = nbloc irb.dst = ExprId(new_lbl, size=self.pc.size)
def add_condition_expr(ir, instr, cond, instr_ir): if cond == COND_AL: return instr_ir, [] if not cond in tab_cond: raise ValueError('unknown condition %r' % cond) cond = tab_cond[cond] lbl_next = ExprId(ir.get_next_label(instr), 32) lbl_do = ExprId(ir.gen_label(), 32) dst_cond = ExprCond(cond, lbl_do, lbl_next) assert(isinstance(instr_ir, list)) has_irdst = False for e in instr_ir: if e.dst == ir.IRDst: has_irdst = True break if not has_irdst: instr_ir.append(ExprAff(ir.IRDst, lbl_next)) e_do = irbloc(lbl_do.name, [instr_ir]) e = [ExprAff(ir.IRDst, dst_cond)] return e, [e_do]
def post_add_bloc(self, bloc, ir_blocs): ir.post_add_bloc(self, bloc, ir_blocs) l = bloc.lines[-1] if not l.is_subcall(): return for irb in ir_blocs: pc_val = None for assignblk in irb.irs: pc_val = assignblk.get(PC, pc_val) if pc_val is None: continue l = bloc.lines[-1] lbl = bloc.get_next() new_lbl = self.gen_label() irs = self.call_effects(pc_val, l) irs.append( AssignBlock( [ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))])) nbloc = irbloc(new_lbl, irs) nbloc.lines = [l] * len(irs) self.blocs[new_lbl] = nbloc irb.dst = ExprId(new_lbl, size=self.pc.size)
def post_add_bloc(self, bloc, ir_blocs): ir.post_add_bloc(self, bloc, ir_blocs) for irb in ir_blocs: # print 'X'*40 # print irb pc_val = None lr_val = None for exprs in irb.irs: for e in exprs: if e.dst == PC: pc_val = e.src if e.dst == RA: lr_val = e.src #print "XXX", pc_val, lr_val if pc_val is None or lr_val is None: continue if not expr_is_int_or_label(lr_val): continue if expr_is_label(lr_val): lr_val = ExprInt32(lr_val.name.offset) l = bloc.lines[-2] #print 'TEST', l, hex(lr_val.arg), hex(l.offset + 8) #print lr_val.arg, hex(l.offset + l.l) if lr_val.arg != l.offset + 8: fds continue # print 'IS CALL!' lbl = bloc.get_next() new_lbl = self.gen_label() irs = self.call_effects(pc_val) irs.append([ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))]) nbloc = irbloc(new_lbl, irs) nbloc.lines = [l] self.blocs[new_lbl] = nbloc irb.dst = ExprId(new_lbl, size=self.pc.size)
def post_add_bloc(self, bloc, ir_blocs): ir.post_add_bloc(self, bloc, ir_blocs) for irb in ir_blocs: # print 'X'*40 # print irb pc_val = None lr_val = None for exprs in irb.irs: for e in exprs: if e.dst == PC: pc_val = e.src if e.dst == RA: lr_val = e.src #print "XXX", pc_val, lr_val if pc_val is None or lr_val is None: continue if not expr_is_int_or_label(lr_val): continue if expr_is_label(lr_val): lr_val = ExprInt32(lr_val.name.offset) l = bloc.lines[-2] #print 'TEST', l, hex(lr_val.arg), hex(l.offset + 8) #print lr_val.arg, hex(l.offset + l.l) if lr_val.arg != l.offset + 8: raise ValueError("Wrong arg") # print 'IS CALL!' lbl = bloc.get_next() new_lbl = self.gen_label() irs = self.call_effects(pc_val) irs.append([ExprAff(self.IRDst, ExprId(lbl, size=self.pc.size))]) nbloc = irbloc(new_lbl, irs) nbloc.lines = [l] self.blocs[new_lbl] = nbloc irb.dst = ExprId(new_lbl, size=self.pc.size)
def gen_irbloc(lbl, exprs): """ Returns an IRBlock with empty lines. Used only for tests purpose """ lines = [None for _ in xrange(len(exprs))] return irbloc(lbl, exprs, lines)
def gen_irbloc(label, exprs): lines = [None for _ in xrange(len(exprs))] irbl = irbloc(label, exprs, lines) return irbl
def gen_irbloc(lbl, exprs): lines = [None for i in xrange(len(exprs))] irb = irbloc(lbl, exprs, lines) return irb