Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #3
0
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
Beispiel #4
0
 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)
Beispiel #5
0
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
Beispiel #6
0
    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
Beispiel #7
0
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)))
Beispiel #8
0
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)))
Beispiel #9
0
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
Beispiel #10
0
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
Beispiel #11
0
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
Beispiel #12
0
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
Beispiel #13
0
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)
Beispiel #14
0
 def SignExt(self, n: int):
     assert n >= 0
     return BVExpr(self.size + n, z3.SignExt(n, self.z3obj),
                   self.interval.SignExt(n))
Beispiel #15
0
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
Beispiel #16
0
@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(
Beispiel #17
0
 def sext(self, ext):
     if ext < 0:
         raise ValueError()
     return type(self).unsized_t[self.size + ext](z3.SignExt(
         ext, self.value))
Beispiel #18
0
 def Iop_8Sto64(self, argument):
     return z3.SignExt(56, argument)
Beispiel #19
0
 def Iop_32Sto64(self, argument):
     return z3.SignExt(32, argument)
Beispiel #20
0
 def Iop_1Sto32(self, argument):
     return z3.SignExt(31, argument)
Beispiel #21
0
 def Iop_1Sto64(self, argument):
     return z3.SignExt(63, argument)
Beispiel #22
0
## 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
Beispiel #23
0
@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),
Beispiel #24
0
    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()
Beispiel #25
0
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)
Beispiel #26
0
# 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
Beispiel #27
0
def _(x, y):
    size = x.size()
    return z3.SignExt(size, x) * z3.SignExt(size, y) == z3.SignExt(size, x * y)
Beispiel #28
0
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
Beispiel #29
0
 def walk_bv_sext (self, formula, args, **kwargs):
     return z3.SignExt(formula.bv_extend_step(), args[0])
Beispiel #30
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