Ejemplo n.º 1
0
 def run(self, to_check, length):
     user_input = state.memory.load(to_check, length)
     return claripy.If(user_input == "WQNDNKKWAWOLXBAC", claripy.BVV(1, 32),
                       claripy.BVV(0, 32))
Ejemplo n.º 2
0
    def exec_branch(self, state):  # pylint:disable=invalid-name
        """Execute forward from a state, queuing new states if needed."""
        logger.debug("Constraints: %s", state.solver.constraints)

        def solution(variable):
            """Returns the solution. There must be one or we fail."""
            solutions = state.solver.eval(variable, 2)
            if len(solutions) > 1:
                raise MultipleSolutionsError(
                    "Multiple solutions for %s (%#x)" %
                    (variable, self.code[state.pc]))
            solution = solutions[0]
            return solution if isinstance(solution,
                                          numbers.Number) else solution.value

        self.code.pc = state.pc

        while True:
            if state.pc >= len(self.code):
                return True

            op = self.code[state.pc]
            self.code.pc += 1
            self.coverage[state.pc] += 1

            logger.debug("NEW STEP")
            logger.debug("Memory: %s", state.memory)
            logger.debug("Stack: %s", state.stack)
            logger.debug("PC: %i, %#x", state.pc, op)

            assert self.code.pc == state.pc + 1
            assert isinstance(op, numbers.Number)
            assert all(
                isinstance(i, claripy.ast.base.BV) for i in
                state.stack), "The stack musty only contains claripy BV's"

            # Trivial operations first
            if not self.code.is_valid_opcode(state.pc):
                raise utils.CodeError("Trying to execute PUSH data")
            elif op == 254:  # INVALID opcode
                raise utils.CodeError("designed INVALID opcode")
            elif op == opcode_values.JUMPDEST:
                pass
            elif op == opcode_values.ADD:
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                state.stack_push(s0 + s1)
            elif op == opcode_values.SUB:
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                state.stack_push(s0 - s1)
            elif op == opcode_values.MUL:
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                state.stack_push(s0 * s1)
            elif op == opcode_values.DIV:
                # We need to use claripy.LShR instead of a division if possible,
                # because the solver is bad dealing with divisions, better
                # with shifts. And we need shifts to handle the solidity ABI
                # for function selection.
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                try:
                    s1 = solution(s1)  # pylint:disable=invalid-name
                except MultipleSolutionsError:
                    state.stack_push(claripy.If(s1 == 0, BVV_0, s0 / s1))
                else:
                    if s1 == 0:
                        state.stack_push(BVV_0)
                    elif s1 == 1:
                        state.stack_push(s0)
                    elif s1 & (s1 - 1) == 0:
                        exp = int(math.log(s1, 2))
                        state.stack_push(s0.LShR(exp))
                    else:
                        state.stack_push(s0 / s1)
            elif op == opcode_values.SDIV:
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                try:
                    s1 = solution(s1)
                except MultipleSolutionsError:
                    state.stack_push(claripy.If(s1 == 0, BVV_0, s0.SDiv(s1)))
                else:
                    state.stack_push(BVV_0 if s1 == 0 else s0.SDiv(s1))
            elif op == opcode_values.MOD:
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                try:
                    s1 = solution(s1)
                except MultipleSolutionsError:
                    state.stack_push(claripy.If(s1 == 0, BVV_0, s0 % s1))
                else:
                    state.stack_push(BVV_0 if s1 == 0 else s0 % s1)
            elif op == opcode_values.SMOD:
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                try:
                    s1 = solution(s1)
                except MultipleSolutionsError:
                    state.stack_push(claripy.If(s1 == 0, BVV_0, s0.SMod(s1)))
                else:
                    state.stack_push(BVV_0 if s1 == 0 else s0.SMod(s1))
            elif op == opcode_values.ADDMOD:
                s0, s1, s2 = state.stack_pop(), state.stack_pop(
                ), state.stack_pop()
                try:
                    s2 = solution(s2)
                except MultipleSolutionsError:
                    state.stack_push(claripy.If(s2 == 0, BVV_0,
                                                (s0 + s1) % s2))
                else:
                    state.stack_push(BVV_0 if s2 == 0 else (s0 + s1) % s2)
            elif op == opcode_values.MULMOD:
                s0, s1, s2 = state.stack_pop(), state.stack_pop(
                ), state.stack_pop()
                try:
                    s2 = solution(s2)
                except MultipleSolutionsError:
                    state.stack_push(claripy.If(s2 == 0, BVV_0,
                                                (s0 * s1) % s2))
                else:
                    state.stack_push(BVV_0 if s2 == 0 else (s0 * s1) % s2)
            elif op == opcode_values.SHL:
                shift, value = state.stack_pop(), state.stack_pop()
                state.stack_push(value << shift)
            elif op == opcode_values.SHR:
                shift, value = state.stack_pop(), state.stack_pop()
                state.stack_push(value.LShR(shift))
            elif op == opcode_values.SAR:
                shift, value = state.stack_pop(), state.stack_pop()
                state.stack_push(claripy.RotateRight(value, shift))
            elif op == opcode_values.EXP:
                base, exponent = state.stack_pop(), state.stack_pop()
                base_sol = solution(base)
                if base_sol == 2:
                    state.stack_push(1 << exponent)
                else:
                    try:
                        exponent_sol = solution(exponent)
                    except MultipleSolutionsError:
                        state.stack_push(exponent)  # restore stack
                        state.stack_push(base)
                        self.add_for_fuzzing(state, exponent,
                                             EXP_EXPONENT_FUZZ)
                        return False
                    else:
                        state.stack_push(
                            claripy.BVV(base_sol**exponent_sol, 256))
            elif op == opcode_values.LT:
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                state.stack_push(bool_to_bv(claripy.ULT(s0, s1)))
            elif op == opcode_values.GT:
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                state.stack_push(bool_to_bv(claripy.UGT(s0, s1)))
            elif op == opcode_values.SLT:
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                state.stack_push(bool_to_bv(claripy.SLT(s0, s1)))
            elif op == opcode_values.SGT:
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                state.stack_push(bool_to_bv(claripy.SGT(s0, s1)))
            elif op == opcode_values.SIGNEXTEND:
                # TODO: Use Claripy's SignExt that should do exactly that.
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                # s0 is the number of bits. s1 the number we want to extend.
                s0 = solution(s0)
                if s0 <= 31:
                    sign_bit = 1 << (s0 * 8 + 7)
                    state.stack_push(
                        claripy.If(
                            s1 & sign_bit == 0,
                            s1 & (sign_bit - 1),
                            s1 | ((1 << 256) - sign_bit),
                        ))
                else:
                    state.stack_push(s1)
            elif op == opcode_values.EQ:
                s0, s1 = state.stack_pop(), state.stack_pop()
                state.stack_push(bool_to_bv(s0 == s1))
            elif op == opcode_values.ISZERO:
                state.stack_push(bool_to_bv(state.stack_pop() == BVV_0))
            elif op == opcode_values.AND:
                s0, s1 = state.stack_pop(), state.stack_pop()
                state.stack_push(s0 & s1)
            elif op == opcode_values.OR:
                s0, s1 = state.stack_pop(), state.stack_pop()
                state.stack_push(s0 | s1)
            elif op == opcode_values.XOR:
                s0, s1 = state.stack_pop(), state.stack_pop()
                state.stack_push(s0 ^ s1)
            elif op == opcode_values.NOT:
                state.stack_push(~state.stack_pop())
            elif op == opcode_values.BYTE:
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                state.stack_push(
                    s1.LShR(claripy.If(s0 > 31, 32, 31 - s0) * 8) & 0xFF)

            elif op == opcode_values.PC:
                state.stack_push(bvv(state.pc))
            elif op == opcode_values.GAS:
                state.stack_push(state.env.gas)
            elif op == opcode_values.ADDRESS:
                state.stack_push(state.env.address)
            elif op == opcode_values.BALANCE:
                addr = solution(state.stack_pop())
                if addr != solution(state.env.address):
                    raise utils.InterpreterError(
                        state,
                        "Can only query balance of the current contract for now"
                    )
                state.stack_push(state.env.balance)
            elif op == opcode_values.ORIGIN:
                state.stack_push(state.env.origin)
            elif op == opcode_values.CALLER:
                state.stack_push(state.env.caller)
            elif op == opcode_values.CALLVALUE:
                state.stack_push(state.env.value)
            elif op == opcode_values.BLOCKHASH:
                block_num = state.stack_pop()
                if block_num not in state.env.block_hashes:
                    state.env.block_hashes[block_num] = claripy.BVS(
                        "blockhash[%s]" % block_num, 256)
                state.stack_push(state.env.block_hashes[block_num])
            elif op == opcode_values.TIMESTAMP:
                state.stack_push(state.env.block_timestamp)
            elif op == opcode_values.NUMBER:
                state.stack_push(state.env.block_number)
            elif op == opcode_values.COINBASE:
                state.stack_push(state.env.coinbase)
            elif op == opcode_values.DIFFICULTY:
                state.stack_push(state.env.difficulty)
            elif op == opcode_values.POP:
                state.stack_pop()
            elif op == opcode_values.JUMP:
                addr = solution(state.stack_pop())
                if addr >= len(self.code
                               ) or self.code[addr] != opcode_values.JUMPDEST:
                    raise utils.CodeError("Invalid jump (%i)" % addr)
                state.pc = addr
                self.add_branch(state)
                return False
            elif op == opcode_values.JUMPI:
                addr, condition = solution(
                    state.stack_pop()), state.stack_pop()
                state_false = state.copy()
                state.solver.add(condition != BVV_0)
                state_false.solver.add(condition == BVV_0)
                state_false.pc += 1
                self.add_branch(state_false)
                state.pc = addr
                if (state.pc >= len(self.code)
                        or self.code[state.pc] != opcode_values.JUMPDEST):
                    raise utils.CodeError("Invalid jump (%i)" % (state.pc - 1))
                self.add_branch(state)
                return False
            elif opcode_values.PUSH1 <= op <= opcode_values.PUSH32:
                pushnum = op - opcode_values.PUSH1 + 1
                raw_value = self.code.read(pushnum)
                state.pc += pushnum
                state.stack_push(
                    bvv(int.from_bytes(raw_value, byteorder="big")))
            elif opcode_values.DUP1 <= op <= opcode_values.DUP16:
                depth = op - opcode_values.DUP1 + 1
                state.stack_push(state.stack[-depth])
            elif opcode_values.SWAP1 <= op <= opcode_values.SWAP16:
                depth = op - opcode_values.SWAP1 + 1
                temp = state.stack[-depth - 1]
                state.stack[-depth - 1] = state.stack[-1]
                state.stack[-1] = temp
            elif opcode_values.LOG0 <= op <= opcode_values.LOG4:
                depth = op - opcode_values.LOG0
                mstart, msz = (state.stack_pop(), state.stack_pop())
                topics = [state.stack_pop() for x in range(depth)]
            elif op == opcode_values.SHA3:
                start, length = solution(state.stack_pop()), solution(
                    state.stack_pop())
                memory = state.memory.read(start, length)
                state.stack_push(Sha3(memory))
            elif op == opcode_values.STOP:
                return True
            elif op == opcode_values.RETURN:
                return True

            elif op == opcode_values.CALLDATALOAD:
                index = state.stack_pop()
                try:
                    index_sol = solution(index)
                except MultipleSolutionsError:
                    state.stack_push(index)  # restore the stack
                    self.add_for_fuzzing(state, index, CALLDATALOAD_INDEX_FUZZ)
                    return False
                state.stack_push(state.env.calldata.read(index_sol, 32))
            elif op == opcode_values.CALLDATASIZE:
                state.stack_push(state.env.calldata_size)
            elif op == opcode_values.CALLDATACOPY:
                old_state = state.copy()
                mstart, dstart, size = (
                    state.stack_pop(),
                    state.stack_pop(),
                    state.stack_pop(),
                )
                mstart, dstart = solution(mstart), solution(dstart)
                try:
                    size = solution(size)
                except MultipleSolutionsError:
                    self.add_for_fuzzing(old_state, size,
                                         CALLDATACOPY_SIZE_FUZZ)
                    return False
                state.memory.copy_from(state.env.calldata, mstart, dstart,
                                       size)
            elif op == opcode_values.CODESIZE:
                state.stack_push(bvv(len(self.code)))
            elif op == opcode_values.EXTCODESIZE:
                addr = state.stack_pop()
                if (addr == state.env.address).is_true():
                    state.stack_push(bvv(len(self.code)))
                else:
                    # TODO: Improve that... It's clearly not constraining enough.
                    state.stack_push(claripy.BVS("EXTCODESIZE[%s]" % addr,
                                                 256))

            elif op == opcode_values.EXTCODECOPY:
                old_state = state.copy()
                addr = state.stack_pop()
                mem_start = solution(state.stack_pop())
                code_start = solution(state.stack_pop())

                size = state.stack_pop()
                try:
                    size = solution(size)
                except MultipleSolutionsError:
                    # TODO: Fuzz.
                    # self.add_for_fuzzing(old_state, size, [])
                    # return False
                    raise
                state.memory.write(
                    mem_start,
                    size,
                    claripy.BVS("EXTCODE[%s from %s]" % (addr, code_start),
                                size * 8),
                )

            elif op == opcode_values.CODECOPY:
                mem_start, code_start, size = [
                    solution(state.stack_pop()) for _ in range(3)
                ]
                for i in range(size):
                    if code_start + i < len(state.env.code):
                        state.memory.write(
                            mem_start + i,
                            1,
                            claripy.BVV(state.env.code[code_start + i], 8),
                        )
                    else:
                        state.memory.write(mem_start + i, 1, claripy.BVV(0, 8))

            elif op == opcode_values.MLOAD:
                index = solution(state.stack_pop())
                state.stack_push(state.memory.read(index, 32))
            elif op == opcode_values.MSTORE:
                index, value = solution(state.stack_pop()), state.stack_pop()
                state.memory.write(index, 32, value)
            elif op == opcode_values.MSTORE8:
                index, value = solution(state.stack_pop()), state.stack_pop()
                state.memory.write(index, 1, value[7:0])
            elif op == opcode_values.MSIZE:
                state.stack_push(bvv(state.memory.size()))

            elif op == opcode_values.SLOAD:
                state.pc += 1
                key = state.stack_pop()
                for w_key, w_value in state.storage_written.items():
                    read_written = [w_key == key]
                    if state.solver.satisfiable(
                            extra_constraints=read_written):
                        new_state = state.copy()
                        new_state.solver.add(read_written)
                        new_state.stack_push(w_value)
                        self.add_branch(new_state)
                    state.solver.add(w_key != key)
                if state.solver.satisfiable():
                    assert key not in state.storage_written
                    if key not in state.storage_read:
                        state.storage_read[key] = claripy.BVS(
                            "storage[%s]" % key, 256)
                    state.stack_push(state.storage_read[key])
                    self.add_branch(state)
                return

            elif op == opcode_values.SSTORE:
                state.pc += 1
                key = state.stack_pop()
                value = state.stack_pop()
                for w_key, w_value in state.storage_written.items():
                    read_written = [w_key == key]
                    if state.solver.satisfiable(
                            extra_constraints=read_written):
                        new_state = state.copy()
                        new_state.solver.add(read_written)
                        new_state.storage_written[w_key] = value
                        self.add_branch(new_state)
                        state.solver.add(w_key != key)
                if state.solver.satisfiable():
                    assert key not in state.storage_written
                    state.storage_written[key] = value
                    self.add_branch(state)
                return

            elif op == opcode_values.CALL:
                state.pc += 1

                # pylint:disable=unused-variable
                gas, to_, value, meminstart, meminsz, memoutstart, memoutsz = (
                    state.stack_pop() for _ in range(7))

                # First possibility: the call fails
                # (always possible with a call stack big enough)
                state_fail = state.copy()
                state_fail.stack_push(BVV_0)
                self.add_branch(state_fail)

                # Second possibility: success.
                state.calls.append((memoutsz, memoutstart, meminsz, meminstart,
                                    value, to_, gas))

                memoutsz = solution(memoutsz)
                if memoutsz != 0:
                    # If we expect some output, let's constraint the call to
                    # be to a contract that we do control. Otherwise it could
                    # return anything...
                    state.solver.add(to_[159:0] == utils.DEFAULT_CALLER[159:0])

                    memoutstart = solution(memoutstart)
                    state.memory.write(
                        memoutstart,
                        memoutsz,
                        claripy.BVS("CALL_RETURN[%s]" % to_, memoutsz * 8),
                    )

                state.stack_push(BVV_1)
                self.add_branch(state)
                return False

            elif op == opcode_values.DELEGATECALL:
                state.pc += 1

                # pylint:disable=unused-variable
                gas, to_, meminstart, meminsz, memoutstart, memoutsz = (
                    state.stack_pop() for _ in range(6))

                # First possibility: the call fails
                # (always possible with a call stack big enough)
                state_fail = state.copy()
                state_fail.stack_push(BVV_0)
                self.add_branch(state_fail)

                # If the call is to a specific contract we don't control,
                # don't assume it could return anything, or even be successful.
                # So we say we need to be able to call an arbitrary contract.
                state.solver.add(to_[159:0] == utils.DEFAULT_CALLER[159:0])

                # Second possibility: success.
                state.calls.append(
                    (memoutsz, memoutstart, meminsz, meminstart, to_, gas))

                memoutsz = solution(memoutsz)
                if memoutsz != 0:
                    memoutstart = solution(memoutstart)
                    state.memory.write(
                        memoutstart,
                        memoutsz,
                        claripy.BVS("DELEGATECALL_RETURN[%s]" % to_,
                                    memoutsz * 8),
                    )

                state.stack_push(BVV_1)
                self.add_branch(state)
                return False

            elif op == opcode_values.RETURNDATASIZE:
                state.stack_push(claripy.BVS("RETURNDATASIZE", 256))

            elif op == opcode_values.RETURNDATACOPY:
                old_state = state.copy()
                mem_start_position = solution(state.stack_pop())
                returndata_start_position = solution(state.stack_pop())

                size = state.stack_pop()
                try:
                    size = solution(size)
                except MultipleSolutionsError:
                    self.add_for_fuzzing(old_state, size,
                                         RETURNDATACOPY_SIZE_FUZZ)
                    return False

                state.memory.write(mem_start_position, size,
                                   claripy.BVS("RETURNDATACOPY", size * 8))

            elif op == opcode_values.SELFDESTRUCT:
                state.selfdestruct_to = state.stack[-1]
                return True

            elif op == opcode_values.REVERT:
                return False

            else:
                raise utils.InterpreterError(state, "Unknown opcode %#x" % op)

            state.pc += 1
