def itoa_helper(state, value, string, base, sign=True): addr = state.evalcon(string).as_long() # ok so whats going on here is... uhh it works data = [BZERO] nvalue = z3.SignExt(96, z3.Extract(31, 0, value)) pvalue = z3.ZeroExt(64, value) do_neg = z3.And(nvalue < 0, base == 10, z3.BoolVal(sign)) base = z3.ZeroExt(64, base) new_value = z3.If(do_neg, -nvalue, pvalue) shift = BV(0, 128) for i in range(32): d = (new_value % bvpow(base, i + 1)) / bvpow(base, i) c = z3.Extract(7, 0, d) shift = z3.If(c == BZERO, shift + BV(8, 128), BV(0, 128)) data.append(z3.If(c < 10, c + BV_0, (c - 10) + BV_a)) pbv = z3.Concat(*data) szdiff = pbv.size() - shift.size() pbv = pbv >> z3.ZeroExt(szdiff, shift) nbv = z3.simplify(z3.Concat(pbv, BV(ord("-"), 8))) pbv = z3.simplify(z3.Concat(BV(0, 8), pbv)) # oof state.memory[addr] = z3.If(do_neg, nbv, pbv) return string
def prepare(val, signext=False, size=SIZE) -> z3.BitVecRef: if z3.is_bv(val): szdiff = size - val.size() if szdiff > 0: if signext: result = z3.SignExt(szdiff, val) else: result = z3.ZeroExt(szdiff, val) elif szdiff < 0: result = z3.Extract(size - 1, 0, val) else: result = val elif type(val) == int: result = z3.BitVecVal(val, size) elif z3.is_int(val): result = z3.Int2BV(val, size) elif z3.is_fp(val): # changing up this logic to align with r2ghidra impl result = z3.fpToIEEEBV(val) #result = val else: result = z3.BitVecVal(val, size) #return z3.simplify(result) return result
def _bitvec_sext(x, nbits): current_bits = x.sort().size() assert current_bits <= nbits, '%d <= %d' % (current_bits, nbits) if nbits > current_bits: return z3.SignExt(nbits - current_bits, x) else: return x
def sext(self, ctx, return_type, a, atype, **kwargs): outsize = itypes.integer_size(return_type) insize = itypes.integer_size(atype) assert outsize > insize if z3.is_bool(a): return util.If(a, z3.BitVecVal(1, outsize), z3.BitVecVal(0, outsize)) return z3.SignExt(outsize - insize, a)
def prepare(val, signext=False, size=SIZE) -> z3.BitVecRef: if z3.is_bv(val): szdiff = size-val.size() if szdiff == 0: result = val elif szdiff > 0: if signext: result = z3.SignExt(szdiff, val) else: result = z3.ZeroExt(szdiff, val) elif szdiff < 0: result = z3.Extract(size-1, 0, val) elif isinstance(val, int): result = z3.BitVecVal(val, size) elif z3.is_int(val): result = z3.Int2BV(val, size) elif z3.is_fp(val): result = z3.fpToIEEEBV(val) else: result = z3.BitVecVal(val, size) if not z3.is_bv_value(result): return z3.simplify(result) else: return result
def from_ExprOp(self, expr): args = map(self.from_expr, expr.args) res = args[0] if len(args) > 1: for arg in args[1:]: if expr.op in self.trivial_ops: res = eval("res %s arg" % expr.op) elif expr.op == ">>": res = z3.LShR(res, arg) elif expr.op == "a>>": res = res >> arg elif expr.op == "<<<": res = z3.RotateLeft(res, arg) elif expr.op == ">>>": res = z3.RotateRight(res, arg) elif expr.op == "idiv": res = self._idivC(res, arg) elif expr.op == "udiv": res = z3.UDiv(res, arg) elif expr.op == "imod": res = res - (arg * (self._idivC(res, arg))) elif expr.op == "umod": res = z3.URem(res, arg) else: raise NotImplementedError("Unsupported OP yet: %s" % expr.op) elif expr.op == 'parity': arg = z3.Extract(7, 0, res) res = z3.BitVecVal(1, 1) for i in xrange(8): res = res ^ z3.Extract(i, i, arg) elif expr.op == '-': res = -res elif expr.op == "cnttrailzeros": size = expr.size src = res res = z3.If(src == 0, size, src) for i in xrange(size - 1, -1, -1): res = z3.If((src & (1 << i)) != 0, i, res) elif expr.op == "cntleadzeros": size = expr.size src = res res = z3.If(src == 0, size, src) for i in xrange(size, 0, -1): index = -i % size out = size - (index + 1) res = z3.If((src & (1 << index)) != 0, out, res) elif expr.op.startswith("zeroExt"): arg, = expr.args res = z3.ZeroExt(expr.size - arg.size, self.from_expr(arg)) elif expr.op.startswith("signExt"): arg, = expr.args res = z3.SignExt(expr.size - arg.size, self.from_expr(arg)) else: raise NotImplementedError("Unsupported OP yet: %s" % expr.op) return res
def do_SIGN(op, stack, state): arg1, arg2 = pop_values(stack, state, 2) size = arg2 if z3.is_bv(size): size = size.as_long() szdiff = SIZE - size stack.append(z3.SignExt(szdiff, z3.Extract(size - 1, 0, arg1)))
def do_SIGN(op, stack, state): arg1, arg2 = pop_values(stack, state, 2) size = arg2 if z3.is_bv(size): size = size.as_long() if not z3.is_bv(arg1): arg1 = z3.BitVecVal(arg1, SIZE) stack.append(z3.SignExt(SIZE - size, z3.Extract(size - 1, 0, arg1)))
def extend(value, width, signed=None): if not is_z3(value): return value # XXX range check if not z3.is_bv(value): value = z3.Int2BV(value, width) assert value.size() > 0 diff = try_simplify(width - value.size()) if diff > 0: if signed is None: # XXX default to unsigned signed = False if signed: return z3.SignExt(diff, value) else: return z3.ZeroExt(diff, value) return value
def SEXTEND(s, old_size, size): assert old_size <= size if isinstance(s, Symbol): assert s.size == old_size if old_size != size: retv = BitVec(z3.SignExt(size - old_size, s.symbol)) assert retv.size == size return retv.simplify() return s if isInt(s): if s < 0: return s if s & (1 << (old_size - 1)): s |= ((1 << (size)) - (1 << old_size)) return s return s assert False
def resize(n, size, unsigned=True): """Convert `n` into a `z3.BitVecRef` of size `size`. If `n` is larger than `size` bits already, then it will be silently truncated. To check for this, use `truncates(n, size)`. `n` can be an `int`, a `str`, a `bool`, a `z3.BoolRef`, or a `z3.BitVecRef`. For the two boolean types, size must equal 1. If `n` is a `Z3.BitVecRef` and `n.size() < size`, then `n` will be zero-extended if `unsigned == True`, or sign-extended if `unsigned == False`. """ # Handle the non-BitVecRef cases with one-liners if isinstance(n, int): return z3.BitVecVal(n, size) elif isinstance(n, str): return z3.BitVec(n, size) elif isinstance(n, bool) or isinstance(n, z3.BoolRef): if size != 1: raise Exception( "in `resize(n, size)`, if `n` is a bool, `size` must equal 1") return z3.If(n, z3.BitVecVal(1, 1), z3.BitVecVal(0, 1)) elif not isinstance(n, z3.BitVecRef): raise TypeError(n) # Handle the BitVecRef case ext_bits = size - n.size() if ext_bits > 0: if unsigned: return z3.ZeroExt(ext_bits, n) else: return z3.SignExt(ext_bits, n) elif ext_bits < 0: # Silent truncation: see docstring return z3.Extract(size - 1, 0, n) else: return n
def get_solution(bad_num): s = z3.Solver() a, b = z3.BitVec('a', 64), z3.BitVec('b', 64) for idx, num in enumerate([a, b]): r3 = z3.BitVecVal(int(static_nums[idx]), 32) r3 = z3.SignExt(32, r3) asdf = (r3 | (r3 << 32)) stat1 = z3.BitVecVal(static_longs[idx], 64) stat2 = z3.BitVecVal(static_longs[idx + 2], 64) res1 = asdf ^ stat1 r5 = num # s.add(r5 <= 0x7fffffffffffffff) res2 = r5 * stat2 s.add(res1 == res2) for ba, bb in bad_num: s.add(z3.Or(a != ba, b != bb)) assert s.check() == z3.sat ea = s.model().eval(a).as_long() eb = s.model().eval(b).as_long() return ea, eb
def convert_arg(state, arg, typ, size, base): szdiff = size - arg.size() if szdiff > 0: if typ == SINT: arg = z3.SignExt(szdiff, arg) else: arg = z3.ZeroExt(szdiff, arg) elif szdiff < 0: arg = z3.Extract(size - 1, 0, arg) arg = state.evalcon(arg) if typ == UINT: return arg.as_long() elif typ == SINT: return arg.as_signed_long() elif typ == FLOAT: argl = arg.as_long() return ieee_to_float(state.endian, argl, size) else: addr = arg.as_long() string = state.symbolic_string(addr)[0] return state.evaluate_string(string)
def SignExt(self, n: int): assert n >= 0 return BVExpr(self.size + n, z3.SignExt(n, self.z3obj), self.interval.SignExt(n))
def z3_matchLeftAndRight(left,right,op): """Appropriately change the two variables so that they can be used in an expression Parameters ---------- left,right : pyObjectManager.Int.Int or pyObjectManager.Real.Real or pyObjectManager.BitVec.BitVec or pyObjectManager.Char.Char Objects to be matched op : ast.* Operation that will be performed Returns ------- tuple (z3ObjectLeft,z3ObjectRight) tuple of z3 objects that can be used in an expression The purpose of this function is to match two pyObjectManager.* variables to a given ast operation element. Z3 needs to have matched types, and this call will not only match the objects, but also attempt to concretize input wherever possible. Example ------- If you want to auto-match BitVector sizes:: In [1]: import z3, pyState.z3Helpers, ast In [2]: from pySym.pyObjectManager.BitVec import BitVec In [3]: from pySym.pyState import State In [4]: state = State() In [5]: x = BitVec("x",0,16,state=state) In [6]: y = BitVec("y",0,32,state=state) In [7]: l,r = pyState.z3Helpers.z3_matchLeftAndRight(x,y,ast.Add()) In [8]: s = z3.Solver() In [9]: s.add(l + r == 12) In [10]: s Out[10]: [SignExt(16, 0x@0) + 0y@0 == 12] In [11]: s.check() Out[11]: sat """ lType = type(left) rType = type(right) # If it's char, just grab the BitVec object if lType is Char: left = left.variable lType = type(left) if rType is Char: right = right.variable rType = type(right) logger.debug("z3_matchLeftAndRight: Called to match {0} and {1}".format(type(left),type(right))) needBitVec = True if type(op) in [ast.BitXor, ast.BitAnd, ast.BitOr, ast.LShift, ast.RShift] else False # TODO: If the two sizes are different, we'll have problems down the road. bitVecSize = max([c.size for c in [b for b in [left,right] if type(b) is BitVec]],default=Z3_DEFAULT_BITVEC_SIZE) ##################################### # Case: Both are already BitVectors # ##################################### # Check length. Extend if needed. if type(left) is BitVec and type(right) is BitVec: logger.debug("z3_matchLeftAndRight: Matching BitVecLength @ {0} (left={1},right={2})".format(bitVecSize,left.size,right.size)) if left.size < right.size: # Sign extend left's value to match left = z3.SignExt(right.size-left.size,left.getZ3Object()) right = right.getZ3Object() elif right.size > left.size: right = z3.SignExt(left.size-right.size,right.getZ3Object()) left = left.getZ3Object() # Sync-up the output variables left = left.getZ3Object() if type(left) in [Int, Real, BitVec] else left right = right.getZ3Object() if type(right) in [Int, Real, BitVec] else right logger.debug("z3_matchLeftAndRight: Returning {0} and {1}".format(type(left),type(right))) return left,right ##################################### # Case: One is BitVec and one isn't # ##################################### # For now only handling casting of int to BV. Not other way around. if (lType is BitVec and rType is Int) or (rType is Int and needBitVec): # If we need to convert to BitVec and it is a constant, not variable, do so more directly if right.isStatic(): right = z3.BitVecVal(right.getValue(),bitVecSize) # Otherwise cast it. Not optimal, but oh well. else: right = z3_int_to_bv(right.getZ3Object(),size=bitVecSize) if (rType is BitVec and lType is Int) or (lType is Int and needBitVec): if left.isStatic(): left = z3.BitVecVal(left.getValue(),bitVecSize) else: left = z3_int_to_bv(left.getZ3Object(),size=bitVecSize) ################################ # Case: One is Int one is Real # ################################ # So long as this isn't modular arithmetic, let's change to Real things if lType is Real and rType is Int and type(op) is not ast.Mod: if right.isStatic(): right = z3.RealVal(right.getValue()) else: # TODO: Z3 is really bad at handling these... right = z3.ToReal(right.getZ3Object()) if rType is Real and lType is Int and type(op) is not ast.Mod: if left.isStatic(): left = z3.RealVal(left.getValue()) else: # TODO: Z3 is really bad at handling these... left = z3.ToReal(left.getZ3Object()) ############################################ # Case: One is Int one is Real for ast.Mod # ############################################ # So long as this isn't modular arithmetic, let's change to Real things if lType is Real and rType is Int and type(op) is ast.Mod: if left.isStatic(): leftVal = left.getValue() left = z3.IntVal(leftVal) if int(leftVal) != leftVal: logger.warn("Truncating value for Modular Arithmetic. That may or may not be what was intended!") # See if we can swing this the other direction elif right.isStatic(): rightVal = right.getValue() right = z3.RealVal(rightVal) if rType is Real and lType is Int and type(op) is ast.Mod: if right.isStatic(): rightVal = right.getValue() right = z3.IntVal(rightVal) if int(rightVal) != rightVal: logger.warn("Truncating value for Modular Arithmetic. That may or may not be what was intended!") # See if we can swing this the other direction else: left = z3.RealVal(left.getValue()) # Sync-up the output variables left = left.getZ3Object() if type(left) in [Int, Real, BitVec] else left right = right.getZ3Object() if type(right) in [Int, Real, BitVec] else right logger.debug("z3_matchLeftAndRight: Returning {0} and {1}".format(type(left),type(right))) return left,right
@eval.register(Input, BaseSMTTranslator) def _(term, smt): ty = smt.type(term) return z3.Const(term.name, _ty_sort(ty)) def binop(op, defined=None, poisons=None): return lambda term, smt: smt._binary_operator(term, op, defined, poisons) eval.register( AddInst, BaseSMTTranslator, binop(operator.add, poisons={ 'nsw': lambda x, y: z3.SignExt(1, x) + z3.SignExt(1, y) == z3.SignExt( 1, x + y), 'nuw': lambda x, y: z3.ZeroExt(1, x) + z3.ZeroExt(1, y) == z3.ZeroExt( 1, x + y) })) eval.register( SubInst, BaseSMTTranslator, binop(operator.sub, poisons={ 'nsw': lambda x, y: z3.SignExt(1, x) - z3.SignExt(1, y) == z3.SignExt( 1, x - y), 'nuw': lambda x, y: z3.ZeroExt(1, x) - z3.ZeroExt(1, y) == z3.ZeroExt(
def sext(self, ext): if ext < 0: raise ValueError() return type(self).unsized_t[self.size + ext](z3.SignExt( ext, self.value))
def Iop_8Sto64(self, argument): return z3.SignExt(56, argument)
def Iop_32Sto64(self, argument): return z3.SignExt(32, argument)
def Iop_1Sto32(self, argument): return z3.SignExt(31, argument)
def Iop_1Sto64(self, argument): return z3.SignExt(63, argument)
## Use z3.UDiv(x, y) for unsigned division of x by y. ## Use z3.LShR(x, y) for unsigned (logical) right shift of x by y bits. u_avg = z3.UDiv(a, 2) + z3.UDiv(b, 2) + (a & b & 1) s_avg = (a + b) / 2 ## Do not change the code below. ## To compute the reference answers, we extend both a and b by one ## more bit (to 33 bits), add them, divide by two, and shrink back ## down to 32 bits. You are not allowed to "cheat" in this way in ## your answer. az33 = z3.ZeroExt(1, a) bz33 = z3.ZeroExt(1, b) real_u_avg = z3.Extract(31, 0, z3.UDiv(az33 + bz33, 2)) as33 = z3.SignExt(1, a) bs33 = z3.SignExt(1, b) real_s_avg = z3.Extract(31, 0, (as33 + bs33) / 2) def do_check(msg, e): print "Checking", msg, "using Z3 expression:" print " " + str(e).replace("\n", "\n ") solver = z3.Solver() solver.add(e) ok = solver.check() print " Answer for %s: %s" % (msg, ok) if ok == z3.sat: m = solver.model() print " Example solution:", m
@eval.register(Symbol, BaseSMTEncoder) def _(term, smt): ty = smt.type(term) return z3.Const(term.name, _ty_sort(ty)) # TODO: since none of the clients use defined (aside from PLDI2015), maybe # better to move it out def binop(op, defined=None, nonpoison=None, poisons=None): return lambda term, smt: smt._binary_operator( term, op, defined, nonpoison, poisons) eval.register(AddInst, BaseSMTEncoder, binop(operator.add, poisons = { 'nsw': lambda x,y: z3.SignExt(1,x)+z3.SignExt(1,y) == z3.SignExt(1,x+y), 'nuw': lambda x,y: z3.ZeroExt(1,x)+z3.ZeroExt(1,y) == z3.ZeroExt(1,x+y) })) eval.register(SubInst, BaseSMTEncoder, binop(operator.sub, poisons = { 'nsw': lambda x,y: z3.SignExt(1,x)-z3.SignExt(1,y) == z3.SignExt(1,x-y), 'nuw': lambda x,y: z3.ZeroExt(1,x)-z3.ZeroExt(1,y) == z3.ZeroExt(1,x-y) })) eval.register(MulInst, BaseSMTEncoder, binop(operator.mul, poisons = { 'nsw': lambda x,y: z3.SignExt(x.size(),x)*z3.SignExt(x.size(),y) == z3.SignExt(x.size(),x*y),
def to_z3(self, expr): """ Transform an expression into an z3 expression :param expr: str :return: z3 expression """ stack = [] # walk over expression for e in expr.split(" "): # ternary operator if e in self.grammar.op3: op1 = stack.pop() op2 = stack.pop() op3 = stack.pop() op_type = stack.pop() if e == "sign_extend": op1 = self.to_z3_variable(op1) result = z3.SignExt(int(op3) - op1.size(), op1) elif e == "bvextract": op3 = self.to_z3_variable(op3) result = z3.Extract(int(op1), int(op2), op3) stack.append(result) # binary operator elif e in self.grammar.op2: # operands op1 = self.to_z3_variable(stack.pop()) op2 = self.to_z3_variable(stack.pop()) op_type = stack.pop() # operator if e == "bvadd": result = (op2 + op1) elif e == "bvsub": result = (op2 - op1) elif e == "bvmul": result = (op2 * op1) elif e == "bvudiv": result = z3.UDiv(op2, op1) elif e == "bvsdiv": result = (op2 / op1) elif e == "bvurem": result = z3.URem(op2, op1) elif e == "bvsrem": result = z3.SRem(op2, op1) elif e == "bvshl": if self.bitsize == 64: op1 &= 63 else: op1 &= 31 result = (op2 << op1) elif e == "bvlshr": if self.bitsize == 64: op1 &= 63 else: op1 &= 31 result = z3.LShR(op2, op1) elif e == "bvashr": if self.bitsize == 64: op1 &= 63 else: op1 &= 31 result = (op2 >> op1) elif e == "bvand": result = (op2 & op1) elif e == "bvor": result = (op2 | op1) elif e == "bvxor": result = (op2 ^ op1) elif e == "zero_extend": result = z3.ZeroExt(int(op2) - op1.size(), op1) elif e == "bvconcat": result = z3.Concat(op2, op1) stack.append(result) # unary operator elif e in self.grammar.op1: # operand op = self.to_z3_variable(stack.pop()) op_type = stack.pop() # operator if e == "bvnot": result = ~ op elif e == "bvneg": result = - op stack.append(result) else: stack.append(e) return stack.pop()
def _(term, smt): v = smt.eval(term._args[0]) src = smt.type(term._args[0]) tgt = smt.type(term) return z3.SignExt(tgt.width - src.width, v)
# mov eax, [rbp+index] eax = index # sar eax, 1Fh eax >>= 0x1f # mov ecx, eax ecx = eax # xor ecx, [rbp+index] ecx ^= index # sub ecx, eax ecx -= eax # mov edx, 2216757315 edx = z3.BitVecVal(2216757315, 32) # mov eax, ecx eax = ecx # imul edx imul = z3.SignExt(64 - eax.size(), eax) * z3.SignExt(64 - edx.size(), edx) eax = z3.Extract(31, 0, imul) edx = z3.Extract(63, 32, imul) # lea eax, [rdx+rcx] eax = edx + ecx # sar eax, 5 eax >>= 5 # mov edx, eax edx = eax # mov eax, ecx eax = ecx # sar eax, 1Fh eax >>= 0x1f # sub edx, eax edx -= eax # mov eax, edx
def _(x, y): size = x.size() return z3.SignExt(size, x) * z3.SignExt(size, y) == z3.SignExt(size, x * y)
def main() -> int: with open('output.text') as output: env: Dict[int, z3.BitVecRef] states: Dict[int, z3.BitVecRef] new_states: Dict[int, z3.BitVecRef] = {} i: int line: str for i, line in enumerate(output): line_no: int = i + 1 line = line.strip(' \n') front, _, end = line.partition(';') if not front: func_name: str = line.strip(' ;') print('Checking {}'.format(func_name)) if func_name == 'init' or 'next': if func_name == 'next' and len(states) != len(new_states): sys.stderr.write( 'Line {}: {}\n\tNumber of states changed before {}. ' 'Before: {}, after: {}\n'.format( line_no, line, func_name, len(states), len(new_states))) states = new_states new_states = {} else: if len(new_states) != 0: sys.stderr.write('Line {}: {}\n\tState modified in {}\n'.format( line_no, line, func_name)) env = {} continue front_tokens: List[str] = front.split() nid: int = int(front_tokens[0]) name: str = front_tokens[1] args: List[int] = [int(x) for x in front_tokens[2:]] end_tokens: List[str] = end.split() width: int = int(end_tokens[-1].strip('()')) value: int = int(end_tokens[-2], 16) actual: z3.BitVecRef = z3.BitVecVal(value, width) expected: Optional[Union[z3.BitVecRef, z3.BoolRef]] = None assign: bool = end_tokens[1] == '=' try: if name == 'input': pass elif name == 'state': if len(states) != 0 and not assign: expected = states[nid] elif name == 'const': expected = z3.BitVecVal(int(front_tokens[3], 2), width) elif name == 'eq': expected = env[args[1]] == env[args[2]] elif name == 'neq': expected = env[args[1]] != env[args[2]] elif name == 'not': expected = ~env[args[1]] elif name == 'and': expected = env[args[1]] & env[args[2]] elif name == 'or': expected = env[args[1]] | env[args[2]] elif name == 'add': expected = env[args[1]] + env[args[2]] elif name == 'concat': expected = z3.Concat(env[args[1]], env[args[2]]) elif name == 'ite': expected = z3.If(env[args[1]] == z3.BitVecVal(1, 1), env[args[2]], env[args[3]]) elif name == 'redor': expected = z3.BVRedOr(env[args[1]]) elif name == 'sext': expected = z3.SignExt(args[2], env[args[1]]) elif name == 'sgt': expected = env[args[1]] > env[args[2]] elif name == 'slice': expected = z3.Extract(args[2], args[3], env[args[1]]) elif name == 'uext': expected = z3.ZeroExt(args[2], env[args[1]]) elif name == 'bad': if end_tokens[0] != 'ret:': sys.stderr.write('Line {}: {}\n\tMissing ret:\n'.format(line_no, line)) expected = env[args[0]] elif name == 'constraint': if end_tokens[0] != 'ret:': sys.stderr.write('Line {}: {}\n\tMissing ret:\n'.format(line_no, line)) expected = env[args[0]] elif name == 'init' or name == 'next': if not assign: sys.stderr.write('Line {}: {}\n\tMissing =\n'.format(line_no, line)) if int(end_tokens[0]) != args[1]: sys.stderr.write('Line {}: {}\n\tIncorrect NID after =. ' 'Expected: {}, but got: {}\n'.format(line_no, line, args[1], int(end_tokens[0]))) expected = env[args[2]] else: sys.stderr.write( 'Line {}: {}\n\tUnknown node type: {}\n'.format(line_no, line, name)) except KeyError as key_error: sys.stderr.write( 'Line {}: {}\n\tNID not found: {}\n'.format(line_no, line, key_error.args[0])) if expected is not None: if isinstance(expected, z3.BoolRef): expected = z3.If(expected, z3.BitVecVal(1, 1), z3.BitVecVal(0, 1)) if not z3.is_true(z3.simplify(expected == actual)): sys.stderr.write('Line {}: {}\n\tIncorrect value. ' 'Expected: {}, but got: {}\n'.format(line_no, line, z3.simplify(expected), actual)) if assign: if name != 'state' and name != 'input' and name != 'init' and name != 'next': sys.stderr.write( 'Line {}: {}\n\t{} should not modify state.\n'.format(line_no, line, name)) if int(end_tokens[0]) in new_states: sys.stderr.write( 'Line {}: {}\n\tNID already set: {}\n'.format(line_no, line, end_tokens[0])) new_states[int(end_tokens[0])] = actual else: if nid in env: sys.stderr.write( 'Line {}: {}\n\tNID already evaluated: {}\n'.format(line_no, line, nid)) else: env[nid] = actual return 0
def walk_bv_sext (self, formula, args, **kwargs): return z3.SignExt(formula.bv_extend_step(), args[0])
wanted_length = 8 assert wanted_length > 5 # checked at 0x08048a4f sym_username = [z3.BitVec('x{i}'.format(i=i), 8) for i in range(wanted_length)] sym_serial = z3.BitVec('serial', 32) # 2. Translating preloop ''' 0x08048ab6 8b4508 mov eax, dword [arg_8h] 0x08048ab9 83c003 add eax, 3 0x08048abc 0fb600 movzx eax, byte [eax] 0x08048abf 0fbec0 movsx eax, al 0x08048ac2 3537130000 xor eax, 0x1337 0x08048ac7 05eded5e00 add eax, 0x5eeded 0x08048acc 8945f0 mov dword [local_10h], eax ''' eax = z3.SignExt(24, sym_username[3]) # (int32_t)*((uint8_t*)arg_8h + 3) eax ^= z3.BitVecVal(0x1337, 32) eax += z3.BitVecVal(0x5eeded, 32) local_10h = eax # 3. Translating loop header / footer ''' 0x08048acf c745ec000000. mov dword [local_14h], 0 0x08048ad6 eb4e jmp 0x8048b26 ... 0x08048b22 8345ec01 add dword [local_14h], 1 0x08048b26 8b45ec mov eax, dword [local_14h] 0x08048b29 3b45f4 cmp eax, dword [local_ch] 0x08048b2c 7caa jl 0x8048ad8 ''' local_ch = len(sym_username) # this is set by the strnlen at 0x08048a3e