def __init__(self, result): self.result = result self._vars = dict() self.concrete_reads = set() self.concrete_writes = set() self.symbolic_reads = set() self.symbolic_writes = set() self.symbolic_hash_reads = set() self.symbolic_hash_writes = set() for addr in set(result.state.storage.reads): if concrete(addr): self.concrete_reads.add(addr) else: x_vars = get_vars_non_recursive(addr, True) self._vars[addr] = x_vars if set(x_vars) & set(result.sha_constraints.keys()): self.symbolic_hash_reads.add(addr) else: self.symbolic_reads.add(addr) for addr in set(result.state.storage.writes): if concrete(addr): self.concrete_writes.add(addr) else: x_vars = get_vars_non_recursive(addr, True) self._vars[addr] = x_vars if set(x_vars) & set(result.sha_constraints.keys()): self.symbolic_hash_writes.add(addr) else: self.symbolic_writes.add(addr)
def dependency_summary(constraints, sha_constraints, detailed=False): all_dependencies = set(x for c in constraints if z3.is_expr(c) for x in get_vars_non_recursive(z3.simplify(c), include_select=detailed)) changed = True while changed: changed = False for x in set(all_dependencies): if x in sha_constraints: changed = True all_dependencies.discard(x) all_dependencies.update( get_vars_non_recursive(z3.simplify(sha_constraints[x], include_select=detailed))) return all_dependencies
def translate(expr, xid): substitutions = dict() def raw(s): return '_'.join(s.split('_')[:-1]) for v in get_vars_non_recursive(expr): if v not in substitutions: v_name = raw(v.decl().name()) if v.sort_kind() == z3.Z3_INT_SORT: substitutions[v] = z3.Int('%s_%d' % (v_name, xid)) elif v.sort_kind() == z3.Z3_BOOL_SORT: substitutions[v] = z3.Bool('%s_%d' % (v_name, xid)) elif v.sort_kind() == z3.Z3_BV_SORT: substitutions[v] = z3.BitVec('%s_%d' % (v_name, xid), v.size()) elif v.sort_kind() == z3.Z3_ARRAY_SORT: substitutions[v] = z3.Array('%s_%d' % (v_name, xid), v.domain(), v.range()) else: raise Exception('CANNOT CONVERT %s (%d)' % (v, v.sort_kind())) subst = list(substitutions.items()) return z3.substitute(expr, subst)
def check_and_model(constraints, sha_constraints, ne_constraints, second_try=False): # logging.debug(' ' * 16 + '-' * 16) unresolved = set(sha_constraints.keys()) sol = get_solver() sol.add(ne_constraints) todo = constraints progress = True all_vars = dict() while progress: new_todo = [] progress = False for c in todo: all_vars[c] = get_vars_non_recursive(c, include_select=True, include_indices=False) if any(x in unresolved for x in all_vars[c]): new_todo.append(c) else: progress = True sol.add(c) unresolved_vars = set(v.get_id() for c in new_todo for v in all_vars[c]) | set(v.get_id() for v in unresolved) # logging.debug("Unresolved vars: %s", ','.join(map(str, unresolved_vars))) if sol.check() != z3.sat: raise IntractablePath() m = sol.model() unresolved_todo = list(set(unresolved)) while unresolved_todo: u = unresolved_todo.pop() c = sha_constraints[u] if isinstance(c, SymRead): vars = set() if not concrete(c.start): vars |= get_vars_non_recursive(c.start, include_select=True) if not concrete(c.size): vars |= get_vars_non_recursive(c.size, include_select=True) # logging.debug("Trying to resolve %s, start and size vars: %s", u, ','.join(map(str, vars))) if any(x.get_id() in unresolved_vars for x in vars): continue start = c.start if not concrete(c.start): tmp = m.eval(c.start) if not z3util.is_expr_val(tmp): continue start = tmp.as_long() sol.add(c.start == start) size = c.size if not concrete(c.size): tmp = m.eval(c.size) if not z3util.is_expr_val(tmp): continue size = tmp.as_long() sol.add(c.size == size) data = c.memory.read(start, size) if isinstance(data, list): if len(data) > 1: data = z3.Concat(*data) elif len(data) == 1: data = data[0] else: raise IntractablePath() sha_constraints = dict(sha_constraints) sha_constraints[u] = data unresolved_todo.append(u) else: vars = get_vars_non_recursive(c, include_select=True) # logging.debug("Trying to resolve %s, vars: %s", u, ','.join(map(str, vars))) if any(x.get_id() in unresolved_vars for x in vars): continue v = m.eval(c) if z3util.is_expr_val(v): sha = big_endian_to_int(sha3(to_bytes(v))) sol.add(c == v) sol.add(u == sha) unresolved.remove(u) progress = True todo = new_todo if sol.check() != z3.sat: raise IntractablePath() if todo: if second_try: raise IntractablePath() raise UnresolvedConstraints(unresolved) return sol.model()