Ejemplo n.º 3
0
 def _perform_vex_expr_ITE(self, cond, ifTrue, ifFalse):
     return claripy.If(cond != 0, ifTrue, ifFalse)
Ejemplo n.º 4
0
    def interpret(self, startpos, args, addr=None, simfd=None):
        """
        implement scanf - extract formatted data from memory or a file according to the stored format
        specifiers and store them into the pointers extracted from `args`.

        :param startpos:    The index of the first argument corresponding to the first format element
        :param args:        A function which, given the index of an argument to the function, returns that argument
        :param addr:        The address in the memory to extract data from, or...
        :param simfd:       A file descriptor to use for reading data from
        :return:            The number of arguments parsed
        """
        if simfd is not None and isinstance(simfd.read_storage, SimPackets):
            argnum = startpos
            for component in self.components:
                if type(component) is bytes:
                    sdata, _ = simfd.read_data(len(component),
                                               short_reads=False)
                    self.state.add_constraints(sdata == component)
                elif isinstance(component, claripy.Bits):
                    sdata, _ = simfd.read_data(len(component) // 8,
                                               short_reads=False)
                    self.state.add_constraints(sdata == component)
                elif component.spec_type == b's':
                    if component.length_spec is None:
                        sdata, slen = simfd.read_data(
                            self.state.libc.buf_symbolic_bytes)
                    else:
                        sdata, slen = simfd.read_data(component.length_spec)
                    for byte in sdata.chop(8):
                        self.state.add_constraints(
                            claripy.And(*[
                                byte != char for char in self.SCANF_DELIMITERS
                            ]))
                    self.state.memory.store(args(argnum), sdata, size=slen)
                    self.state.memory.store(
                        args(argnum) + slen, claripy.BVV(0, 8))
                    argnum += 1
                elif component.spec_type == b'c':
                    sdata, _ = simfd.read_data(1, short_reads=False)
                    self.state.memory.store(args(argnum), sdata)
                    argnum += 1
                else:
                    bits = component.size * 8
                    if component.spec_type == b'x':
                        base = 16
                    elif component.spec_type == b'o':
                        base = 8
                    else:
                        base = 10

                    # here's the variable representing the result of the parsing
                    target_variable = self.state.solver.BVS(
                        'scanf_' + component.string.decode(),
                        bits,
                        key=('api', 'scanf', argnum - startpos,
                             component.string))
                    negative = claripy.SLT(target_variable, 0)

                    # how many digits does it take to represent this variable fully?
                    max_digits = int(math.ceil(math.log(2**bits, base)))

                    # how many digits does the format specify?
                    spec_digits = component.length_spec

                    # how many bits can we specify as input?
                    available_bits = float(
                        'inf'
                    ) if spec_digits is None else spec_digits * math.log(
                        base, 2)
                    not_enough_bits = available_bits < bits

                    # how many digits will we model this input as?
                    digits = max_digits if spec_digits is None else spec_digits

                    # constrain target variable range explicitly if it can't take on all possible values
                    if not_enough_bits:
                        self.state.add_constraints(
                            self.state.solver.And(
                                self.state.solver.SLE(target_variable,
                                                      (base**digits) - 1),
                                self.state.solver.SGE(
                                    target_variable,
                                    -(base**(digits - 1) - 1))))

                    # perform the parsing in reverse - constrain the input digits to be the string version of the input
                    # this only works because we're reading from a packet stream and therefore nobody has the ability
                    # to add other constraints to this data!
                    # this makes z3's job EXTREMELY easy
                    sdata, _ = simfd.read_data(digits, short_reads=False)
                    for i, digit in enumerate(reversed(sdata.chop(8))):
                        digit_value = (target_variable // (base**i)) % base
                        digit_ascii = digit_value + ord('0')
                        if base > 10:
                            digit_ascii = claripy.If(
                                digit_value >= 10,
                                digit_value + (-10 + ord('a')), digit_ascii)

                        # if there aren't enough bits, we can increase the range by accounting for the possibility that
                        # the first digit is a minus sign
                        if not_enough_bits:
                            if i == digits - 1:
                                neg_digit_ascii = ord('-')
                            else:
                                neg_digit_value = (-target_variable //
                                                   (base**i)) % base
                                neg_digit_ascii = neg_digit_value + ord('0')
                                if base > 10:
                                    neg_digit_ascii = claripy.If(
                                        neg_digit_value >= 10,
                                        neg_digit_value + (-10 + ord('a')),
                                        neg_digit_ascii)

                            digit_ascii = claripy.If(negative, neg_digit_ascii,
                                                     digit_ascii)

                        self.state.add_constraints(digit == digit_ascii[7:0])

                    self.state.memory.store(
                        args(argnum),
                        target_variable,
                        endness=self.state.arch.memory_endness)
                    argnum += 1

            return argnum - startpos

        if simfd is not None:
            region = simfd.read_storage
            addr = simfd._pos if hasattr(
                simfd, '_pos') else simfd._read_pos  # XXX THIS IS BAD
        else:
            region = self.parser.state.memory

        bits = self.parser.state.arch.bits
        failed = self.parser.state.solver.BVV(0, bits)
        argpos = startpos
        position = addr
        for component in self.components:
            if isinstance(component, bytes):
                # TODO we skip non-format-specifiers in format string interpretation for now
                # if the region doesn't match the concrete component, we need to return immediately
                pass
            else:
                fmt_spec = component
                try:
                    dest = args(argpos)
                except SimProcedureArgumentError:
                    dest = None
                if fmt_spec.spec_type == b's':
                    # set some limits for the find
                    max_str_len = self.parser.state.libc.max_str_len
                    max_sym_bytes = self.parser.state.libc.buf_symbolic_bytes

                    # has the length of the format been limited by the string itself?
                    if fmt_spec.length_spec is not None:
                        max_str_len = fmt_spec.length_spec
                        max_sym_bytes = fmt_spec.length_spec

                    # TODO: look for limits on other characters which scanf is sensitive to, '\x00', '\x20'
                    ohr, _, match_indices = region.find(
                        position,
                        self.parser.state.solver.BVV(b'\n'),
                        max_str_len,
                        max_symbolic_bytes=max_sym_bytes)

                    if not match_indices:
                        # if no newline is found, mm is position + max_strlen
                        mm = position + max_str_len
                        # we're just going to concretize the length, load will do this anyways
                        length = self.parser.state.solver.max_int(mm -
                                                                  position)
                    else:
                        # a newline is found, or a max length is specified with the specifier
                        length = max(match_indices)
                    src_str = region.load(position, length)

                    # TODO all of these should be delimiters we search for above
                    # add that the contents of the string cannot be any scanf %s string delimiters
                    for delimiter in set(FormatString.SCANF_DELIMITERS):
                        delim_bvv = self.parser.state.solver.BVV(delimiter)
                        for i in range(length):
                            self.parser.state.add_constraints(
                                region.load(position + i, 1) != delim_bvv)

                    # write it out to the pointer
                    self.parser.state.memory.store(dest, src_str)
                    # store the terminating null byte
                    self.parser.state.memory.store(
                        dest + length, self.parser.state.solver.BVV(0, 8))

                    position += length

                else:

                    # XXX: atoi only supports strings of one byte
                    if fmt_spec.spec_type in [b'd', b'i', b'u', b'x']:
                        base = 16 if fmt_spec.spec_type == b'x' else 10
                        status, i, num_bytes = self.parser._sim_atoi_inner(
                            position,
                            region,
                            base=base,
                            read_length=fmt_spec.length_spec)
                        # increase failed count if we were unable to parse it
                        failed = self.parser.state.solver.If(
                            status, failed, failed + 1)
                        position += num_bytes
                    elif fmt_spec.spec_type == b'c':
                        i = region.load(position, 1)
                        i = i.zero_extend(bits - 8)
                        position += 1
                    else:
                        raise SimProcedureError(
                            "unsupported format spec '%s' in interpret" %
                            fmt_spec.spec_type)

                    i = self.parser.state.solver.Extract(
                        fmt_spec.size * 8 - 1, 0, i)
                    self.parser.state.memory.store(
                        dest,
                        i,
                        size=fmt_spec.size,
                        endness=self.parser.state.arch.memory_endness)

                argpos += 1

        if simfd is not None:
            _, realsize = simfd.read_data(position - addr)
            self.state.add_constraints(realsize == position - addr)

        return (argpos - startpos) - failed
Ejemplo n.º 5
0
 def _fgeneric_minmax(cmp_op, a, b):
     a, b = a.raw_to_fp(), b.raw_to_fp()
     return claripy.If(cmp_op(a, b), a, b)
Ejemplo n.º 6
0
 def _op_generic_CmpORD(self, args):
     x = args[0]
     y = args[1]
     s = self._from_size
     cond = x < y if self.is_signed else claripy.ULT(x, y)
     return claripy.If(x == y, claripy.BVV(0x2, s), claripy.If(cond, claripy.BVV(0x8, s), claripy.BVV(0x4, s)))
Ejemplo n.º 7
0
 def if_builder(self, element, a, x):
     return claripy.If(element == int(x, 16), x, a)
Ejemplo n.º 8
0
def test_vsa_constraint_to_si():
    # Set backend
    b = claripy.backend_vsa
    s = claripy.LightFrontend(claripy.backend_vsa)  #pylint:disable=unused-variable

    SI = claripy.SI
    BVV = claripy.BVV

    claripy.vsa.strided_interval.allow_dsis = False

    #
    # If(SI == 0, 1, 0) == 1
    #

    s1 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=2)
    ast_true = (claripy.If(s1 == BVV(0, 32), BVV(1, 1), BVV(0,
                                                            1)) == BVV(1, 1))
    ast_false = (claripy.If(s1 == BVV(0, 32), BVV(1, 1), BVV(0, 1)) != BVV(
        1, 1))

    trueside_sat, trueside_replacement = b.constraint_to_si(ast_true)
    nose.tools.assert_equal(trueside_sat, True)
    nose.tools.assert_equal(len(trueside_replacement), 1)
    nose.tools.assert_true(trueside_replacement[0][0] is s1)
    # True side: claripy.SI<32>0[0, 0]
    nose.tools.assert_true(
        claripy.is_true(trueside_replacement[0][1] == claripy.SI(
            bits=32, stride=0, lower_bound=0, upper_bound=0)))

    falseside_sat, falseside_replacement = b.constraint_to_si(ast_false)
    nose.tools.assert_equal(falseside_sat, True)
    nose.tools.assert_equal(len(falseside_replacement), 1)
    nose.tools.assert_true(falseside_replacement[0][0] is s1)
    # False side; claripy.SI<32>1[1, 2]
    nose.tools.assert_true(
        claripy.is_true(falseside_replacement[0][1].identical(
            SI(bits=32, stride=1, lower_bound=1, upper_bound=2))))

    #
    # If(SI == 0, 1, 0) <= 1
    #

    s1 = SI(bits=32, stride=1, lower_bound=0, upper_bound=2)
    ast_true = (claripy.If(s1 == BVV(0, 32), BVV(1, 1), BVV(0, 1)) <= BVV(
        1, 1))
    ast_false = (claripy.If(s1 == BVV(0, 32), BVV(1, 1), BVV(0, 1)) > BVV(
        1, 1))

    trueside_sat, trueside_replacement = b.constraint_to_si(ast_true)
    nose.tools.assert_equal(trueside_sat, True)  # Always satisfiable

    falseside_sat, falseside_replacement = b.constraint_to_si(ast_false)
    nose.tools.assert_equal(falseside_sat, False)  # Not sat

    #
    # If(SI == 0, 20, 10) > 15
    #

    s1 = SI(bits=32, stride=1, lower_bound=0, upper_bound=2)
    ast_true = (claripy.If(s1 == BVV(0, 32), BVV(20, 32), BVV(10, 32)) > BVV(
        15, 32))
    ast_false = (claripy.If(s1 == BVV(0, 32), BVV(20, 32), BVV(10, 32)) <= BVV(
        15, 32))

    trueside_sat, trueside_replacement = b.constraint_to_si(ast_true)
    nose.tools.assert_equal(trueside_sat, True)
    nose.tools.assert_equal(len(trueside_replacement), 1)
    nose.tools.assert_true(trueside_replacement[0][0] is s1)
    # True side: SI<32>0[0, 0]
    nose.tools.assert_true(
        claripy.is_true(trueside_replacement[0][1] == SI(
            bits=32, stride=0, lower_bound=0, upper_bound=0)))

    falseside_sat, falseside_replacement = b.constraint_to_si(ast_false)
    nose.tools.assert_equal(falseside_sat, True)
    nose.tools.assert_equal(len(falseside_replacement), 1)
    nose.tools.assert_true(falseside_replacement[0][0] is s1)
    # False side; SI<32>1[1, 2]
    nose.tools.assert_true(
        claripy.is_true(falseside_replacement[0][1].identical(
            SI(bits=32, stride=1, lower_bound=1, upper_bound=2))))

    #
    # If(SI == 0, 20, 10) >= 15
    #

    s1 = SI(bits=32, stride=1, lower_bound=0, upper_bound=2)
    ast_true = (claripy.If(s1 == BVV(0, 32), BVV(15, 32), BVV(10, 32)) >= BVV(
        15, 32))
    ast_false = (claripy.If(s1 == BVV(0, 32), BVV(15, 32), BVV(10, 32)) < BVV(
        15, 32))

    trueside_sat, trueside_replacement = b.constraint_to_si(ast_true)
    nose.tools.assert_equal(trueside_sat, True)
    nose.tools.assert_equal(len(trueside_replacement), 1)
    nose.tools.assert_true(trueside_replacement[0][0] is s1)
    # True side: SI<32>0[0, 0]
    nose.tools.assert_true(
        claripy.is_true(trueside_replacement[0][1] == SI(
            bits=32, stride=0, lower_bound=0, upper_bound=0)))

    falseside_sat, falseside_replacement = b.constraint_to_si(ast_false)
    nose.tools.assert_equal(falseside_sat, True)
    nose.tools.assert_equal(len(falseside_replacement), 1)
    nose.tools.assert_true(falseside_replacement[0][0] is s1)
    # False side; SI<32>0[0,0]
    nose.tools.assert_true(
        claripy.is_true(falseside_replacement[0][1].identical(
            SI(bits=32, stride=0, lower_bound=0, upper_bound=0))))

    #
    # Extract(0, 0, Concat(BVV(0, 63), If(SI == 0, 1, 0))) == 1
    #

    s2 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=2)
    ast_true = (claripy.Extract(
        0, 0,
        claripy.Concat(BVV(0, 63), claripy.If(s2 == 0, BVV(1, 1),
                                              BVV(0, 1)))) == 1)
    ast_false = (claripy.Extract(
        0, 0,
        claripy.Concat(BVV(0, 63), claripy.If(s2 == 0, BVV(1, 1), BVV(0, 1))))
                 != 1)

    trueside_sat, trueside_replacement = b.constraint_to_si(ast_true)
    nose.tools.assert_equal(trueside_sat, True)
    nose.tools.assert_equal(len(trueside_replacement), 1)
    nose.tools.assert_true(trueside_replacement[0][0] is s2)
    # True side: claripy.SI<32>0[0, 0]
    nose.tools.assert_true(
        claripy.is_true(trueside_replacement[0][1].identical(
            SI(bits=32, stride=0, lower_bound=0, upper_bound=0))))

    falseside_sat, falseside_replacement = b.constraint_to_si(ast_false)
    nose.tools.assert_equal(falseside_sat, True)
    nose.tools.assert_equal(len(falseside_replacement), 1)
    nose.tools.assert_true(falseside_replacement[0][0] is s2)
    # False side; claripy.SI<32>1[1, 2]
    nose.tools.assert_true(
        claripy.is_true(falseside_replacement[0][1].identical(
            SI(bits=32, stride=1, lower_bound=1, upper_bound=2))))

    #
    # Extract(0, 0, ZeroExt(32, If(SI == 0, BVV(1, 32), BVV(0, 32)))) == 1
    #

    s3 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=2)
    ast_true = (claripy.Extract(
        0, 0, claripy.ZeroExt(32, claripy.If(s3 == 0, BVV(1, 32),
                                             BVV(0, 32)))) == 1)
    ast_false = (claripy.Extract(
        0, 0, claripy.ZeroExt(32, claripy.If(s3 == 0, BVV(1, 32), BVV(0, 32))))
                 != 1)

    trueside_sat, trueside_replacement = b.constraint_to_si(ast_true)
    nose.tools.assert_equal(trueside_sat, True)
    nose.tools.assert_equal(len(trueside_replacement), 1)
    nose.tools.assert_true(trueside_replacement[0][0] is s3)
    # True side: claripy.SI<32>0[0, 0]
    nose.tools.assert_true(
        claripy.is_true(trueside_replacement[0][1].identical(
            SI(bits=32, stride=0, lower_bound=0, upper_bound=0))))

    falseside_sat, falseside_replacement = b.constraint_to_si(ast_false)
    nose.tools.assert_equal(falseside_sat, True)
    nose.tools.assert_equal(len(falseside_replacement), 1)
    nose.tools.assert_true(falseside_replacement[0][0] is s3)
    # False side; claripy.SI<32>1[1, 2]
    nose.tools.assert_true(
        claripy.is_true(falseside_replacement[0][1].identical(
            SI(bits=32, stride=1, lower_bound=1, upper_bound=2))))

    #
    # Extract(0, 0, ZeroExt(32, If(Extract(32, 0, (SI & claripy.SI)) < 0, BVV(1, 1), BVV(0, 1))))
    #

    s4 = claripy.SI(bits=64,
                    stride=1,
                    lower_bound=0,
                    upper_bound=0xffffffffffffffff)
    ast_true = (claripy.Extract(
        0, 0,
        claripy.ZeroExt(
            32,
            claripy.If(
                claripy.Extract(31, 0, (s4 & s4)).SLT(0), BVV(1, 32),
                BVV(0, 32)))) == 1)
    ast_false = (claripy.Extract(
        0, 0,
        claripy.ZeroExt(
            32,
            claripy.If(
                claripy.Extract(31, 0, (s4 & s4)).SLT(0), BVV(1, 32), BVV(
                    0, 32)))) != 1)

    trueside_sat, trueside_replacement = b.constraint_to_si(ast_true)
    nose.tools.assert_equal(trueside_sat, True)
    nose.tools.assert_equal(len(trueside_replacement), 1)
    nose.tools.assert_true(trueside_replacement[0][0] is s4)
    # True side: claripy.SI<32>0[0, 0]
    nose.tools.assert_true(
        claripy.is_true(trueside_replacement[0][1].identical(
            SI(bits=64,
               stride=1,
               lower_bound=-0x8000000000000000,
               upper_bound=-1))))

    falseside_sat, falseside_replacement = b.constraint_to_si(ast_false)
    nose.tools.assert_equal(falseside_sat, True)
    nose.tools.assert_equal(len(falseside_replacement), 1)
    nose.tools.assert_true(falseside_replacement[0][0] is s4)
    # False side; claripy.SI<32>1[1, 2]
    nose.tools.assert_true(
        claripy.is_true(falseside_replacement[0][1].identical(
            SI(bits=64,
               stride=1,
               lower_bound=0,
               upper_bound=0x7fffffffffffffff))))
