Example #1
0
 def _op_fgeneric_Cmp(self, args):  #pylint:disable=no-self-use
     a, b = args[0].raw_to_fp(), args[1].raw_to_fp()
     return claripy.ite_cases((
         (claripy.fpLT(a, b), claripy.BVV(0x01, 32)),
         (claripy.fpGT(a, b), claripy.BVV(0x00, 32)),
         (claripy.fpEQ(a, b), claripy.BVV(0x40, 32)),
     ), claripy.BVV(0x45, 32))
Example #2
0
 def _op_fgeneric_Cmp(self, args): #pylint:disable=no-self-use
     a, b = args[0].raw_to_fp(), args[1].raw_to_fp()
     return claripy.ite_cases((
         (claripy.fpLT(a, b), claripy.BVV(0x01, 32)),
         (claripy.fpGT(a, b), claripy.BVV(0x00, 32)),
         (claripy.fpEQ(a, b), claripy.BVV(0x40, 32)),
         ), claripy.BVV(0x45, 32))
def test_ite_reverse():
    a = claripy.BVS('a', 32)
    cases = [(a == i, claripy.BVV(i, 32)) for i in range(30)]
    ast = claripy.ite_cases(cases, -1)
    ext_cases = list(claripy.reverse_ite_cases(ast))

    assert sum(1 if case.op == 'And' else 0 for case, _ in ext_cases)
Example #4
0
    def _char_to_val(char, base):
        """
        converts a symbolic char to a number in the given base
        returns expression, result
        expression is a symbolic boolean indicating whether or not it was a valid number
        result is the value
        """
        cases = []
        # 0-9
        max_digit = claripy.BVV(b"9")
        min_digit = claripy.BVV(b"0")
        if base < 10:
            max_digit = claripy.BVV(ord("0") + base, 8)
        is_digit = claripy.And(char >= min_digit, char <= max_digit)
        # return early here so we don't add unnecessary statements
        if base <= 10:
            return is_digit, char - min_digit

        # handle alphabetic chars
        max_char_lower = claripy.BVV(ord("a") + base-10 - 1, 8)
        max_char_upper = claripy.BVV(ord("A") + base-10 - 1, 8)
        min_char_lower = claripy.BVV(ord("a"), 8)
        min_char_upper = claripy.BVV(ord("A"), 8)

        cases.append((is_digit, char - min_digit))
        is_alpha_lower = claripy.And(char >= min_char_lower, char <= max_char_lower)
        cases.append((is_alpha_lower, char - min_char_lower + 10))
        is_alpha_upper = claripy.And(char >= min_char_upper, char <= max_char_upper)
        cases.append((is_alpha_upper, char - min_char_upper + 10))

        expression = claripy.Or(is_digit, is_alpha_lower, is_alpha_upper)
        # use the last case as the default, the expression will encode whether or not it's satisfiable
        result = claripy.ite_cases(cases[:-1], cases[-1][1])

        return expression, result
Example #5
0
    def _op_fgeneric_Cmp(self, args):  #pylint:disable=no-self-use

        # see https://github.com/angr/vex/blob/master/pub/libvex_ir.h#L580
        a, b = args[0].raw_to_fp(), args[1].raw_to_fp()
        return claripy.ite_cases((
            (claripy.fpLT(a, b), claripy.BVV(0x01, 32)),
            (claripy.fpGT(a, b), claripy.BVV(0x00, 32)),
            (claripy.fpEQ(a, b), claripy.BVV(0x40, 32)),
        ), claripy.BVV(0x45, 32))
Example #6
0
def test_ite_reverse():
    a = claripy.BVS('a', 32)
    cases = [(a == i, claripy.BVV(i, 32)) for i in range(30)]
    ast = claripy.ite_cases(cases, -1)
    ext_cases = list(claripy.reverse_ite_cases(ast))

    assert sum(1 if case.op == 'And' else 0 for case, _ in ext_cases)
    for case, val in ext_cases:
        if case.op == 'And':
            assert claripy.is_true(val == -1)
        else:
            assert any(case is orig_case and val is orig_val for orig_case, orig_val in cases)
Example #7
0
    def _op_generic_Perm(self, args):
        ordered_0 = list(reversed(args[0].chop(self._vector_size)))
        ordered_1 = list(reversed(args[1].chop(self._vector_size)))
        res = []
        nbits = int(math.log2(self._vector_size))
        for pword in ordered_1:
            switch = pword[nbits-1:0]
            kill = pword[self._vector_size - 1]
            switched = claripy.ite_cases([(switch == i, v) for i, v in enumerate(ordered_0[:-1])], ordered_0[-1])
            killed = claripy.If(kill == 1, 0, switched)
            res.append(killed)

        return claripy.Concat(*reversed(res))
