def getTypedZ3ValFromIdentifier(identifier, types): if type(identifier) == dict: # FIXME how can we handle this here raise NotSupportedException('Complex objects as base for operations cannot be modelled in z3') if type(identifier) == list: arr = z3.Array('ignore_helper_constant_array_' + randomString(), z3.IntSort(), z3.StringSort()) for i, arg in enumerate(identifier): GLOBAL_CONSTRAINTS.append(z3.Select(arr, i) == createZ3ExpressionFromConstraint(arg, types)) ARRAY_LENGTHS[str(arr.decl())] = len(identifier) return arr cur_types = types GLOBAL_IDENTIFIER.add(identifier) cur_types = infered_types[identifier] # if cur_types == 'object': # infered_types[identifier] = '' # cur_types = '' if identifier.endswith('.length'): return z3.Length(z3.String(identifier[:-7])) if cur_types == 'string': return z3.String(identifier) elif cur_types == 'number': return z3.Int(identifier) elif cur_types == 'boolean': return z3.Bool(identifier) elif cur_types == 'array': return z3.Array(identifier, z3.IntSort(), z3.StringSort()) if 'event.data' in identifier or 'event.origin' in identifier or 'event' == identifier: return z3.String(identifier) else: MAKE_UNSOLVABLE.add(identifier) return z3.String(identifier)
def get_z3py_variable(v): """Convert the given variable object to a z3py variable""" if v.type.base == "Boolean": if v.type.size < 1: return z3.Bool(v.name) else: return z3.Array(v.name, z3.IntSort(), z3.BoolSort()) else: if v.type.size < 1: return z3.Int(v.name) else: return z3.Array(v.name, z3.IntSort(), z3.IntSort())
def set_mem(self, address, value): unique_name = "mem_{}".format(self.mem_count) new_memory = z3.Array(unique_name, z3.BitVecSort(self.arch.bits), z3.BitVecSort(8)) self.mem_count += 1 self.memory = utils.z3_set_memory(self.memory, address, value, self.arch) self.append_assignment(new_memory, self.memory) self.memory = new_memory
def __getitem__(self, op): if (op | iss | InputOp): r = "" for loc in op.getLocations(): var = z3.BitVec(str(loc), 8) var = self.m[var] r = r + ("\\x%.2x" % var.as_long()) return r if (op | iss | RegOp): var = map(lambda b: z3.BitVec(str(b), 8), op.getLocations()) var = map(lambda b: self.m[b], var) if (len(var) > 1): return z3.simplify(z3.Concat(var)).as_signed_long() else: return z3.simplify(var[0]).as_signed_long() elif (op.isMem()): array = z3.Array(op.name, z3.BitVecSort(16), z3.BitVecSort(8)) f = self.m[array] #print self.m es = f.as_list()[:-1] var = [] for loc in op.getLocations(): byte = None for entry in es: #print entry if loc.getIndex() == entry[0].as_signed_long(): byte = entry[1] #.as_signed_long() break if (byte == None): byte = f.else_value() var.append(byte) r = "" for v in var: r = r + ("\\x%.2x" % v.as_long()) return r #var.reverse() #if (len(var) > 1): # return z3.simplify(z3.Concat(var)).as_signed_long() #else: # return z3.simplify(var[0]).as_signed_long() else: assert (0) r = [] for loc in i.getLocations(): r.append(self.vars[str(loc)]) return r
def _symbol(self, name): lightdp_type = self._type_map[name] if isinstance(lightdp_type, NumType): return z3.Real(name) elif isinstance(lightdp_type, ListType): if isinstance(lightdp_type.elem_type, NumType): return z3.Array(name, z3.RealSort(), z3.RealSort()) elif isinstance(lightdp_type.elem_type, BoolType): return z3.Array(name, z3.BoolSort(), z3.RealSort()) else: raise ValueError('Unsupported list inside list.') elif isinstance(lightdp_type, FunctionType): raise NotImplementedError( 'Function type is currently not supported.') elif isinstance(lightdp_type, BoolType): return z3.Bool(name) else: assert False, 'No such type %s' % lightdp_type
def mem_to_z3(e,solver=None): e.simplify() M = z3.Array('M',z3.BitVecSort(e.a.size),z3.BitVecSort(8)) p = e.a.to_smtlib(solver) b = [] for i in range(0,e.length): b.insert(0,M[p+i]) if e._endian==-1: b.reverse() # big-endian case if len(b) > 1: return z3.Concat(*b) return b[0]
def __init__(self, name: str, domain: int, value_range: int): """Initializes a symbolic array. :param name: Name of the array :param domain: The domain for the array (10 -> all the values that a bv of size 10 could take) :param value_range: The range for the values in the array (10 -> all the values that a bv of size 10 could take) """ self.domain = z3.BitVecSort(domain) self.range = z3.BitVecSort(value_range) self.raw = z3.Array(name, self.domain, self.range)
def _switch_to_symbolic(self): if self._conc_store is not None: assert self._z3obj is None self._z3obj = z3.Array(self.name, z3.BitVecSort(self.index_width), z3.BitVecSort(self.value_width)) for index in self._conc_store: self._z3obj = z3.Store(self._z3obj, z3.BitVecVal(index, self.index_width), self._conc_store[index].z3obj) self._conc_store = None
def getValue(self, op): assert (self.m <> None) if (op.isReg()): #if (literal): # # var = map(lambda b: z3.BitVec(b, 8), op.get_bytes()) var = map(lambda b: self.m[b], var) if (len(var) > 1): return z3.simplify(z3.Concat(var)).as_signed_long() else: return z3.simplify(var[0]).as_signed_long() elif (op.isMem()): array = z3.Array(op.mem_source, z3.BitVecSort(16), z3.BitVecSort(8)) #print "debug getValue:" #print op, op.mem_offset ,"->", array f = self.m[array] #print f # #var = map(lambda b: z3.BitVec(b,8), op.get_bytes()) #var = map(lambda b: self.m[b], var) # ##if (self.m): #print "eax:" #print "%x" % self.m[eax].as_unsigned() #assert(0) ##print op.mem_source ##print op.mem_offset es = f.as_list()[:-1] var = [] for i in range(op.size): byte = None for entry in es: if op.mem_offset + i == entry[0].as_signed_long(): byte = entry[1] #.as_signed_long() break if (byte == None): byte = f.else_value() var.append(byte) var.reverse() if (len(var) > 1): return z3.simplify(z3.Concat(var)).as_signed_long() else: return z3.simplify(var[0]).as_signed_long()
def mem_to_z3(e, slv=None): "translate mem expression into z3 a Concat of BitVec bytes" e.simplify() M = z3.Array("M", z3.BitVecSort(e.a.size), z3.BitVecSort(8)) p = e.a.to_smtlib(slv) b = [] for i in range(0, e.length): b.insert(0, M[p + i]) if e.endian == -1: b.reverse() # big-endian case if len(b) > 1: return z3.Concat(*b) return b[0]
def visit_Quantification(self, node : Quantification): bound_var = None if node.ty == TINT: bound_var = z3.Int(node.var.name) elif node.ty == TBOOL: bound_var = z3.Bool(node.var.name) elif isinstance(node.ty, TARR): bound_var = z3.Array(z3.IntSort(), self.translate_type(node.ty.ty)) if bound_var is not None: self.name_dict[node.var.name] = bound_var return z3.ForAll(bound_var, self.visit(node.expr)) else: raise Exception(f'Unsupported quantified type: {node.ty}')
def get_smt_statements(self, irsb, irsb_num): self.irsb_num = irsb_num for stmt in irsb.statements: if hasattr(self, stmt.tag): getattr(self, stmt.tag)(stmt) else: return None # Make some _after variables so it's easy to get their value for name, reg in self.out_regs.items(): self.append_assignment(reg, z3.BitVec('{}_after'.format(self.arch.translate_register_name(name)), reg.size())) self.append_assignment(self.memory, z3.Array("mem_after", z3.BitVecSort(self.arch.bits), z3.BitVecSort(8))) return self.stmt
def get_mem_array(self, size): """Returns a z3 Array used internally to represent memory for addresses of size @size. @size: integer, size in bit of addresses in the memory to get. Return a z3 Array: BitVecSort(size) -> BitVecSort(8). """ try: mem = self.mems[size] except KeyError: # Lazy instantiation self.mems[size] = z3.Array(self.name + str(size), z3.BitVecSort(size), z3.BitVecSort(8)) mem = self.mems[size] return mem
def _try_build_reduced_array(self, index_min, index_max): if self._z3obj is not None: # symbolic mode return self._z3obj if index_max - index_min >= 2**self.index_width: return self.z3obj res = z3.Array(self.name, z3.BitVecSort(self.index_width), z3.BitVecSort(self.value_width)) for i in range(index_min, index_max + 1): if i in self._conc_store: res = z3.Store(res, z3.BitVecVal(i, self.index_width), self._conc_store[i].z3obj) return res
def get_z3_equality_list(stmt_node, z3_vars, direct_equality= False): global all_z3_vars z3_asserts = [] if not direct_equality: stmt_node = stmt_node.children[0] ## get the equalitystmt first left = stmt_node.children[0] right = stmt_node.children[1] zright = get_z3_expr(right, z3_vars) name = "stmt_rhs_{}".format(stmt_node.line) i = 0 temp_name = name while (temp_name in all_z3_vars): temp_name = name + "_" + str(i) i += 1 name = temp_name zright_temp = z3.Int(name) z3_asserts.append(zright_temp == zright) all_z3_vars[name] = zright_temp if left.data == "select": # we need to update the z3_vars array_name = left.children[0].children[0].value current_label = z3_vars[array_name][1] current_array = z3_vars[array_name][0] new_label = current_label + 1 new_name = "{}_{}".format(array_name, new_label) new_array = z3.Array(new_name, z3.IntSort(), z3.IntSort()) all_z3_vars[new_name] = new_array if (left.children[1].data == "var"): index = z3_vars[left.children[1].children[0].value][0] else: #left children is num index = left.children[1].children[0].value store = z3.Store(current_array, index, zright_temp) z3_vars[array_name] = (new_array, new_label) z3_asserts.append(new_array == store) #LHS equal to new variable if left.data == "var": var_name = left.children[0].value var_label = z3_vars[var_name][1] new_name = "{}_{}".format(var_name, var_label+1) new_var = z3.Int(new_name) all_z3_vars[new_name] = new_var # add the new variable to global list z3_vars[var_name] = (new_var, var_label + 1) z3_asserts.append(new_var == zright_temp) return [(assertion, stmt_node) for assertion in z3_asserts]
def substitute_bvset(bvset, prefix): index = 0 substitution_dict = {} for bv in bvset: if type(bv) == z3.BitVecRef: substitution_dict[bv] = z3.BitVec( '{}_{}_{}'.format(bv, prefix, index), bv.size()) elif type(bv) == z3.ArrayRef: substitution_dict[bv] = z3.Array( '{}_{}_{}'.format(bv, prefix, index), bv.sort().domain(), bv.sort().range()) index += 1 return substitution_dict
def z3obj(self): if self._z3obj is not None: # symbolic mode return self._z3obj # concrete mode if self._z3objConcCache is not None: return self._z3objConcCache res = z3.Array(self.name, z3.BitVecSort(self.index_width), z3.BitVecSort(self.value_width)) for index in self._conc_store: res = z3.Store(res, z3.BitVecVal(index, self.index_width), self._conc_store[index].z3obj) self._z3objConcCache = res return res
def main(): b, c = z3.Ints("b c") a = z3.Array("a", z3.IntSort(), z3.IntSort()) f = z3.Function("f", z3.IntSort(), z3.IntSort()) solver = z3.Solver() solver.add(c == b + z3.IntVal(2)) lhs = f(z3.Store(a, b, 3)[c - 2]) rhs = f(c - b + 1) solver.add(lhs != rhs) res = solver.check() if res == z3.sat: print("sat") elif res == z3.unsat: print("unsat") else: print("unknown")
def main(): b, c = z3.Ints('b c') a = z3.Array('a', z3.IntSort(), z3.IntSort()) f = z3.Function('f', z3.IntSort(), z3.IntSort()) solver = z3.Solver() solver.add(c == b + z3.IntVal(2)) lhs = f(z3.Store(a, b, 3)[c - 2]) rhs = f(c - b + 1) solver.add(lhs <> rhs) res = solver.check() if res == z3.sat: print 'sat' elif res == z3.unsat: print 'unsat' else: print 'unknown'
def __init__(self, arch): self.arch = arch self.stmt = [] self.out_regs = {} self.reg_count = collections.defaultdict(int, {}) # Make sure all the registers have initial BitVecs in the constraints for name, (num, size) in self.arch.registers.items(): real_name = self.arch.translate_register_name(num) # So we don't get both sp and rsp, ip and rip, etc. if real_name not in self.out_regs and real_name not in extra_archinfo.IGNORED_REGISTERS[self.arch.name]: self.out_regs[num] = z3.BitVec("{}_before".format(real_name), size * 8) # Setup the initial memory self.memory = z3.Array("mem_before", z3.BitVecSort(self.arch.bits), z3.BitVecSort(8)) self.mem_count = 0 self.first_mem = self.memory
def get_sym_bitvec(self, constraint_type, gen, bv_size=256, unique=False, **kwargs): vector_name = ConstraintType[constraint_type.name].value label_template = vector_name + '_gen{}' for k in kwargs: label_template += '_' + k + '{' + k + '}' label = label_template.format(gen, **kwargs) if unique: unique_id = self.unique_vector_name_counter.get(vector_name, 0) self.unique_vector_name_counter[vector_name] = unique_id + 1 label = label + '_uid' + str(unique_id) assert constraint_type != ConstraintType.CALLDATA or 'acc' not in kwargs if constraint_type == ConstraintType.CALLDATA_ARRAY: return z3.Array(label, z3.BitVecSort(bv_size), z3.BitVecSort(8)) elif constraint_type in [ConstraintType.CALLER, ConstraintType.ORIGIN, ConstraintType.ENTRY_ACCOUNT]: return svm_utils.zpad_bv_right(z3.BitVec(label, svm_utils.ADDRESS_LEN), svm_utils.VECTOR_LEN) else: return z3.BitVec(label, bv_size)
def getZ3ValFromJSVal(val): if type(val) == str: return z3.StringVal(val) if type(val) == bool: return z3.BoolVal(val) if type(val) == int: return z3.IntVal(val) if type(val) == int: return z3.IntVal(val) if type(val) == list: arr = z3.Array('ignore_helper_constant_array_' + randomString(), z3.IntSort(), z3.StringSort()) for i, arg in enumerate(val): GLOBAL_CONSTRAINTS.append(z3.Select(arr, i) == createZ3ExpressionFromConstraint(arg, {})) ARRAY_LENGTHS[str(arr.decl())] = len(val) return arr if type(val) == dict: raise NotSupportedException('Complex Objects as base for operations with proxy strings are not yet supported!') raise Exception('Could not transform Js val to Z3 Val' + repr(val))
def _solve(self): self._field = z3.Array('f', z3.IntSort(), z3.BoolSort()) self._solver = z3.Solver() width = len(self._vertical_hints) height = len(self._horizontal_hints) for i, c in enumerate(self._horizontal_hints): self._add_column(c, 1, i * width, width, 'h%d' % i) for i, c in enumerate(self._vertical_hints): self._add_column(c, width, i, height, 'v%d' % i) res = self._solver.check() if str(res) != 'sat': return None m = self._solver.model() f0 = [[False for i in xrange(height)] for j in xrange(width)] for j in xrange(height): for i in xrange(width): f0[i][j] = str(m.eval(self._field[j * width + i])) == 'True' return f0
def VertexNameToSmt(self): assert(self.type != VertexNode.VertexType.NONE and \ self.type != VertexNode.VertexType.FUNC) if self.type == VertexNode.VertexType.VAR: return z3.BitVec(self.__str__(), self.bitlength) if self.type == VertexNode.VertexType.TEMP: # is it a boolean? if self.bitlength == -1: return z3.Bool(self.__str__()) return z3.BitVec(self.__str__(), self.bitlength) if self.type == VertexNode.VertexType.IMM: return z3.BitVecVal(self.value, self.bitlength) if self.type == VertexNode.VertexType.ARR: return z3.Array(self.__str__(), \ z3.BitVecSort(self.arrayIndexBitlength), \ z3.BitVecSort(self.arrayElBitlength))
def getValue(self, op): assert (self.m <> None) if (op | iss | RegOp): var = map(lambda b: z3.BitVec(str(b), 8), op.getLocations()) var = map(lambda b: self.m[b], var) if (len(var) > 1): return z3.simplify(z3.Concat(var)).as_signed_long() else: return z3.simplify(var[0]).as_signed_long() elif (op.isMem()): array = z3.Array(op.name, z3.BitVecSort(16), z3.BitVecSort(8)) f = self.m[array] #print self.m es = f.as_list()[:-1] var = [] for loc in op.getLocations(): byte = None for entry in es: #print entry if loc.getIndex() == entry[0].as_signed_long(): byte = entry[1] #.as_signed_long() break if (byte == None): byte = f.else_value() var.append(byte) var.reverse() if (len(var) > 1): return z3.simplify(z3.Concat(var)).as_signed_long() else: return z3.simplify(var[0]).as_signed_long() else: assert (0)
def string_split(x, args): st = x split_val = z3.StringVal(args[0].encode()) x = transformNonBooleanLazyEvaluations(x) arr = z3.Array('__ignore_{}.split({})'.format(str(x), str(args[0])), z3.IntSort(), z3.StringSort()) for i in range(3): index = z3.IndexOf(st, split_val, 0) s = z3.SubString(st, 0, index) st = z3.SubString(st, index + z3.Length(split_val), z3.Length(st)) GLOBAL_CONSTRAINTS.append(z3.Select(arr, i) == s) GLOBAL_CONSTRAINTS.append(s != z3.StringVal('')) GLOBAL_ARRAY_HANDLER[arr].append(s) GLOBAL_CONSTRAINTS.append(z3.Select(arr, 3) == st) GLOBAL_CONSTRAINTS.append(st != z3.StringVal('')) GLOBAL_ARRAY_HANDLER[arr].append(st) # We just guess the length here and hope that this works for the program ARRAY_LENGTHS[str(arr.decl())] = 4 GLOBAL_CONSTRAINTS.append(z3.IndexOf(GLOBAL_ARRAY_HANDLER[arr][-1], split_val, 0) == -1) # GLOBAL_CONSTRAINTS.append(z3.PrefixOf(GLOBAL_ARRAY_HANDLER[arr][0], x)) return arr
def _switch_to_symbolic(self, soft=False): if self._mode == BVArrayState.SEMI_CONCRETE_MODE and soft: return if self._mode == BVArrayState.SEMI_CONCRETE_MODE and not soft: self._mode = BVArrayState.SYMBOLIC_MODE self._conc_store = None return if self._mode == BVArrayState.CONCRETE_MODE: assert self._z3obj is None self._z3obj = z3.Array(self.name, z3.BitVecSort(self.index_width), z3.BitVecSort(self.value_width)) # The solver needs to add those constraints! (even lazly) for index in self._conc_store: self._assertions[index] = \ BoolExpr(z3.Select( self._z3obj, index) == self._conc_store[index].z3obj) if soft: self._mode = BVArrayState.SEMI_CONCRETE_MODE else: self._mode = BVArrayState.SYMBOLIC_MODE self._conc_store = None
def makeZ3Var(v): t = v.varType name = v.varName if t.startswith('INSTANCE:'): s = t[9:] if s == 'BYTE': return z3.Array(name, BitVecSort(32), z3.BitVecSort(8)) elif s == 'SHORT': return z3.Array(name, BitVecSort(32), z3.BitVecSort(16)) elif s == 'INT': return z3.Array(name, BitVecSort(32), z3.BitVecSort(32)) elif s == 'LONG': return z3.Array(name, BitVecSort(32), z3.BitVecSort(64)) elif s == 'FLOAT': return z3.Array(name, BitVecSort(32), Float) elif s == 'DOUBLE': return z3.Array(name, BitVecSort(32), Double) elif s == 'CHAR': return z3.Array(name, BitVecSort(32), z3.BitVecSort(16)) else: raise Exception("unsupported type {}".format(t)) elif t == 'BYTE': return z3.BitVec(name, 8) elif t == 'SHORT': return z3.BitVec(name, 16) elif t == 'INT': return z3.BitVec(name, 32) elif t == 'LONG': return z3.BitVec(name, 64) elif t == 'FLOAT': return z3.FP(name, Float) elif t == 'DOUBLE': return z3.FP(name, Double) elif t == 'CHAR': return z3.BitVec(name, 16) else: raise Exception("unsupported type {}".format(t))
import itertools import re import z3 base = 'plaidctf' r = open('regex_57f2cf49f6a354b4e8896c57a4e3c973.txt').read().strip() s = re.search(r'\((.*)\)', r).group(1) s = s.split('|')[3:] s = [re.findall(r'(.*?)\[(.*?)\]', it) for it in s] solver = z3.Solver() sol = z3.Array('sol', z3.IntSort(), z3.BoolSort()) for x in s: pos = 0 rule = [] for a, b in x: m = re.match(r'\.{(\d+)}', a) if m: pos += int(m.group(1)) else: pos += len(a) b = [base.index(it) for it in b] b = [bin(it)[2:].rjust(3, '0') for it in b] b = zip(*b) for j, y in enumerate(b): y = [it == '1' for it in y] var = sol[pos * 3 + j] if all(it == True for it in y): rule.append(var)
def get_mem(self, name): return z3.Array("mem_{}".format(name), z3.BitVecSort(self.arch.bits), z3.BitVecSort(8)) def get_mem_before(self): return self.get_mem("before")