Ejemplo n.º 9
0
    def exec_branch(self, state):  # pylint:disable=invalid-name
        """Execute forward from a state, queuing new states if needed."""
        logger.debug("Constraints: %s", state.solver.constraints)

        def solution(variable):
            """Returns the solution. There must be one or we fail."""
            solutions = state.solver.eval(variable, 2)
            if len(solutions) > 1:
                raise ValueError("Ambiguous solution for %s (%s)" %
                                 (variable, self.code[state.pc]))
            solution = solutions[0]
            return solution if isinstance(solution,
                                          numbers.Number) else solution.value

        state.score += 1
        self.code.pc = state.pc

        while True:
            if state.pc >= len(self.code):
                return True

            op = self.code.next()
            self.coverage[state.pc] += 1

            logger.debug("NEW STEP")
            logger.debug("Memory: %s", state.memory)
            logger.debug("Stack: %s", state.stack)
            logger.debug("PC: %i, %s", state.pc, op)

            assert self.code.pc == state.pc + 1
            assert isinstance(op, numbers.Number)
            assert all(
                hasattr(i, "symbolic") for i in
                state.stack), "The stack musty only contains claripy BV's"

            # Trivial operations first
            if not self.code.is_valid_opcode(state.pc):
                raise utils.CodeError("Trying to execute PUSH data")
            elif op == 254:  # INVALID opcode
                raise utils.CodeError("designed INVALID opcode")
            elif op == opcode_values.JUMPDEST:
                pass
            elif op == opcode_values.ADD:
                s0, s1 = (
                    not_bool(state.stack_pop()),
                    not_bool(state.stack_pop()),
                )  # pylint:disable=invalid-name
                state.stack_push(s0 + s1)
            elif op == opcode_values.SUB:
                s0, s1 = (
                    not_bool(state.stack_pop()),
                    not_bool(state.stack_pop()),
                )  # pylint:disable=invalid-name
                state.stack_push(s0 - s1)
            elif op == opcode_values.MUL:
                s0, s1 = (
                    not_bool(state.stack_pop()),
                    not_bool(state.stack_pop()),
                )  # pylint:disable=invalid-name
                state.stack_push(s0 * s1)
            elif op == opcode_values.DIV:
                # We need to use claripy.LShR instead of a division if possible,
                # because the solver is bad dealing with divisions, better
                # with shifts. And we need shifts to handle the solidity ABI
                # for function selection.
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                try:
                    s1 = solution(s1)  # pylint:disable=invalid-name
                except ValueError:
                    state.stack_push(claripy.If(s1 == 0, BVV_0, s0 / s1))
                else:
                    if s1 == 0:
                        state.stack_push(BVV_0)
                    elif s1 == 1:
                        state.stack_push(s0)
                    elif s1 & (s1 - 1) == 0:
                        exp = int(math.log(s1, 2))
                        state.stack_push(s0.LShR(exp))
                    else:
                        state.stack_push(s0 / s1)
            elif op == opcode_values.SDIV:
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                try:
                    s1 = solution(s1)
                except ValueError:
                    state.stack_push(claripy.If(s1 == 0, BVV_0, s0.SDiv(s1)))
                else:
                    state.stack_push(BVV_0 if s1 == 0 else s0.SDiv(s1))
            elif op == opcode_values.MOD:
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                try:
                    s1 = solution(s1)
                except ValueError:
                    state.stack_push(claripy.If(s1 == 0, BVV_0, s0 % s1))
                else:
                    state.stack_push(BVV_0 if s1 == 0 else s0 % s1)
            elif op == opcode_values.SMOD:
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                try:
                    s1 = solution(s1)
                except ValueError:
                    state.stack_push(claripy.If(s1 == 0, BVV_0, s0.SMod(s1)))
                else:
                    state.stack_push(BVV_0 if s1 == 0 else s0.SMod(s1))
            elif op == opcode_values.ADDMOD:
                s0, s1, s2 = state.stack_pop(), state.stack_pop(
                ), state.stack_pop()
                try:
                    s2 = solution(s2)
                except ValueError:
                    state.stack_push(claripy.If(s2 == 0, BVV_0,
                                                (s0 + s1) % s2))
                else:
                    state.stack_push(BVV_0 if s2 == 0 else (s0 + s1) % s2)
            elif op == opcode_values.MULMOD:
                s0, s1, s2 = state.stack_pop(), state.stack_pop(
                ), state.stack_pop()
                try:
                    s2 = solution(s2)
                except ValueError:
                    state.stack_push(claripy.If(s2 == 0, BVV_0,
                                                (s0 * s1) % s2))
                else:
                    state.stack_push(BVV_0 if s2 == 0 else (s0 * s1) % s2)
            elif op == opcode_values.EXP:
                base, exponent = solution(state.stack_pop()), state.stack_pop()
                if base == 2:
                    state.stack_push(1 << exponent)
                else:
                    exponent = solution(exponent)
                    state.stack_push(claripy.BVV(base**exponent, 256))
            elif op == opcode_values.LT:
                s0, s1 = (
                    not_bool(state.stack_pop()),
                    not_bool(state.stack_pop()),
                )  # pylint:disable=invalid-name
                state.stack_push(claripy.ULT(s0, s1))
            elif op == opcode_values.GT:
                s0, s1 = (
                    not_bool(state.stack_pop()),
                    not_bool(state.stack_pop()),
                )  # pylint:disable=invalid-name
                state.stack_push(claripy.UGT(s0, s1))
            elif op == opcode_values.SLT:
                s0, s1 = (
                    not_bool(state.stack_pop()),
                    not_bool(state.stack_pop()),
                )  # pylint:disable=invalid-name
                state.stack_push(claripy.SLT(s0, s1))
            elif op == opcode_values.SGT:
                s0, s1 = (
                    not_bool(state.stack_pop()),
                    not_bool(state.stack_pop()),
                )  # pylint:disable=invalid-name
                state.stack_push(claripy.SGT(s0, s1))
            elif op == opcode_values.SIGNEXTEND:
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                # s0 is the number of bits. s1 the number we want to extend.
                s0 = solution(s0)
                if s0 <= 31:
                    sign_bit = 1 << (s0 * 8 + 7)
                    state.stack_push(
                        claripy.If(
                            s1 & sign_bit == 0,
                            s1 & (sign_bit - 1),
                            s1 | ((1 << 256) - sign_bit),
                        ))
                else:
                    state.stack_push(s1)
            elif op == opcode_values.EQ:
                s0, s1 = state.stack_pop(), state.stack_pop()
                if isinstance(s0, claripy.ast.Bool) and isinstance(
                        s1, claripy.ast.Bool):
                    state.stack_push(s0 == s1)
                else:
                    state.stack_push(not_bool(s0) == not_bool(s1))
            elif op == opcode_values.ISZERO:
                condition = state.stack_pop()
                if isinstance(condition, claripy.ast.Bool):
                    state.stack_push(claripy.Not(condition))
                else:
                    state.stack_push(condition == BVV_0)
            elif op == opcode_values.AND:
                s0, s1 = make_consistent(state.stack_pop(), state.stack_pop())
                if isinstance(s0, claripy.ast.Bool) and isinstance(
                        s1, claripy.ast.Bool):
                    state.stack_push(s0 and s1)
                else:
                    state.stack_push(s0 & s1)
            elif op == opcode_values.OR:
                s0, s1 = make_consistent(state.stack_pop(), state.stack_pop())
                if isinstance(s0, claripy.ast.Bool) and isinstance(
                        s1, claripy.ast.Bool):
                    state.stack_push(s0 or s1)
                else:
                    state.stack_push(s0 | s1)
            elif op == opcode_values.XOR:
                s0, s1 = make_consistent(state.stack_pop(), state.stack_pop())
                state.stack_push(s0 ^ s1)
            elif op == opcode_values.NOT:
                state.stack_push(~state.stack_pop())
            elif op == opcode_values.BYTE:
                s0, s1 = (
                    state.stack_pop(),
                    state.stack_pop(),
                )  # pylint:disable=invalid-name
                state.stack_push(
                    s1.LShR(claripy.If(s0 > 31, 32, 31 - s0) * 8) & 0xFF)

            elif op == opcode_values.PC:
                state.stack_push(bvv(state.pc))
            elif op == opcode_values.GAS:
                state.stack_push(state.env.gas)
            elif op == opcode_values.ADDRESS:
                state.stack_push(state.env.address)
            elif op == opcode_values.BALANCE:
                addr = solution(state.stack_pop())
                if addr != solution(state.env.address):
                    raise utils.InterpreterError(
                        state,
                        "Can only query balance of the current contract for now"
                    )
                state.stack_push(state.env.balance)
            elif op == opcode_values.ORIGIN:
                state.stack_push(state.env.origin)
            elif op == opcode_values.CALLER:
                state.stack_push(state.env.caller)
            elif op == opcode_values.CALLVALUE:
                state.stack_push(state.env.value)
            elif op == opcode_values.BLOCKHASH:
                block_num = state.stack_pop()
                if block_num not in state.env.block_hashes:
                    state.env.block_hashes[block_num] = claripy.BVS(
                        "blockhash[%s]" % block_num, 256)
                state.stack_push(state.env.block_hashes[block_num])
            elif op == opcode_values.TIMESTAMP:
                state.stack_push(state.env.block_timestamp)
            elif op == opcode_values.NUMBER:
                state.stack_push(state.env.block_number)
            elif op == opcode_values.COINBASE:
                state.stack_push(state.env.coinbase)
            elif op == opcode_values.DIFFICULTY:
                state.stack_push(state.env.difficulty)
            elif op == opcode_values.POP:
                state.stack_pop()
            elif op == opcode_values.JUMP:
                addr = solution(state.stack_pop())
                if addr >= len(self.code
                               ) or self.code[addr] != opcode_values.JUMPDEST:
                    raise utils.CodeError("Invalid jump (%i)" % addr)
                state.pc = addr
                self.add_branch(state)
                return False
            elif op == opcode_values.JUMPI:
                addr, condition = solution(
                    state.stack_pop()), state.stack_pop()
                state_false = state.copy()
                if isinstance(condition, claripy.ast.Bool):
                    state.solver.add(condition)
                    state_false.solver.add(claripy.Not(condition))
                else:
                    state.solver.add(condition != 0)
                    state_false.solver.add(condition == 0)
                state_false.pc += 1
                self.add_branch(state_false)
                state.pc = addr
                if (state.pc >= len(self.code)
                        or self.code[state.pc] != opcode_values.JUMPDEST):
                    raise utils.CodeError("Invalid jump (%i)" % (state.pc - 1))
                self.add_branch(state)
                return False
            elif opcode_values.PUSH1 <= op <= opcode_values.PUSH32:
                pushnum = op - opcode_values.PUSH1 + 1
                raw_value = self.code.read(pushnum)
                state.pc += pushnum
                state.stack_push(
                    bvv(int.from_bytes(raw_value, byteorder="big")))
            elif opcode_values.DUP1 <= op <= opcode_values.DUP16:
                depth = op - opcode_values.DUP1 + 1
                state.stack_push(state.stack[-depth])
            elif opcode_values.SWAP1 <= op <= opcode_values.SWAP16:
                depth = op - opcode_values.SWAP1 + 1
                temp = state.stack[-depth - 1]
                state.stack[-depth - 1] = state.stack[-1]
                state.stack[-1] = temp
            elif opcode_values.LOG0 <= op <= opcode_values.LOG4:
                depth = op - opcode_values.LOG0
                mstart, msz = (state.stack_pop(), state.stack_pop())
                topics = [state.stack_pop() for x in range(depth)]
            elif op == opcode_values.SHA3:
                start, length = solution(state.stack_pop()), solution(
                    state.stack_pop())
                memory = state.memory.read(start, length)
                state.stack_push(Sha3(memory))
            elif op == opcode_values.STOP:
                return True
            elif op == opcode_values.RETURN:
                return True

            elif op == opcode_values.CALLDATALOAD:
                indexes = state.stack_pop()
                try:
                    index = solution(indexes)
                except ValueError:  # Multiple solutions, let's fuzz.
                    state.stack_push(indexes)  # restore the stack
                    self.add_for_fuzzing(state, indexes, CALLDATASIZE_FUZZ)
                    return False
                state.solver.add(state.env.calldata_size >= index + 32)
                state.stack_push(state.env.calldata.read(index, 32))
            elif op == opcode_values.CALLDATASIZE:
                state.stack_push(state.env.calldata_size)
            elif op == opcode_values.CALLDATACOPY:
                old_state = state.copy()
                mstart, dstart, size = (
                    state.stack_pop(),
                    state.stack_pop(),
                    state.stack_pop(),
                )
                mstart, dstart = solution(mstart), solution(dstart)
                try:
                    size = solution(size)
                except ValueError:
                    self.add_for_fuzzing(old_state, size, CALLDATASIZE_FUZZ)
                    return False
                state.memory.copy_from(state.env.calldata, mstart, dstart,
                                       size)
                state.solver.add(state.env.calldata_size >= dstart + size)
            elif op == opcode_values.CODESIZE:
                state.stack_push(bvv(len(self.code)))
            elif op == opcode_values.EXTCODESIZE:
                addr = state.stack_pop()
                if (addr == state.env.address).is_true():
                    state.stack_push(bvv(len(self.code)))
                else:
                    # TODO: Improve that... It's clearly not constraining enough.
                    state.stack_push(claripy.BVS("EXTCODESIZE[%s]" % addr,
                                                 256))
            elif op == opcode_values.CODECOPY:
                mem_start, code_start, size = [
                    solution(state.stack_pop()) for _ in range(3)
                ]
                for i in range(size):
                    if code_start + i < len(state.env.code):
                        state.memory.write(
                            mem_start + i,
                            1,
                            claripy.BVV(state.env.code[code_start + i], 8),
                        )
                    else:
                        state.memory.write(mem_start + i, 1, claripy.BVV(0, 8))

            elif op == opcode_values.MLOAD:
                index = solution(state.stack_pop())
                state.stack_push(state.memory.read(index, 32))
            elif op == opcode_values.MSTORE:
                index, value = solution(state.stack_pop()), not_bool(
                    state.stack_pop())
                state.memory.write(index, 32, value)
            elif op == opcode_values.MSTORE8:
                index, value = solution(state.stack_pop()), not_bool(
                    state.stack_pop())
                state.memory.write(index, 1, value[7:0])
            elif op == opcode_values.MSIZE:
                state.stack_push(bvv(state.memory.size()))
            elif op == opcode_values.SLOAD:
                # TODO: This is inaccurate, because the storage can change
                # in a single transaction.
                # See commit d98cab834f8f359f01ef805256d179f5529ebe30.
                key = state.stack_pop()
                if key in state.storage_written:
                    state.stack_push(state.storage_written[key])
                else:
                    if key not in state.storage_read:
                        state.storage_read[key] = claripy.BVS(
                            "storage[%s]" % key, 256)
                    state.stack_push(state.storage_read[key])
            elif op == opcode_values.SSTORE:
                # TODO: This is inaccurate, because the storage can change
                # in a single transaction.
                # See commit d98cab834f8f359f01ef805256d179f5529ebe30.
                key = state.stack_pop()
                value = state.stack_pop()
                state.storage_written[key] = value

            elif op == opcode_values.CALL:
                state.pc += 1

                # First possibility: the call fails
                # (always possible with a call stack big enough)
                state_fail = state.copy()
                state_fail.stack_push(claripy.BoolV(False))
                self.add_branch(state_fail)

                # Second possibility: success.
                state.calls.append(state.stack[-7:])

                # pylint:disable=unused-variable
                gas, to_, value, meminstart, meminsz, memoutstart, memoutsz = (
                    state.stack_pop() for _ in range(7))

                if solution(memoutsz) != 0:
                    raise utils.InterpreterError(state,
                                                 "CALL seems to return data")
                if solution(meminsz) != 0:
                    raise utils.InterpreterError(state,
                                                 "CALL seems to take data")

                state.stack_push(claripy.BoolV(True))
                self.add_branch(state)
                return False

            elif op == opcode_values.SELFDESTRUCT:
                state.selfdestruct_to = state.stack[-1]
                return True

            elif op == opcode_values.REVERT:
                return False
            else:
                raise utils.InterpreterError(state, "Unknown opcode %s" % op)

            state.pc += 1