Example #8
0
    def _char_to_val(char, base):
        """
        converts a symbolic char to a number in the given base
        returns expression, result
        expression is a symbolic boolean indicating whether or not it was a valid number
        result is the value
        """
        cases = []
        # 0-9
        max_digit = claripy.BVV(b"9")
        min_digit = claripy.BVV(b"0")
        if base < 10:
            max_digit = claripy.BVV(ord("0") + base, 8)
        is_digit = claripy.And(char >= min_digit, char <= max_digit)
        # return early here so we don't add unnecessary statements
        if base <= 10:
            return is_digit, char - min_digit

        # handle alphabetic chars
        max_char_lower = claripy.BVV(ord("a") + base - 10 - 1, 8)
        max_char_upper = claripy.BVV(ord("A") + base - 10 - 1, 8)
        min_char_lower = claripy.BVV(ord("a"), 8)
        min_char_upper = claripy.BVV(ord("A"), 8)

        cases.append((is_digit, char - min_digit))
        is_alpha_lower = claripy.And(char >= min_char_lower,
                                     char <= max_char_lower)
        cases.append((is_alpha_lower, char - min_char_lower + 10))
        is_alpha_upper = claripy.And(char >= min_char_upper,
                                     char <= max_char_upper)
        cases.append((is_alpha_upper, char - min_char_upper + 10))

        expression = claripy.Or(is_digit, is_alpha_lower, is_alpha_upper)
        # use the last case as the default, the expression will encode whether or not it's satisfiable
        result = claripy.ite_cases(cases[:-1], cases[-1][1])

        return expression, result
def raw_ite(solver_type):
    s = solver_type()
    x = claripy.BVS("x", 32)
    y = claripy.BVS("y", 32)
    z = claripy.BVS("z", 32)

    ite = claripy.ite_dict(x, {1:11, 2:22, 3:33, 4:44, 5:55, 6:66, 7:77, 8:88, 9:99}, claripy.BVV(0, 32))
    nose.tools.assert_equal(sorted(s.eval(ite, 100)), [ 0, 11, 22, 33, 44, 55, 66, 77, 88, 99 ] )

    ss = s.branch()
    ss.add(ite == 88)
    nose.tools.assert_equal(sorted(ss.eval(ite, 100)), [ 88 ] )
    nose.tools.assert_equal(sorted(ss.eval(x, 100)), [ 8 ] )

    ity = claripy.ite_dict(x, {1:11, 2:22, 3:y, 4:44, 5:55, 6:66, 7:77, 8:88, 9:99}, claripy.BVV(0, 32))
    ss = s.branch()
    ss.add(ity != 11)
    ss.add(ity != 22)
    ss.add(ity != 33)
    ss.add(ity != 44)
    ss.add(ity != 55)
    ss.add(ity != 66)
    ss.add(ity != 77)
    ss.add(ity != 88)
    ss.add(ity != 0)
    ss.add(y == 123)
    nose.tools.assert_equal(sorted(ss.eval(ity, 100)), [ 99, 123 ] )
    nose.tools.assert_equal(sorted(ss.eval(x, 100)), [ 3, 9 ] )
    nose.tools.assert_equal(sorted(ss.eval(y, 100)), [ 123 ] )

    itz = claripy.ite_cases([ (claripy.And(x == 10, y == 20), 33), (claripy.And(x==1, y==2), 3), (claripy.And(x==100, y==200), 333) ], claripy.BVV(0, 32))
    ss = s.branch()
    ss.add(z == itz)
    ss.add(itz != 0)
    nose.tools.assert_equal(ss.eval(y/x, 100), ( 2, ))
    nose.tools.assert_equal(sorted(ss.eval(x, 100)), [ 1, 10, 100 ])
    nose.tools.assert_equal(sorted(ss.eval(y, 100)), [ 2, 20, 200 ])
Example #10
0
def raw_ite(solver_type):
    s = solver_type()
    x = claripy.BVS("x", 32)
    y = claripy.BVS("y", 32)
    z = claripy.BVS("z", 32)

    ite = claripy.ite_dict(x, {1:11, 2:22, 3:33, 4:44, 5:55, 6:66, 7:77, 8:88, 9:99}, claripy.BVV(0, 32))
    nose.tools.assert_equal(sorted(s.eval(ite, 100)), [ 0, 11, 22, 33, 44, 55, 66, 77, 88, 99 ] )

    ss = s.branch()
    ss.add(ite == 88)
    nose.tools.assert_equal(sorted(ss.eval(ite, 100)), [ 88 ] )
    nose.tools.assert_equal(sorted(ss.eval(x, 100)), [ 8 ] )

    ity = claripy.ite_dict(x, {1:11, 2:22, 3:y, 4:44, 5:55, 6:66, 7:77, 8:88, 9:99}, claripy.BVV(0, 32))
    ss = s.branch()
    ss.add(ity != 11)
    ss.add(ity != 22)
    ss.add(ity != 33)
    ss.add(ity != 44)
    ss.add(ity != 55)
    ss.add(ity != 66)
    ss.add(ity != 77)
    ss.add(ity != 88)
    ss.add(ity != 0)
    ss.add(y == 123)
    nose.tools.assert_equal(sorted(ss.eval(ity, 100)), [ 99, 123 ] )
    nose.tools.assert_equal(sorted(ss.eval(x, 100)), [ 3, 9 ] )
    nose.tools.assert_equal(sorted(ss.eval(y, 100)), [ 123 ] )

    itz = claripy.ite_cases([ (claripy.And(x == 10, y == 20), 33), (claripy.And(x==1, y==2), 3), (claripy.And(x==100, y==200), 333) ], claripy.BVV(0, 32))
    ss = s.branch()
    ss.add(z == itz)
    ss.add(itz != 0)
    nose.tools.assert_equal(ss.eval(y/x, 100), ( 2, ))
    nose.tools.assert_equal(sorted(ss.eval(x, 100)), [ 1, 10, 100 ])
    nose.tools.assert_equal(sorted(ss.eval(y, 100)), [ 2, 20, 200 ])
