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 _gen_path_constraints(self, translator, expr, expected): """Generate path constraint from @expr. Handle special case with generated labels """ out = [] expected_is_label = expr_is_label(expected) for consval in possible_values(expr): if (expected_is_label and consval.value != expected): continue if (not expected_is_label and expr_is_label(consval.value)): continue conds = z3.And(*[translator.from_expr(cond.to_constraint()) for cond in consval.constraints]) if expected != consval.value: conds = z3.And(conds, translator.from_expr( m2_expr.ExprAff(consval.value, expected))) out.append(conds) if out: conds = z3.Or(*out) else: # Ex: expr: lblgen1, expected: 0x1234 # -> Avoid unconsistent solution lblgen1 = 0x1234 conds = translator.from_expr(self.unsat_expr) return conds
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 edge_attr(self, src, dst): if src not in self._blocks or dst not in self._blocks: return {} src_irdst = self._blocks[src].dst edge_color = "blue" if isinstance(src_irdst, m2_expr.ExprCond): if (expr_is_label(src_irdst.src1) and src_irdst.src1.name == dst): edge_color = "limegreen" elif (expr_is_label(src_irdst.src2) and src_irdst.src2.name == dst): edge_color = "red" return {"color": edge_color}
def traverse_expr_dst(self, expr, dst2index): """ Generate the index of the destination label for the @expr @dst2index: dictionnary to link label to its index """ if isinstance(expr, m2_expr.ExprCond): cond = self.id_to_c(expr.cond) src1, src1b = self.traverse_expr_dst(expr.src1, dst2index) src2, src2b = self.traverse_expr_dst(expr.src2, dst2index) return ("((%s)?(%s):(%s))" % (cond, src1, src2), "((%s)?(%s):(%s))" % (cond, src1b, src2b)) elif isinstance(expr, m2_expr.ExprInt): offset = int(expr.arg) self.add_label_index(dst2index, offset) return ("%s" % dst2index[offset], hex(offset)) elif expr_is_label(expr): label = expr.name if label.offset != None: offset = label.offset self.add_label_index(dst2index, offset) return ("%s" % dst2index[offset], hex(offset)) else: self.add_label_index(dst2index, label) return ("%s" % dst2index[label], "0") else: dst2index[expr] = -1 return ("-1", self.id_to_c(expr))
def traverse_expr_dst(self, expr, dst2index): """ Generate the index of the destination label for the @expr @dst2index: dictionnary to link label to its index """ if isinstance(expr, m2_expr.ExprCond): cond = self.id_to_c(expr.cond) src1, src1b = self.traverse_expr_dst(expr.src1, dst2index) src2, src2b = self.traverse_expr_dst(expr.src2, dst2index) return ("((%s)?(%s):(%s))" % (cond, src1, src2), "((%s)?(%s):(%s))" % (cond, src1b, src2b)) elif isinstance(expr, m2_expr.ExprInt): offset = int(expr) self.add_label_index(dst2index, offset) return ("%s" % dst2index[offset], hex(offset)) elif expr_is_label(expr): label = expr.name if label.offset != None: offset = label.offset self.add_label_index(dst2index, offset) return ("%s" % dst2index[offset], hex(offset)) else: self.add_label_index(dst2index, label) return ("%s" % dst2index[label], "0") else: dst2index[expr] = -1 return ("-1", self.id_to_c(expr))
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 cb_x86_callpop(cur_bloc, symbol_pool, *args, **kwargs): """ 1000: call 1005 1005: pop Will give: 1000: push 1005 1005: pop """ # Pattern matching if len(cur_bloc.lines) < 1: return ## We want to match a CALL, always the last line of a basic block last_instr = cur_bloc.lines[-1] if last_instr.name != 'CALL': return ## The destination must be a label dst = last_instr.args[0] if not expr_is_label(dst): return ## The destination must be the next instruction if dst.name.offset != last_instr.offset + last_instr.l: return # Update instruction instance last_instr.name = 'PUSH' # Update next blocks to process in the disassembly engine cur_bloc.bto.clear() cur_bloc.add_cst(dst.name.offset, asm_constraint.c_next, symbol_pool)
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 _follow_nolabel(exprs): """Do not follow labels""" follow = set() for expr in exprs: if not expr_is_label(expr): follow.add(expr) return follow, set()
def _follow_label(exprs): """Do not follow labels""" follow = set() for expr in exprs: if expr_is_label(expr): continue follow.add(expr) return follow, set()
def _follow_label(exprs): """Do not follow labels""" follow = set() unfollow = set() for expr in exprs: if expr_is_label(expr): unfollow.add(expr) else: follow.add(expr) return follow, unfollow
def _gen_graph(self): """ Gen irbloc digraph """ self._graph = DiGraphIR(self.blocs) for lbl, b in self.blocs.iteritems(): self._graph.add_node(lbl) dst = self.dst_trackback(b) for d in dst: if isinstance(d, m2_expr.ExprInt): d = m2_expr.ExprId( self.symbol_pool.getby_offset_create(int(d.arg))) if expr_is_label(d): self._graph.add_edge(lbl, d.name)
def _gen_graph(self): """ Gen irbloc digraph """ self._graph = DiGraphIR(self.blocs) for lbl, b in self.blocs.iteritems(): self._graph.add_node(lbl) dst = self.dst_trackback(b) for d in dst: if isinstance(d, m2_expr.ExprInt): d = m2_expr.ExprId( self.symbol_pool.getby_offset_create(int(d))) if expr_is_label(d): self._graph.add_edge(lbl, d.name)
def sort_dst(self, todo, done): out = set() while todo: dst = todo.pop() if expr_is_label(dst): done.add(dst) elif isinstance(dst, m2_expr.ExprMem) or isinstance(dst, m2_expr.ExprInt): done.add(dst) elif isinstance(dst, m2_expr.ExprCond): todo.add(dst.src1) todo.add(dst.src2) elif isinstance(dst, m2_expr.ExprId): out.add(dst) else: done.add(dst) return out
def _extract_dst(self, todo, done): """ Naive extraction of @todo destinations WARNING: @todo and @done are modified """ out = set() while todo: dst = todo.pop() if expr_is_label(dst): done.add(dst) elif isinstance(dst, m2_expr.ExprMem) or isinstance(dst, m2_expr.ExprInt): done.add(dst) elif isinstance(dst, m2_expr.ExprCond): todo.add(dst.src1) todo.add(dst.src2) elif isinstance(dst, m2_expr.ExprId): out.add(dst) else: done.add(dst) return out
def _extract_dst(self, todo, done): """ Naive extraction of @todo destinations WARNING: @todo and @done are modified """ out = set() while todo: dst = todo.pop() if expr_is_label(dst): done.add(dst) elif isinstance(dst, m2_expr.ExprMem) or isinstance( dst, m2_expr.ExprInt): done.add(dst) elif isinstance(dst, m2_expr.ExprCond): todo.add(dst.src1) todo.add(dst.src2) elif isinstance(dst, m2_expr.ExprId): out.add(dst) else: done.add(dst) return out
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 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)