Ejemplo n.º 10
0
 def if_builder(self, element, a, x):
     return claripy.If(element == x, claripy.BVV(int(x, 16), 8 * 4), a)
Ejemplo n.º 11
0
 def run(self, addr_str_to_check, length):
     #load the string from memory from the current state, self.state
     string = self.state.memory.load(addr_str_to_check, length)
     #return correct value from string comparison
     return claripy.If(string == keyword, claripy.BVV(1, 32),
                       claripy.BVV(0, 32))
Ejemplo n.º 12
0
 def generic_compare(args: Iterable[BV], comparison: Callable[[BV, BV],
                                                              BV]) -> BV:
     return claripy.If(comparison(args[0], args[1]), claripy.BVV(1, 1),
                       claripy.BVV(0, 1))
Ejemplo n.º 13
0
import claripy
s = claripy.Solver()
x = claripy.BVS('x', 8)
y = claripy.BVV(65, 8)
z = claripy.If(x == 1, x, y)
s.add(claripy.ULT(x, 5))
s.add(z % 5 != 0)
print s.eval(z, 10)
Ejemplo n.º 14
0
def bool_to_bv(b):
    return claripy.If(b, BVV_1, BVV_0)
Ejemplo n.º 15
0
    def updateTimeFromDependencies(self, regs, memory):
        """
        Sets the execution time to the max of the execution time and the time required to access the dependencies.
        The max function is symbolic so it can handle symbolic expressions with overlapping feasibility space
        Call this after all dependencies are known
        
        returns a tuple of two symbolic boolean expressions.
            The first expresses whether there was a pipeline bubble (wait on data dependency)
            The first expresses whether dual issuing is prevented (by either a bubble or the register being available only in the current moment)
        TODO low priority, optimisation only: This function gets called often but heavily relies on calls to the solver. Thus, if the constraints are complex, the function can significantly slow down the entire analysis.
        
        TODO: registers get processed in order... which is strange.
            if a register analysed first could actually increase execution time it gets added as a registers influencing maxtime.
            if another resgister takes longer the previous register is still seen as influencing max time (it could, but this isn't sure)
            basically: we should first see witch registers can influence time, and the registers that are left
        """
        bubble = claripy.false
        dualPrevented = claripy.false

        regsInfluencingMaxTime = []
        memsInfluencingMaxTime = []
        #check whether we have to wait for a register
        for r in regs:
            if r in self.registers:
                compute = claripy.backends.z3.simplify(
                    self.registers[r][0].SGT(self.totalExecutionTime))
                satisfiability = self.state.se.satisfiable([compute])
                if satisfiability:  #actually wait for the register
                    registerName = (
                        "register %s" %
                        self.state.meta.factory.project.arch.capstone.reg_name(
                            r)) if r != FLAGS_REGISTER else "flags register"
                    if self.state.se.satisfiable([claripy.Not(compute)]):
                        #symbolic maximum function:
                        self.totalExecutionTime = claripy.If(
                            compute, self.registers[r][0],
                            self.totalExecutionTime)
                        print("Symbolically waiting for %s..." % registerName)
                        #print compute
                    else:
                        self.totalExecutionTime = self.registers[r][0]
                        if settings.VERBOSE:
                            print("Waiting for %s..." % registerName)
                    regsInfluencingMaxTime.append(r)

        #check whether we have to wait for a memory
        for m in memory:
            if m in self.memory:
                compute = claripy.backends.z3.simplify(self.memory[m][0].SGT(
                    self.totalExecutionTime))
                satisfiability = self.state.se.satisfiable([compute])
                if satisfiability:  #actually wait for the memory
                    if self.state.se.satisfiable([claripy.Not(compute)]):
                        self.totalExecutionTime = claripy.If(
                            compute, self.memory[m][0],
                            self.totalExecutionTime)
                        if m.concrete:
                            print("Symbolically waiting for memory [0x%x]..." %
                                  m.args[0])
                        else:
                            print("Symbolically waiting for memory [%s]..." %
                                  m)
                    else:
                        self.totalExecutionTime = self.memory[m][0]
                        if settings.VERBOSE:
                            if m.concrete:
                                print("Waiting for memory [0x%x]..." %
                                      m.args[0])
                            else:
                                print("Waiting for memory [%s]..." % m)
                    memsInfluencingMaxTime.append(m)

        global type1violations
        global type2violations
        global type3violations

        #if we have multiple contenders for time-influences, we need to check whether some rule some others out
        if len(regsInfluencingMaxTime) + len(memsInfluencingMaxTime) > 1:
            if not self.state.se._solver.hasMultipleSolutions(
                    self.totalExecutionTime
            ):  #if execution time doesn't have multiple solutions, there's no need to process any further.
                regsInfluencingMaxTime = []
                memsInfluencingMaxTime = []
            else:
                #we know that execution time can take on multiple values, now we check which registers or memory dependencies can really slow it down.
                for r in regsInfluencingMaxTime:
                    if not self.state.se._solver.satisfiable(
                        [self.registers[r][0].SGT(self.totalExecutionTime)]):
                        regsInfluencingMaxTime.remove(r)
                for m in memsInfluencingMaxTime:
                    if not self.state.se._solver.satisfiable(
                        [self.memory[m][0].SGT(self.totalExecutionTime)]):
                        memsInfluencingMaxTime.remove(m)

        #determine whether any of the registers we're waiting for depends on a secret
        for r in regsInfluencingMaxTime:
            if self.registers[r][
                    1] != None:  #this value was updated to (insn.mnemonic, insn.address) in the pipelineModel step 4, if in step 3 it was computed that the latency depends on a secret, and has multiple timings. So if this condition is passed we know a timing channel exists -> raise warnings and register the violations
                vType = timingModel.violationType(self.registers[r][2],
                                                  self.registers[r][3])
                if vType != 0:
                    print(
                        "\033[93mWarning: Type %d violation at instruction: %s @ 0x%x\033[0m"
                        % (vType, self.registers[r][1][0],
                           self.registers[r][1][1]))
                    if vType == 1:
                        type1violations.append(self.registers[r][1])
                    elif vType == 2:
                        type2violations.append(self.registers[r][1])
                        if not (self.state.options.__contains__(
                                simuvex.o.CONSERVATIVE_WRITE_STRATEGY)
                                and self.state.options.__contains__(
                                    simuvex.o.CONSERVATIVE_READ_STRATEGY)):
                            print(
                                "\033[93mFor better results you should probably run the analysis and with the initial states' options \"add_options={simuvex.o.CONSERVATIVE_WRITE_STRATEGY, simuvex.o.CONSERVATIVE_READ_STRATEGY}\"\033[0m"
                            )
                    elif vType == 3:
                        type3violations.append(self.registers[r][1])
                    import store
                    store.violations.append(
                        ("%s, @ 0x%x" %
                         (self.registers[r][1][0], self.registers[r][1][1]),
                         self.registers[r]))
                else:  #unknow violation type
                    print(
                        "\033[93mWarning: violation of unknown type at instruction: %s @ 0x%x\033[0m"
                        % (vType, self.registers[r][1][0],
                           self.registers[r][1][1]))

        for m in memsInfluencingMaxTime:
            if self.memory[m][1] != None:
                vType = timingModel.violationType(self.memory[m][2],
                                                  self.memory[m][3])
                if vType != 0:
                    print(
                        "\033[93mWarning: Type %d violation at instruction: %s @ 0x%x\033[0m"
                        % (vType, self.registers[r][1][0],
                           self.registers[r][1][1]))
                    if vType == 1:
                        type1violations.append(self.memory[m][1])
                    elif vType == 2:
                        type2violations.append(self.memory[m][1])
                        if not (self.state.options.__contains__(
                                simuvex.o.CONSERVATIVE_WRITE_STRATEGY)
                                and self.state.options.__contains__(
                                    simuvex.o.CONSERVATIVE_READ_STRATEGY)):
                            print(
                                "\033[93mFor better results you should probably run the analysis and with the initial states' options \"add_options={simuvex.o.CONSERVATIVE_WRITE_STRATEGY, simuvex.o.CONSERVATIVE_READ_STRATEGY}\"\033[0m"
                            )
                    elif vType == 3:
                        type3violations.append(self.memory[m][1])
                    import store
                    store.violations.append(
                        ("%s, @ 0x%x" %
                         (self.registers[m][1][0], self.registers[m][1][1]),
                         self.registers[m]))
                else:  #unknow violation type
                    print(
                        "\033[93mWarning: violation of unknown type at instruction: %s @ 0x%x\033[0m"
                        % (vType, self.registers[r][1][0],
                           self.registers[r][1][1]))

        bubble = claripy.backends.z3.simplify(bubble)
        dualPrevented = claripy.backends.z3.simplify(
            claripy.Or(dualPrevented, bubble))
        return (bubble, dualPrevented)