Example #11
0
class ClaripyDataMixin(VEXMixin):
    """
    This mixin provides methods that makes the vex engine process guest code using claripy ASTs as the data domain.
    """

    # util methods

    def _is_true(self, v):
        return claripy.is_true(v)

    def _is_false(self, v):
        return claripy.is_false(v)

    def _optimize_guarded_addr(self, addr, guard):
        # optimization: is the guard the same as the condition inside the address? if so, unpack the address and remove
        # the guarding condition.
        if isinstance(guard, claripy.ast.Base) and guard.op == 'If' \
                and isinstance(addr, claripy.ast.Base) and addr.op == 'If':
            if guard.args[0] is addr.args[0]:
                # the address is guarded by the same guard! unpack the addr
                return addr.args[1]
        return addr

    # consts

    def _handle_vex_const(self, const):
        return value(const.type, const.value)

    # statements

    def _perform_vex_stmt_LoadG(self, addr, alt, guard, dst, cvt, end):
        addr = self._optimize_guarded_addr(addr, guard)
        super()._perform_vex_stmt_LoadG(addr, alt, guard, dst, cvt, end)

    def _perform_vex_stmt_StoreG(self, addr, data, guard, ty, endness,
                                 **kwargs):
        addr = self._optimize_guarded_addr(addr, guard)
        super()._perform_vex_stmt_StoreG(addr, data, guard, ty, endness,
                                         **kwargs)

    # is this right? do I care?
    def _handle_vex_expr_GSPTR(self, expr):
        return zero

    def _handle_vex_expr_VECRET(self, expr):
        return zero

    def _handle_vex_expr_Binder(self, expr):
        return zero

    # simple wrappers to implement the fp/bv data casting

    def _perform_vex_expr_Get(self, offset, ty, **kwargs):
        res = super()._perform_vex_expr_Get(offset, ty, **kwargs)
        if ty.startswith('Ity_F'):
            return res.raw_to_fp()
        else:
            return res

    def _perform_vex_expr_Load(self, addr, ty, endness, **kwargs):
        res = super()._perform_vex_expr_Load(addr, ty, endness, **kwargs)
        if ty.startswith('Ity_F'):
            return res.raw_to_fp()
        else:
            return res

    def _perform_vex_stmt_Put(self, offset, data, **kwargs):
        super()._perform_vex_stmt_Put(offset, data.raw_to_bv(), **kwargs)

    def _perform_vex_stmt_Store(self, addr, data, endness, **kwargs):
        super()._perform_vex_stmt_Store(addr, data.raw_to_bv(), endness,
                                        **kwargs)

    # op support

    def _perform_vex_expr_ITE(self, cond, ifTrue, ifFalse):
        return claripy.If(cond != 0, ifTrue, ifFalse)

    def _perform_vex_expr_Op(self, op, args):
        # TODO: get rid of these hacks (i.e. state options and modes) and move these switches into engine properties
        options = getattr(self.state, 'options', {o.SUPPORT_FLOATING_POINT})
        simop = irop.vexop_to_simop(op,
                                    extended=o.EXTENDED_IROP_SUPPORT
                                    in options,
                                    fp=o.SUPPORT_FLOATING_POINT in options)
        return simop.calculate(*args)

    # ccall support

    def _perform_vex_expr_CCall(self, func_name, ty, args, func=None):
        if func is None:
            try:
                func = getattr(ccall, func_name)
            except AttributeError as e:
                raise errors.UnsupportedCCallError(
                    f"Unsupported ccall {func_name}") from e

        try:
            return func(self.state, *args)
        except ccall.CCallMultivaluedException as e:
            cases, to_replace = e.args
            # pylint: disable=undefined-loop-variable
            for i, arg in enumerate(args):
                if arg is to_replace:
                    break
            else:
                raise errors.UnsupportedCCallError(
                    "Trying to concretize a value which is not an argument")
            evaluated_cases = [(case,
                                func(self.state, *args[:i], value_,
                                     *args[i + 1:])) for case, value_ in cases]
            return claripy.ite_cases(evaluated_cases, value(ty, 0))