Ejemplo n.º 16
0
def test_vsa():
    # Set backend
    b = claripy.backend_vsa

    SI = claripy.StridedInterval
    VS = claripy.ValueSet
    BVV = claripy.BVV

    # Disable the use of DiscreteStridedIntervalSet
    claripy.vsa.strided_interval.allow_dsis = False

    def is_equal(ast_0, ast_1):
        return ast_0.identical(ast_1)

    si1 = claripy.TSI(32, name="foo")
    nose.tools.assert_equal(si1.model.name, "foo")

    # Normalization
    si1 = SI(bits=32, stride=1, lower_bound=10, upper_bound=10)
    nose.tools.assert_equal(si1.model.stride, 0)

    # Integers
    si1 = claripy.SI(bits=32, stride=0, lower_bound=10, upper_bound=10)
    si2 = claripy.SI(bits=32, stride=0, lower_bound=10, upper_bound=10)
    si3 = claripy.SI(bits=32, stride=0, lower_bound=28, upper_bound=28)
    # Strided intervals
    si_a = claripy.SI(bits=32, stride=2, lower_bound=10, upper_bound=20)
    si_b = claripy.SI(bits=32, stride=2, lower_bound=-100, upper_bound=200)
    si_c = claripy.SI(bits=32, stride=3, lower_bound=-100, upper_bound=200)
    si_d = claripy.SI(bits=32, stride=2, lower_bound=50, upper_bound=60)
    si_e = claripy.SI(bits=16,
                      stride=1,
                      lower_bound=0x2000,
                      upper_bound=0x3000)
    si_f = claripy.SI(bits=16, stride=1, lower_bound=0, upper_bound=255)
    si_g = claripy.SI(bits=16, stride=1, lower_bound=0, upper_bound=0xff)
    si_h = claripy.SI(bits=32,
                      stride=0,
                      lower_bound=0x80000000,
                      upper_bound=0x80000000)
    nose.tools.assert_true(is_equal(si1, claripy.SI(bits=32, to_conv=10)))
    nose.tools.assert_true(is_equal(si2, claripy.SI(bits=32, to_conv=10)))
    nose.tools.assert_true(is_equal(si1, si2))
    # __add__
    si_add_1 = si1 + si2
    nose.tools.assert_true(
        is_equal(si_add_1,
                 claripy.SI(bits=32, stride=0, lower_bound=20,
                            upper_bound=20)))
    si_add_2 = si1 + si_a
    nose.tools.assert_true(
        is_equal(si_add_2,
                 claripy.SI(bits=32, stride=2, lower_bound=20,
                            upper_bound=30)))
    si_add_3 = si_a + si_b
    nose.tools.assert_true(
        is_equal(
            si_add_3,
            claripy.SI(bits=32, stride=2, lower_bound=-90, upper_bound=220)))
    si_add_4 = si_b + si_c
    nose.tools.assert_true(
        is_equal(
            si_add_4,
            claripy.SI(bits=32, stride=1, lower_bound=-200, upper_bound=400)))
    # __add__ with overflow
    si_add_5 = si_h + 0xffffffff
    nose.tools.assert_true(
        is_equal(
            si_add_5,
            claripy.SI(bits=32,
                       stride=0,
                       lower_bound=0x7fffffff,
                       upper_bound=0x7fffffff)))
    # __sub__
    si_minus_1 = si1 - si2
    nose.tools.assert_true(
        is_equal(si_minus_1,
                 claripy.SI(bits=32, stride=0, lower_bound=0, upper_bound=0)))
    si_minus_2 = si_a - si_b
    nose.tools.assert_true(
        is_equal(
            si_minus_2,
            claripy.SI(bits=32, stride=2, lower_bound=-190, upper_bound=120)))
    si_minus_3 = si_b - si_c
    nose.tools.assert_true(
        is_equal(
            si_minus_3,
            claripy.SI(bits=32, stride=1, lower_bound=-300, upper_bound=300)))
    # __neg__ / __invert__ / bitwise not
    si_neg_1 = ~si1
    nose.tools.assert_true(is_equal(si_neg_1, claripy.SI(bits=32,
                                                         to_conv=-11)))
    si_neg_2 = ~si_b
    nose.tools.assert_true(
        is_equal(
            si_neg_2,
            claripy.SI(bits=32, stride=2, lower_bound=-201, upper_bound=99)))
    # __or__
    si_or_1 = si1 | si3
    nose.tools.assert_true(is_equal(si_or_1, claripy.SI(bits=32, to_conv=30)))
    si_or_2 = si1 | si2
    nose.tools.assert_true(is_equal(si_or_2, claripy.SI(bits=32, to_conv=10)))
    si_or_3 = si1 | si_a  # An integer | a strided interval
    nose.tools.assert_true(
        is_equal(si_or_3,
                 claripy.SI(bits=32, stride=2, lower_bound=10,
                            upper_bound=30)))
    si_or_3 = si_a | si1  # Exchange the operands
    nose.tools.assert_true(
        is_equal(si_or_3,
                 claripy.SI(bits=32, stride=2, lower_bound=10,
                            upper_bound=30)))
    si_or_4 = si_a | si_d  # A strided interval | another strided interval
    nose.tools.assert_true(
        is_equal(si_or_4,
                 claripy.SI(bits=32, stride=2, lower_bound=50,
                            upper_bound=62)))
    si_or_4 = si_d | si_a  # Exchange the operands
    nose.tools.assert_true(
        is_equal(si_or_4,
                 claripy.SI(bits=32, stride=2, lower_bound=50,
                            upper_bound=62)))
    si_or_5 = si_e | si_f  #
    nose.tools.assert_true(
        is_equal(
            si_or_5,
            claripy.SI(bits=16,
                       stride=1,
                       lower_bound=0x2000,
                       upper_bound=0x30ff)))
    si_or_6 = si_e | si_g  #
    nose.tools.assert_true(
        is_equal(
            si_or_6,
            claripy.SI(bits=16,
                       stride=1,
                       lower_bound=0x2000,
                       upper_bound=0x30ff)))
    # Shifting
    si_shl_1 = si1 << 3
    nose.tools.assert_equal(si_shl_1.size(), 32)
    nose.tools.assert_true(
        is_equal(si_shl_1,
                 claripy.SI(bits=32, stride=0, lower_bound=80,
                            upper_bound=80)))
    # Multiplication
    si_mul_1 = si1 * 3
    nose.tools.assert_equal(si_mul_1.size(), 32)
    nose.tools.assert_true(
        is_equal(si_mul_1,
                 claripy.SI(bits=32, stride=0, lower_bound=30,
                            upper_bound=30)))
    si_mul_2 = si_a * 3
    nose.tools.assert_equal(si_mul_2.size(), 32)
    nose.tools.assert_true(
        is_equal(si_mul_2,
                 claripy.SI(bits=32, stride=6, lower_bound=30,
                            upper_bound=60)))
    si_mul_3 = si_a * si_b
    nose.tools.assert_equal(si_mul_3.size(), 32)
    nose.tools.assert_true(
        is_equal(
            si_mul_3,
            claripy.SI(bits=32, stride=2, lower_bound=-2000,
                       upper_bound=4000)))
    # Division
    si_div_1 = si1 / 3
    nose.tools.assert_equal(si_div_1.size(), 32)
    nose.tools.assert_true(
        is_equal(si_div_1,
                 claripy.SI(bits=32, stride=0, lower_bound=3, upper_bound=3)))
    si_div_2 = si_a / 3
    nose.tools.assert_equal(si_div_2.size(), 32)
    nose.tools.assert_true(
        is_equal(si_div_2,
                 claripy.SI(bits=32, stride=1, lower_bound=3, upper_bound=6)))
    # Modulo
    si_mo_1 = si1 % 3
    nose.tools.assert_equal(si_mo_1.size(), 32)
    nose.tools.assert_true(
        is_equal(si_mo_1,
                 claripy.SI(bits=32, stride=0, lower_bound=1, upper_bound=1)))
    si_mo_2 = si_a % 3
    nose.tools.assert_equal(si_mo_2.size(), 32)
    nose.tools.assert_true(
        is_equal(si_mo_2,
                 claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=2)))

    #
    # Extracting the sign bit
    #

    # a negative integer
    si = claripy.SI(bits=64, stride=0, lower_bound=-1, upper_bound=-1)
    sb = si[63:63]
    nose.tools.assert_true(is_equal(sb, claripy.SI(bits=1, to_conv=1)))

    # non-positive integers
    si = claripy.SI(bits=64, stride=1, lower_bound=-1, upper_bound=0)
    sb = si[63:63]
    nose.tools.assert_true(
        is_equal(sb, claripy.SI(bits=1, stride=1, lower_bound=0,
                                upper_bound=1)))

    # Extracting an integer
    si = claripy.SI(bits=64,
                    stride=0,
                    lower_bound=0x7fffffffffff0000,
                    upper_bound=0x7fffffffffff0000)
    part1 = si[63:32]
    part2 = si[31:0]
    nose.tools.assert_true(
        is_equal(
            part1,
            claripy.SI(bits=32,
                       stride=0,
                       lower_bound=0x7fffffff,
                       upper_bound=0x7fffffff)))
    nose.tools.assert_true(
        is_equal(
            part2,
            claripy.SI(bits=32,
                       stride=0,
                       lower_bound=0xffff0000,
                       upper_bound=0xffff0000)))

    # Concatenating two integers
    si_concat = part1.concat(part2)
    nose.tools.assert_true(is_equal(si_concat, si))

    # Extracting a claripy.SI
    si = claripy.SI(bits=64, stride=0x9, lower_bound=0x1, upper_bound=0xa)
    part1 = si[63:32]
    part2 = si[31:0]
    nose.tools.assert_true(
        is_equal(
            part1,
            claripy.SI(bits=32, stride=0, lower_bound=0x0, upper_bound=0x0)))
    nose.tools.assert_true(
        is_equal(part2,
                 claripy.SI(bits=32, stride=9, lower_bound=1, upper_bound=10)))

    # Concatenating two claripy.SIs
    si_concat = part1.concat(part2)
    nose.tools.assert_true(is_equal(si_concat, si))

    # Concatenating two SIs that are of different sizes
    si_1 = SI(bits=64, stride=1, lower_bound=0, upper_bound=0xffffffffffffffff)
    si_2 = SI(bits=32, stride=1, lower_bound=0, upper_bound=0xffffffff)
    si_concat = si_1.concat(si_2)
    nose.tools.assert_true(
        is_equal(
            si_concat,
            SI(bits=96,
               stride=1,
               lower_bound=0,
               upper_bound=0xffffffffffffffffffffffff)))

    # Zero-Extend the low part
    si_zeroextended = part2.zero_extend(32)
    nose.tools.assert_true(
        is_equal(si_zeroextended,
                 claripy.SI(bits=64, stride=9, lower_bound=1, upper_bound=10)))

    # Sign-extension
    si_signextended = part2.sign_extend(32)
    nose.tools.assert_true(
        is_equal(si_signextended,
                 claripy.SI(bits=64, stride=9, lower_bound=1, upper_bound=10)))

    # Extract from the result above
    si_extracted = si_zeroextended[31:0]
    nose.tools.assert_true(
        is_equal(si_extracted,
                 claripy.SI(bits=32, stride=9, lower_bound=1, upper_bound=10)))

    # Union
    si_union_1 = si1.union(si2)
    nose.tools.assert_true(
        is_equal(si_union_1,
                 claripy.SI(bits=32, stride=0, lower_bound=10,
                            upper_bound=10)))
    si_union_2 = si1.union(si3)
    nose.tools.assert_true(
        is_equal(
            si_union_2,
            claripy.SI(bits=32, stride=18, lower_bound=10, upper_bound=28)))
    si_union_3 = si1.union(si_a)
    nose.tools.assert_true(
        is_equal(si_union_3,
                 claripy.SI(bits=32, stride=2, lower_bound=10,
                            upper_bound=20)))
    si_union_4 = si_a.union(si_b)
    nose.tools.assert_true(
        is_equal(
            si_union_4,
            claripy.SI(bits=32, stride=2, lower_bound=-100, upper_bound=200)))
    si_union_5 = si_b.union(si_c)
    nose.tools.assert_true(
        is_equal(
            si_union_5,
            claripy.SI(bits=32, stride=1, lower_bound=-100, upper_bound=200)))

    # Intersection
    si_intersection_1 = si1.intersection(si1)
    nose.tools.assert_true(is_equal(si_intersection_1, si2))
    si_intersection_2 = si1.intersection(si2)
    nose.tools.assert_true(
        is_equal(si_intersection_2,
                 claripy.SI(bits=32, stride=0, lower_bound=10,
                            upper_bound=10)))
    si_intersection_3 = si1.intersection(si_a)
    nose.tools.assert_true(
        is_equal(si_intersection_3,
                 claripy.SI(bits=32, stride=0, lower_bound=10,
                            upper_bound=10)))
    si_intersection_4 = si_a.intersection(si_b)
    nose.tools.assert_true(
        is_equal(si_intersection_4,
                 claripy.SI(bits=32, stride=2, lower_bound=10,
                            upper_bound=20)))
    si_intersection_5 = si_b.intersection(si_c)
    nose.tools.assert_true(
        is_equal(
            si_intersection_5,
            claripy.SI(bits=32, stride=6, lower_bound=-100, upper_bound=200)))

    # Sign-extension
    si = claripy.SI(bits=1, stride=0, lower_bound=1, upper_bound=1)
    si_signextended = si.sign_extend(31)
    nose.tools.assert_true(
        is_equal(
            si_signextended,
            claripy.SI(bits=32,
                       stride=0,
                       lower_bound=0xffffffff,
                       upper_bound=0xffffffff)))

    # Comparison between claripy.SI and BVV
    si = claripy.SI(bits=32, stride=1, lower_bound=-0x7f, upper_bound=0x7f)
    si.uninitialized = True
    bvv = BVV(0x30, 32)
    comp = (si < bvv)
    nose.tools.assert_equal(comp.model, MaybeResult())

    # Better extraction
    # si = <32>0x1000000[0xcffffff, 0xdffffff]R
    si = claripy.SI(bits=32,
                    stride=0x1000000,
                    lower_bound=0xcffffff,
                    upper_bound=0xdffffff)
    si_byte0 = si[7:0]
    si_byte1 = si[15:8]
    si_byte2 = si[23:16]
    si_byte3 = si[31:24]
    nose.tools.assert_true(
        is_equal(
            si_byte0,
            claripy.SI(bits=8, stride=0, lower_bound=0xff, upper_bound=0xff)))
    nose.tools.assert_true(
        is_equal(
            si_byte1,
            claripy.SI(bits=8, stride=0, lower_bound=0xff, upper_bound=0xff)))
    nose.tools.assert_true(
        is_equal(
            si_byte2,
            claripy.SI(bits=8, stride=0, lower_bound=0xff, upper_bound=0xff)))
    nose.tools.assert_true(
        is_equal(
            si_byte3,
            claripy.SI(bits=8, stride=1, lower_bound=0xc, upper_bound=0xd)))

    # Optimization on bitwise-and
    si_1 = claripy.SI(bits=32,
                      stride=1,
                      lower_bound=0x0,
                      upper_bound=0xffffffff)
    si_2 = claripy.SI(bits=32,
                      stride=0,
                      lower_bound=0x80000000,
                      upper_bound=0x80000000)
    si = si_1 & si_2
    nose.tools.assert_true(
        is_equal(
            si,
            claripy.SI(bits=32,
                       stride=0x80000000,
                       lower_bound=0,
                       upper_bound=0x80000000)))

    si_1 = claripy.SI(bits=32,
                      stride=1,
                      lower_bound=0x0,
                      upper_bound=0x7fffffff)
    si_2 = claripy.SI(bits=32,
                      stride=0,
                      lower_bound=0x80000000,
                      upper_bound=0x80000000)
    si = si_1 & si_2
    nose.tools.assert_true(
        is_equal(si, claripy.SI(bits=32,
                                stride=0,
                                lower_bound=0,
                                upper_bound=0)))

    # Concatenation: concat with zeros only increases the stride
    si_1 = claripy.SI(bits=8, stride=0xff, lower_bound=0x0, upper_bound=0xff)
    si_2 = claripy.SI(bits=8, stride=0, lower_bound=0, upper_bound=0)
    si = si_1.concat(si_2)
    nose.tools.assert_true(
        is_equal(
            si,
            claripy.SI(bits=16,
                       stride=0xff00,
                       lower_bound=0,
                       upper_bound=0xff00)))

    # Extract from a reversed value
    si_1 = claripy.SI(bits=64, stride=0xff, lower_bound=0x0, upper_bound=0xff)
    si_2 = si_1.reversed[63:56]
    nose.tools.assert_true(
        is_equal(
            si_2,
            claripy.SI(bits=8, stride=0xff, lower_bound=0x0,
                       upper_bound=0xff)))

    #
    # ValueSet
    #

    vs_1 = claripy.ValueSet(bits=32)
    nose.tools.assert_true(vs_1.model.is_empty, True)
    # Test merging two addresses
    vs_1.model.merge_si('global', si1)
    vs_1.model.merge_si('global', si3)
    nose.tools.assert_true(
        vs_1.model.get_si('global').identical(
            SI(bits=32, stride=18, lower_bound=10, upper_bound=28).model))
    # Length of this ValueSet
    nose.tools.assert_equal(len(vs_1.model), 32)

    vs_1 = claripy.ValueSet(name='boo', bits=32)
    vs_2 = claripy.ValueSet(name='foo', bits=32)
    nose.tools.assert_true(vs_1.identical(vs_1))
    nose.tools.assert_true(vs_2.identical(vs_2))
    vs_1.model.merge_si('global', si1)
    nose.tools.assert_false(vs_1.identical(vs_2))
    vs_2.model.merge_si('global', si1)
    nose.tools.assert_true(vs_1.identical(vs_2))
    nose.tools.assert_true(claripy.is_true((vs_1 & vs_2) == vs_1))
    vs_1.model.merge_si('global', si3)
    nose.tools.assert_false(vs_1.identical(vs_2))

    # Subtraction
    # Subtraction of two pointers yields a concrete value

    vs_1 = claripy.ValueSet(name='foo', region='global', bits=32, val=0x400010)
    vs_2 = claripy.ValueSet(name='bar', region='global', bits=32, val=0x400000)
    si = vs_1 - vs_2
    nose.tools.assert_is(type(si.model), StridedInterval)
    nose.tools.assert_true(
        si.identical(
            claripy.SI(bits=32, stride=0, lower_bound=0x10, upper_bound=0x10)))

    #
    # IfProxy
    #

    # max and min on IfProxy
    si = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=0xffffffff)
    if_0 = claripy.If(si == 0, si, si - 1)
    max_val = b.max(if_0)
    min_val = b.min(if_0)
    nose.tools.assert_true(max_val, 0xffffffff)
    nose.tools.assert_true(min_val, -0x80000000)

    # identical
    nose.tools.assert_true(if_0.identical(if_0))
    nose.tools.assert_false(if_0.identical(si))
    if_0_copy = claripy.If(si == 0, si, si - 1)
    nose.tools.assert_true(if_0.identical(if_0_copy))
    if_1 = claripy.If(si == 1, si, si - 1)
    nose.tools.assert_true(if_0.identical(if_1))

    si = SI(bits=32, stride=0, lower_bound=1, upper_bound=1)
    if_0 = claripy.If(si == 0, si, si - 1)
    if_0_copy = claripy.If(si == 0, si, si - 1)
    nose.tools.assert_true(if_0.identical(if_0_copy))
    if_1 = claripy.If(si == 1, si, si - 1)
    nose.tools.assert_false(if_0.identical(if_1))
    if_1 = claripy.If(si == 0, si + 1, si - 1)
    nose.tools.assert_true(if_0.identical(if_1))
    if_1 = claripy.If(si == 0, si, si)
    nose.tools.assert_false(if_0.identical(if_1))

    # if_1 = And(VS_2, IfProxy(si == 0, 0, 1))
    vs_2 = VS(region='global', bits=32, val=0xFA7B00B)
    si = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=1)
    if_1 = (vs_2 & claripy.If(
        si == 0, claripy.SI(bits=32, stride=0, lower_bound=0, upper_bound=0),
        claripy.SI(
            bits=32, stride=0, lower_bound=0xffffffff,
            upper_bound=0xffffffff)))
    nose.tools.assert_true(
        claripy.is_true(
            if_1.model.trueexpr == VS(region='global', bits=32, val=0).model))
    nose.tools.assert_true(claripy.is_true(if_1.model.falseexpr == vs_2.model))

    # if_2 = And(VS_3, IfProxy(si != 0, 0, 1)
    vs_3 = claripy.ValueSet(region='global', bits=32, val=0xDEADCA7)
    si = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=1)
    if_2 = (vs_3 & claripy.If(
        si != 0, claripy.SI(bits=32, stride=0, lower_bound=0, upper_bound=0),
        claripy.SI(
            bits=32, stride=0, lower_bound=0xffffffff,
            upper_bound=0xffffffff)))
    nose.tools.assert_true(
        claripy.is_true(
            if_2.model.trueexpr == VS(region='global', bits=32, val=0).model))
    nose.tools.assert_true(claripy.is_true(if_2.model.falseexpr == vs_3.model))

    # Something crazy is gonna happen...
    if_3 = if_1 + if_2
    nose.tools.assert_true(claripy.is_true(if_3.model.trueexpr == vs_3.model))
    nose.tools.assert_true(claripy.is_true(if_3.model.falseexpr == vs_2.model))
Ejemplo n.º 17
0
 def _fp_vector_comparison(cmp, a0, a1):
     # for cmpps_eq stuff, i.e. Iop_CmpEQ32Fx4
     return claripy.If(cmp(a0, a1), claripy.BVV(-1, len(a0)),
                       claripy.BVV(0, len(a0)))
Ejemplo n.º 18
0
    def check_state(self, state, path=None):
        """Check a reachable state for bugs"""
        logger.debug("Check state: %s", state)
        logger.debug("Constraints: %s", state.solver.constraints)

        solver = state.solver.branch()

        if path is None:
            path = [state]
            # Static read were we never wrote, but we know the key is not symbolic.
            # So we go and fetch it.
            for key, value in state.storage_read.items():
                constraint = state.storage_read[key] == self._read_storage(
                    state, key)
                solver.add(constraint)
                logger.debug("Add storage constraint: %s", constraint)

        for s in path:
            solver.add(list(s.env.extra_constraints()))
            solver.add([
                s.env.caller == utils.DEFAULT_CALLER,
                s.env.origin == utils.DEFAULT_CALLER,
            ])

        # Calls
        total_sent = sum(s.env.value for s in path)
        sent_constraints = [s.env.value < self.max_wei_to_send for s in path]

        total_received_by_me = utils.bvv(0)
        total_received = utils.bvv(0)

        for call in state.calls:
            # TODO: Improve delegatecall support! And make it clearer it's
            # delegatecall, not just based on the length.
            assert 6 <= len(call) <= 7
            value, to, gas = call[-3:]  # pylint: disable=unused-variable,invalid-name

            delegatecall = len(call) == 6

            if delegatecall:
                if solver.satisfiable(
                        extra_constraints=[to[159:0] == self.caller[159:0]]):
                    logger.info("Found delegatecall bug.")
                    solver.add(to[159:0] == self.caller[159:0])
                    return solver
            else:
                total_received_by_me += claripy.If(
                    to[159:0] == self.caller[159:0], value, utils.bvv(0))
                total_received += value
                solver.add(value <= total_sent + path[0].env.balance)

        final_balance = path[0].env.balance + total_sent - total_received

        # Suicide
        if state.selfdestruct_to is not None:
            constraints = [
                final_balance >= self.min_wei_to_receive,
                state.selfdestruct_to[159:0] == self.caller[159:0],
            ]
            logger.debug("Check for selfdestruct bug with constraints %s",
                         constraints)
            if solver.satisfiable(extra_constraints=constraints):
                logger.info("Found selfdestruct bug.")
                solver.add(constraints)
                return solver

        if total_received_by_me is utils.bvv(0):
            return

        logger.debug("Found calls back to caller: %s", total_received_by_me)

        solver.add(sent_constraints)
        solver.add([
            claripy.SGE(final_balance, 0),
            total_received_by_me > total_sent,  # I get more than what I sent?
            total_received_by_me > self.min_wei_to_receive,
        ])

        if solver.satisfiable():
            logger.info("Found call bug.")
            return solver
Ejemplo n.º 19
0
 def skip_check_equal(state):
     buffer_addr = 0x0804A054
     load_buffer_symbol = state.memory.load(buffer_addr, 16)
     check_str = 'XYMKBKUHNIQYNQXE'
     state.regs.eax = claripy.If(load_buffer_symbol == check_str,
                                 claripy.BVV(1, 32), claripy.BVV(0, 32))
Ejemplo n.º 20
0
def test_expression():
    bc = claripy.backends.concrete

    e = claripy.BVV(0x01020304, 32)
    nose.tools.assert_equal(len(e), 32)
    r = e.reversed
    nose.tools.assert_equal(bc.convert(r), 0x04030201)
    nose.tools.assert_equal(len(r), 32)

    nose.tools.assert_equal([bc.convert(i) for i in r.chop(8)], [4, 3, 2, 1])

    e1 = r[31:24]
    nose.tools.assert_equal(bc.convert(e1), 0x04)
    nose.tools.assert_equal(len(e1), 8)
    nose.tools.assert_equal(bc.convert(e1[2]), 1)
    nose.tools.assert_equal(bc.convert(e1[1]), 0)

    ee1 = e1.zero_extend(8)
    nose.tools.assert_equal(bc.convert(ee1), 0x0004)
    nose.tools.assert_equal(len(ee1), 16)

    ee1 = claripy.BVV(0xfe, 8).sign_extend(8)
    nose.tools.assert_equal(bc.convert(ee1), 0xfffe)
    nose.tools.assert_equal(len(ee1), 16)

    xe1 = [bc.convert(i) for i in e1.chop(1)]
    nose.tools.assert_equal(xe1, [0, 0, 0, 0, 0, 1, 0, 0])

    a = claripy.BVV(1, 1)
    nose.tools.assert_equal(bc.convert(a + a), 2)

    x = claripy.BVV(1, 32)
    nose.tools.assert_equal(x.length, 32)
    y = claripy.LShR(x, 10)
    nose.tools.assert_equal(y.length, 32)

    r = claripy.BVV(0x01020304, 32)
    rr = r.reversed
    rrr = rr.reversed
    #nose.tools.assert_is(bc.convert(r), bc.convert(rrr))
    #nose.tools.assert_is(type(bc.convert(rr)), claripy.A)
    nose.tools.assert_equal(bc.convert(rr), 0x04030201)
    nose.tools.assert_is(r.concat(rr), claripy.Concat(r, rr))

    rsum = r + rr
    nose.tools.assert_equal(bc.convert(rsum), 0x05050505)

    r = claripy.BVS('x', 32)
    rr = r.reversed
    rrr = rr.reversed
    nose.tools.assert_is(r, rrr)

    # test identity
    nose.tools.assert_is(r, rrr)
    nose.tools.assert_is_not(r, rr)
    ii = claripy.BVS('ii', 32)
    ij = claripy.BVS('ij', 32)
    nose.tools.assert_is(ii, ii)
    nose.tools.assert_is_not(ii, ij)

    si = claripy.SI(bits=32, stride=2, lower_bound=20, upper_bound=100)
    sj = claripy.SI(bits=32, stride=2, lower_bound=10, upper_bound=10)
    sk = claripy.SI(bits=32, stride=2, lower_bound=20, upper_bound=100)
    nose.tools.assert_true(claripy.backends.vsa.identical(si, si))
    nose.tools.assert_false(claripy.backends.vsa.identical(si, sj))
    nose.tools.assert_true(claripy.backends.vsa.identical(si, sk))
    nose.tools.assert_is_not(si, sj)
    nose.tools.assert_is_not(sj, sk)
    nose.tools.assert_is_not(sk, si)

    # test hash cache
    nose.tools.assert_is(a + a, a + a)

    # test replacement
    old = claripy.BVS('old', 32, explicit_name=True)
    new = claripy.BVS('new', 32, explicit_name=True)
    ooo = claripy.BVV(0, 32)

    old_formula = claripy.If((old + 1) % 256 == 0, old + 10, old + 20)
    print(old_formula.dbg_repr())
    new_formula = old_formula.replace(old, new)
    print(new_formula.dbg_repr())
    ooo_formula = new_formula.replace(new, ooo)

    print(ooo_formula.dbg_repr())

    nose.tools.assert_not_equal(hash(old_formula), hash(new_formula))
    nose.tools.assert_not_equal(hash(old_formula), hash(ooo_formula))
    nose.tools.assert_not_equal(hash(new_formula), hash(ooo_formula))

    nose.tools.assert_equal(old_formula.variables, {'old'})
    nose.tools.assert_equal(new_formula.variables, {'new'})
    nose.tools.assert_equal(ooo_formula.variables, ooo.variables)

    nose.tools.assert_true(old_formula.symbolic)
    nose.tools.assert_true(new_formula.symbolic)
    nose.tools.assert_true(new_formula.symbolic)

    nose.tools.assert_equal(
        str(old_formula).replace('old', 'new'), str(new_formula))
    nose.tools.assert_equal(bc.convert(ooo_formula), 20)

    # test dict replacement
    old = claripy.BVS('old', 32, explicit_name=True)
    new = claripy.BVS('new', 32, explicit_name=True)
    c = (old + 10) - (old + 20)
    d = (old + 1) - (old + 2)
    cr = c.replace_dict({
        (old + 10).cache_key: (old + 1),
        (old + 20).cache_key: (old + 2)
    })
    nose.tools.assert_is(cr, d)

    # test AST collapse
    s = claripy.SI(bits=32, stride=0, lower_bound=10, upper_bound=10)
    b = claripy.BVV(20, 32)

    sb = s + b
    nose.tools.assert_is_instance(sb.args[0], claripy.ast.Base)

    bb = b + b
    # this was broken previously -- it was checking if type(bb.args[0]) == A,
    # and it wasn't, but was instead a subclass. leaving this out for now
    # nose.tools.assert_not_is_instance(bb.args[0], claripy.ast.Base)

    # ss = s+s
    # (see above)
    # nose.tools.assert_not_is_instance(ss.args[0], claripy.ast.Base)

    sob = s | b
    # for now, this is collapsed. Presumably, Fish will make it not collapse at some point
    nose.tools.assert_is_instance(sob.args[0], claripy.ast.Base)

    # make sure the AST collapses for delayed ops like reversing
    rb = b.reversed
    #nose.tools.assert_is_instance(rb.args[0], claripy.ast.Base)
    # TODO: Properly delay reversing: should not be eager

    nose.tools.assert_is_not(rb, bb)
    nose.tools.assert_is(rb, rb)

    # test some alternate bvv creation methods
    nose.tools.assert_is(claripy.BVV('AAAA'), claripy.BVV(0x41414141, 32))
    nose.tools.assert_is(claripy.BVV('AAAA', 32), claripy.BVV(0x41414141, 32))
    nose.tools.assert_is(claripy.BVV('AB'), claripy.BVV(0x4142, 16))
    nose.tools.assert_is(claripy.BVV('AB', 16), claripy.BVV(0x4142, 16))
    nose.tools.assert_raises(claripy.errors.ClaripyValueError, claripy.BVV,
                             'AB', 8)
Ejemplo n.º 21
0
def test_some_vector_ops():
    engine = HeavyVEXMixin(None)
    s = SimState(arch="AMD64")

    def translate(state, op, args):
        return engine._perform_vex_expr_Op(op, args)

    a = s.solver.BVV(0xFFFF0000000100020003000400050006, 128)
    b = s.solver.BVV(0x00020002000200020002000200020002, 128)

    calc_result = translate(s, "Iop_Sub16x8", (a, b))
    correct_result = s.solver.BVV(0xFFFDFFFEFFFF00000001000200030004, 128)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_CmpEQ16x8", (a, b))
    correct_result = s.solver.BVV(0x000000000000FFFF0000000000000000, 128)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_CmpEQ8x16", (a, b))
    correct_result = s.solver.BVV(0x0000FF00FF00FFFFFF00FF00FF00FF00, 128)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_CmpGT16Sx8", (a, b))
    correct_result = s.solver.BVV(0x0000000000000000FFFFFFFFFFFFFFFF, 128)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_CmpGT16Ux8", (a, b))
    correct_result = s.solver.BVV(0xFFFF000000000000FFFFFFFFFFFFFFFF, 128)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_InterleaveLO16x8", (a, b))
    correct_result = s.solver.BVV(0x00030002000400020005000200060002, 128)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_InterleaveLO8x16", (a, b))
    correct_result = s.solver.BVV(0x00000302000004020000050200000602, 128)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_Min8Ux16", (a, b))
    correct_result = s.solver.BVV(0x00020000000100020002000200020002, 128)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_Min8Sx16", (a, b))
    correct_result = s.solver.BVV(0xFFFF0000000100020002000200020002, 128)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_QNarrowBin16Sto8Ux16", (a, b))
    correct_result = s.solver.BVV(0x00000102030405060202020202020202, 128)
    assert s.solver.is_true(calc_result == correct_result)

    c = s.solver.BVV(0xFF008877, 32)
    d = s.solver.BVV(0x11111111, 32)

    calc_result = translate(s, "Iop_HAdd8Sx4", (c, d))
    correct_result = s.solver.BVV(0x0808CC44, 32)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_QAdd8Sx4", (c, d))
    correct_result = s.solver.BVV(0x1011997F, 32)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_QAdd8Ux4", (c, d))
    correct_result = s.solver.BVV(0xFF119988, 32)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_QSub8Sx4", (c, d))
    correct_result = s.solver.BVV(0xEEEF8066, 32)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_QSub8Ux4", (c, d))
    correct_result = s.solver.BVV(0xEE007766, 32)
    assert s.solver.is_true(calc_result == correct_result)

    e = s.solver.BVV(0xFF00887766554433, 64)
    f = s.solver.BVV(0x0202000200020002, 64)

    calc_result = translate(s, "Iop_QNarrowBin16Sto8Ux8", (e, f))
    correct_result = s.solver.BVV(0x0000FFFFFF020202, 64)
    assert s.solver.is_true(calc_result == correct_result)

    gg = claripy.BVV(0x111111112222222233333333FFFFFFFF, 128)
    h = claripy.BVV(0x1111111100000000FFFFFFFFFFFFFFFF, 128)

    calc_result = translate(s, "Iop_CmpEQ32Fx4", (gg, h))
    correct_result = claripy.BVV(0xFFFFFFFF000000000000000000000000, 128)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_Clz32x4", (gg, ))
    correct_result = claripy.BVV(0x00000003000000020000000200000000, 128)
    assert s.solver.is_true(calc_result == correct_result)

    i = claripy.BVV(0x1001000000001000, 64)
    j = claripy.BVV(0x100000000000F000, 64)

    calc_result = translate(s, "Iop_Mull16Sx4", (i, j))
    correct_result = claripy.BVV(0x10010000000000000000000FF000000, 128)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_Mull16Ux4", (i, j))
    correct_result = claripy.BVV(0x100100000000000000000000F000000, 128)
    assert s.solver.is_true(calc_result == correct_result)

    k = claripy.BVV(0xE7, 8)
    ll = claripy.BVV(0x1234, 16)
    m = claripy.BVV(0x12345678, 32)

    calc_result = translate(s, "Iop_Dup8x8", (k, ))
    correct_result = claripy.BVV(0xE7E7E7E7E7E7E7E7, 64)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_Dup8x16", (k, ))
    correct_result = claripy.BVV(0xE7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7, 128)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_Dup16x4", (ll, ))
    correct_result = claripy.BVV(0x1234123412341234, 64)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_Dup16x8", (ll, ))
    correct_result = claripy.BVV(0x12341234123412341234123412341234, 128)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_Dup32x2", (m, ))
    correct_result = claripy.BVV(0x1234567812345678, 64)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_Dup32x4", (m, ))
    correct_result = claripy.BVV(0x12345678123456781234567812345678, 128)
    assert s.solver.is_true(calc_result == correct_result)

    n = claripy.BVV(0x0123456789ABCDEF, 64)
    o = claripy.BVV(0xAF, 8)
    p = claripy.BVV(0xDFEC, 16)
    q = claripy.BVV(0xBFCFDFEF, 32)
    r = claripy.BVV(0x0102030405060708, 64)
    ss = claripy.BVS("index", 8)

    # According to the source code of LibVex, the index is a U8 constant
    calc_result = translate(s, "Iop_GetElem8x8", (n, claripy.BVV(0, 8)))
    correct_result = claripy.BVV(0xEF, 8)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_GetElem8x8", (n, claripy.BVV(1, 8)))
    correct_result = claripy.BVV(0xCD, 8)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_GetElem8x8", (n, claripy.BVV(6, 8)))
    correct_result = claripy.BVV(0x23, 8)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_GetElem8x8", (n, claripy.BVV(7, 8)))
    correct_result = claripy.BVV(0x01, 8)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_GetElem16x4", (n, claripy.BVV(0, 8)))
    correct_result = claripy.BVV(0xCDEF, 16)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_GetElem16x4", (n, claripy.BVV(3, 8)))
    correct_result = claripy.BVV(0x0123, 16)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_GetElem32x2", (n, claripy.BVV(0, 8)))
    correct_result = claripy.BVV(0x89ABCDEF, 32)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_GetElem32x2", (n, claripy.BVV(1, 8)))
    correct_result = claripy.BVV(0x01234567, 32)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_SetElem8x8", (n, claripy.BVV(0, 8), o))
    correct_result = claripy.BVV(0x0123456789ABCDAF, 64)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_SetElem8x8", (n, claripy.BVV(1, 8), o))
    correct_result = claripy.BVV(0x0123456789ABAFEF, 64)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_SetElem8x8", (n, claripy.BVV(6, 8), o))
    correct_result = claripy.BVV(0x01AF456789ABCDEF, 64)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_SetElem8x8", (n, claripy.BVV(7, 8), o))
    correct_result = claripy.BVV(0xAF23456789ABCDEF, 64)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_SetElem16x4", (n, claripy.BVV(0, 8), p))
    correct_result = claripy.BVV(0x0123456789ABDFEC, 64)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_SetElem16x4", (n, claripy.BVV(3, 8), p))
    correct_result = claripy.BVV(0xDFEC456789ABCDEF, 64)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_SetElem32x2", (n, claripy.BVV(0, 8), q))
    correct_result = claripy.BVV(0x01234567BFCFDFEF, 64)
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_SetElem32x2", (n, claripy.BVV(1, 8), q))
    correct_result = claripy.BVV(0xBFCFDFEF89ABCDEF, 64)
    assert s.solver.is_true(calc_result == correct_result)

    # Symbolic indexes
    calc_result = translate(ss, "Iop_GetElem8x8", (r, ss))
    correct_result = claripy.If(
        ss == 7,
        claripy.BVV(0x01, 8),
        claripy.If(
            ss == 6,
            claripy.BVV(0x02, 8),
            claripy.If(
                ss == 5,
                claripy.BVV(0x03, 8),
                claripy.If(
                    ss == 4,
                    claripy.BVV(0x04, 8),
                    claripy.If(
                        ss == 3,
                        claripy.BVV(0x05, 8),
                        claripy.If(
                            ss == 2,
                            claripy.BVV(0x06, 8),
                            claripy.If(ss == 1, claripy.BVV(0x07, 8),
                                       claripy.BVV(0x08, 8)),
                        ),
                    ),
                ),
            ),
        ),
    )
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_GetElem16x4", (r, ss))
    correct_result = claripy.If(
        ss == 3,
        claripy.BVV(0x0102, 16),
        claripy.If(
            ss == 2,
            claripy.BVV(0x0304, 16),
            claripy.If(ss == 1, claripy.BVV(0x0506, 16),
                       claripy.BVV(0x0708, 16)),
        ),
    )
    assert s.solver.is_true(calc_result == correct_result)

    calc_result = translate(s, "Iop_GetElem32x2", (r, ss))
    correct_result = claripy.If(ss == 1, claripy.BVV(0x01020304, 32),
                                claripy.BVV(0x05060708, 32))
    assert s.solver.is_true(calc_result == correct_result)

    r_slices = r.chop(8)
    calc_result = translate(s, "Iop_SetElem8x8", (r, ss, o))
    correct_result = claripy.Concat(
        claripy.If(ss == 7, o, r_slices[0]),
        claripy.If(ss == 6, o, r_slices[1]),
        claripy.If(ss == 5, o, r_slices[2]),
        claripy.If(ss == 4, o, r_slices[3]),
        claripy.If(ss == 3, o, r_slices[4]),
        claripy.If(ss == 2, o, r_slices[5]),
        claripy.If(ss == 1, o, r_slices[6]),
        claripy.If(ss == 0, o, r_slices[7]),
    )
    assert s.solver.is_true(calc_result == correct_result)

    r_slices = r.chop(16)
    calc_result = translate(s, "Iop_SetElem16x4", (r, ss, p))
    correct_result = claripy.Concat(
        claripy.If(ss == 3, p, r_slices[0]),
        claripy.If(ss == 2, p, r_slices[1]),
        claripy.If(ss == 1, p, r_slices[2]),
        claripy.If(ss == 0, p, r_slices[3]),
    )
    assert s.solver.is_true(calc_result == correct_result)

    r_slices = r.chop(32)
    calc_result = translate(s, "Iop_SetElem32x2", (r, ss, q))
    correct_result = claripy.Concat(
        claripy.If(ss == 1, q, r_slices[0]),
        claripy.If(ss == 0, q, r_slices[1]),
    )
    assert s.solver.is_true(calc_result == correct_result)
Ejemplo n.º 22
0
 def run(self, to_check, length):
     string = self.state.memory.load(to_check, length)
     return claripy.If(string == evil, claripy.BVV(1, 32),
                       claripy.BVV(0, 32))
Ejemplo n.º 23
0
 def _op_fgeneric_CmpEQ(self, a0, a1):  # pylint: disable=no-self-use
     # for cmpps_eq stuff, i.e. Iop_CmpEQ32Fx4
     return claripy.If(claripy.fpEQ(a0, a1), claripy.BVV(-1, len(a0)),
                       claripy.BVV(0, len(a0)))
Ejemplo n.º 24
0
def mag(value):
    mag_array = [0x0, 0x9908b0df]
    return claripy.If(value == 0, claripy.BVV(mag_array[0], 64),
                      claripy.BVV(mag_array[1], 64))
Ejemplo n.º 25
0
 def load(self, addr, condition=None, fallback=None, **kwargs):
     res = super().load(addr, condition=condition, **kwargs)
     if condition is not None and fallback is not None:
         res = claripy.If(condition, res, fallback)
     return res
Ejemplo n.º 26
0
 def evaluate_binary(self, size_out: int, size_in: int, in1: BV,
                     in2: BV) -> BV:
     # origin: ccall.py pc_actions_ADD
     res = in1 + in2
     return claripy.If(claripy.ULT(res, in1), claripy.BVV(1, 1),
                       claripy.BVV(0, 1))
Ejemplo n.º 27
0
def test_some_vector_ops():
    engine = HeavyVEXMixin(None)
    s = SimState(arch='AMD64')

    def translate(state, op, args):
        return engine._perform_vex_expr_Op(op, args)

    a = s.solver.BVV(0xffff0000000100020003000400050006, 128)
    b = s.solver.BVV(0x00020002000200020002000200020002, 128)

    calc_result = translate(s, 'Iop_Sub16x8', (a, b))
    correct_result = s.solver.BVV(0xfffdfffeffff00000001000200030004, 128)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_CmpEQ16x8', (a, b))
    correct_result = s.solver.BVV(0x000000000000ffff0000000000000000, 128)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_CmpEQ8x16', (a, b))
    correct_result = s.solver.BVV(0x0000ff00ff00ffffff00ff00ff00ff00, 128)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_CmpGT16Sx8', (a, b))
    correct_result = s.solver.BVV(0x0000000000000000ffffffffffffffff, 128)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_CmpGT16Ux8', (a, b))
    correct_result = s.solver.BVV(0xffff000000000000ffffffffffffffff, 128)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_InterleaveLO16x8', (a, b))
    correct_result = s.solver.BVV(0x00030002000400020005000200060002, 128)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_InterleaveLO8x16', (a, b))
    correct_result = s.solver.BVV(0x00000302000004020000050200000602, 128)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_Min8Ux16', (a, b))
    correct_result = s.solver.BVV(0x00020000000100020002000200020002, 128)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_Min8Sx16', (a, b))
    correct_result = s.solver.BVV(0xffff0000000100020002000200020002, 128)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_QNarrowBin16Sto8Ux16', (a, b))
    correct_result = s.solver.BVV(0x00000102030405060202020202020202, 128)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    c = s.solver.BVV(0xff008877, 32)
    d = s.solver.BVV(0x11111111, 32)

    calc_result = translate(s, 'Iop_HAdd8Sx4', (c, d))
    correct_result = s.solver.BVV(0x0808cc44, 32)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_QAdd8Sx4', (c, d))
    correct_result = s.solver.BVV(0x1011997f, 32)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_QAdd8Ux4', (c, d))
    correct_result = s.solver.BVV(0xff119988, 32)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_QSub8Sx4', (c, d))
    correct_result = s.solver.BVV(0xeeef8066, 32)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_QSub8Ux4', (c, d))
    correct_result = s.solver.BVV(0xee007766, 32)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    e = s.solver.BVV(0xff00887766554433, 64)
    f = s.solver.BVV(0x0202000200020002, 64)

    calc_result = translate(s, 'Iop_QNarrowBin16Sto8Ux8', (e, f))
    correct_result = s.solver.BVV(0x0000ffffff020202, 64)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    gg = claripy.BVV(0x111111112222222233333333ffffffff, 128)
    h = claripy.BVV(0x1111111100000000ffffffffffffffff, 128)

    calc_result = translate(s, 'Iop_CmpEQ32Fx4', (gg, h))
    correct_result = claripy.BVV(0xffffffff000000000000000000000000, 128)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_Clz32x4', (gg, ))
    correct_result = claripy.BVV(0x00000003000000020000000200000000, 128)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    i = claripy.BVV(0x1001000000001000, 64)
    j = claripy.BVV(0x100000000000f000, 64)

    calc_result = translate(s, 'Iop_Mull16Sx4', (i, j))
    correct_result = claripy.BVV(0x10010000000000000000000ff000000, 128)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_Mull16Ux4', (i, j))
    correct_result = claripy.BVV(0x100100000000000000000000f000000, 128)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    k = claripy.BVV(0xe7, 8)
    ll = claripy.BVV(0x1234, 16)
    m = claripy.BVV(0x12345678, 32)

    calc_result = translate(s, 'Iop_Dup8x8', (k, ))
    correct_result = claripy.BVV(0xe7e7e7e7e7e7e7e7, 64)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_Dup8x16', (k, ))
    correct_result = claripy.BVV(0xe7e7e7e7e7e7e7e7e7e7e7e7e7e7e7e7, 128)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_Dup16x4', (ll, ))
    correct_result = claripy.BVV(0x1234123412341234, 64)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_Dup16x8', (ll, ))
    correct_result = claripy.BVV(0x12341234123412341234123412341234, 128)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_Dup32x2', (m, ))
    correct_result = claripy.BVV(0x1234567812345678, 64)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_Dup32x4', (m, ))
    correct_result = claripy.BVV(0x12345678123456781234567812345678, 128)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    n = claripy.BVV(0x0123456789abcdef, 64)
    o = claripy.BVV(0xaf, 8)
    p = claripy.BVV(0xdfec, 16)
    q = claripy.BVV(0xbfcfdfef, 32)
    r = claripy.BVV(0x0102030405060708, 64)
    ss = claripy.BVS('index', 8)

    # According to the source code of LibVex, the index is a U8 constant
    calc_result = translate(s, 'Iop_GetElem8x8', (n, claripy.BVV(0, 8)))
    correct_result = claripy.BVV(0xef, 8)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_GetElem8x8', (n, claripy.BVV(1, 8)))
    correct_result = claripy.BVV(0xcd, 8)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_GetElem8x8', (n, claripy.BVV(6, 8)))
    correct_result = claripy.BVV(0x23, 8)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_GetElem8x8', (n, claripy.BVV(7, 8)))
    correct_result = claripy.BVV(0x01, 8)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_GetElem16x4', (n, claripy.BVV(0, 8)))
    correct_result = claripy.BVV(0xcdef, 16)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_GetElem16x4', (n, claripy.BVV(3, 8)))
    correct_result = claripy.BVV(0x0123, 16)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_GetElem32x2', (n, claripy.BVV(0, 8)))
    correct_result = claripy.BVV(0x89abcdef, 32)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_GetElem32x2', (n, claripy.BVV(1, 8)))
    correct_result = claripy.BVV(0x01234567, 32)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_SetElem8x8', (n, claripy.BVV(0, 8), o))
    correct_result = claripy.BVV(0x0123456789abcdaf, 64)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_SetElem8x8', (n, claripy.BVV(1, 8), o))
    correct_result = claripy.BVV(0x0123456789abafef, 64)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_SetElem8x8', (n, claripy.BVV(6, 8), o))
    correct_result = claripy.BVV(0x01af456789abcdef, 64)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_SetElem8x8', (n, claripy.BVV(7, 8), o))
    correct_result = claripy.BVV(0xaf23456789abcdef, 64)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_SetElem16x4', (n, claripy.BVV(0, 8), p))
    correct_result = claripy.BVV(0x0123456789abdfec, 64)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_SetElem16x4', (n, claripy.BVV(3, 8), p))
    correct_result = claripy.BVV(0xdfec456789abcdef, 64)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_SetElem32x2', (n, claripy.BVV(0, 8), q))
    correct_result = claripy.BVV(0x01234567bfcfdfef, 64)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_SetElem32x2', (n, claripy.BVV(1, 8), q))
    correct_result = claripy.BVV(0xbfcfdfef89abcdef, 64)
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    # Symbolic indexes
    calc_result = translate(ss, 'Iop_GetElem8x8', (r, ss))
    correct_result = claripy.If(
        ss == 7, claripy.BVV(0x01, 8),
        claripy.If(
            ss == 6, claripy.BVV(0x02, 8),
            claripy.If(
                ss == 5, claripy.BVV(0x03, 8),
                claripy.If(
                    ss == 4, claripy.BVV(0x04, 8),
                    claripy.If(
                        ss == 3, claripy.BVV(0x05, 8),
                        claripy.If(
                            ss == 2, claripy.BVV(0x06, 8),
                            claripy.If(ss == 1, claripy.BVV(0x07, 8),
                                       claripy.BVV(0x08, 8))))))))
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_GetElem16x4', (r, ss))
    correct_result = claripy.If(
        ss == 3, claripy.BVV(0x0102, 16),
        claripy.If(
            ss == 2, claripy.BVV(0x0304, 16),
            claripy.If(ss == 1, claripy.BVV(0x0506, 16),
                       claripy.BVV(0x0708, 16))))
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    calc_result = translate(s, 'Iop_GetElem32x2', (r, ss))
    correct_result = claripy.If(ss == 1, claripy.BVV(0x01020304, 32),
                                claripy.BVV(0x05060708, 32))
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    r_slices = r.chop(8)
    calc_result = translate(s, 'Iop_SetElem8x8', (r, ss, o))
    correct_result = claripy.Concat(claripy.If(ss == 7, o, r_slices[0]),
                                    claripy.If(ss == 6, o, r_slices[1]),
                                    claripy.If(ss == 5, o, r_slices[2]),
                                    claripy.If(ss == 4, o, r_slices[3]),
                                    claripy.If(ss == 3, o, r_slices[4]),
                                    claripy.If(ss == 2, o, r_slices[5]),
                                    claripy.If(ss == 1, o, r_slices[6]),
                                    claripy.If(ss == 0, o, r_slices[7]))
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    r_slices = r.chop(16)
    calc_result = translate(s, 'Iop_SetElem16x4', (r, ss, p))
    correct_result = claripy.Concat(claripy.If(ss == 3, p, r_slices[0]),
                                    claripy.If(ss == 2, p, r_slices[1]),
                                    claripy.If(ss == 1, p, r_slices[2]),
                                    claripy.If(ss == 0, p, r_slices[3]))
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))

    r_slices = r.chop(32)
    calc_result = translate(s, 'Iop_SetElem32x2', (r, ss, q))
    correct_result = claripy.Concat(
        claripy.If(ss == 1, q, r_slices[0]),
        claripy.If(ss == 0, q, r_slices[1]),
    )
    nose.tools.assert_true(s.solver.is_true(calc_result == correct_result))