Beispiel #1
0
    def _manage_callstack(state):
        # condition for call = Ijk_Call
        # condition for ret = stack pointer drops below call point
        if state.history.jumpkind == 'Ijk_Call':
            state._inspect('call', BP_BEFORE, function_address=state.regs._ip)
            new_func_addr = state._inspect_getattr('function_address', None)
            if new_func_addr is not None and not claripy.is_true(new_func_addr == state.regs._ip):
                state.regs._ip = new_func_addr

            try:
                if state.arch.call_pushes_ret:
                    ret_addr = state.mem[state.regs._sp].long.concrete
                else:
                    ret_addr = state.se.eval(state.regs._lr)
            except SimSolverModeError:
                # Use the address for UnresolvableTarget instead.
                ret_addr = state.project.simos.unresolvable_target

            try:
                state_addr = state.addr
            except (SimValueError, SimSolverModeError):
                state_addr = None

            try:
                stack_ptr = state.se.eval(state.regs._sp)
            except SimSolverModeError:
                stack_ptr = 0

            new_frame = CallStack(
                    call_site_addr=state.history.recent_bbl_addrs[-1],
                    func_addr=state_addr,
                    stack_ptr=stack_ptr,
                    ret_addr=ret_addr,
                    jumpkind='Ijk_Call')
            state.callstack.push(new_frame)

            state._inspect('call', BP_AFTER)
        else:
            while state.se.is_true(state.regs._sp > state.callstack.top.stack_ptr):
                state._inspect('return', BP_BEFORE, function_address=state.callstack.top.func_addr)
                state.callstack.pop()
                state._inspect('return', BP_AFTER)

            if not state.arch.call_pushes_ret and \
                    claripy.is_true(state.regs._ip == state.callstack.ret_addr) and \
                    claripy.is_true(state.regs._sp == state.callstack.stack_ptr):
                # very weird edge case that's not actually weird or on the edge at all:
                # if we use a link register for the return address, the stack pointer will be the same
                # before and after the call. therefore we have to check for equality with the marker
                # along with this other check with the instruction pointer to guess whether it's time
                # to pop a callframe. Still better than relying on Ijk_Ret.
                state._inspect('return', BP_BEFORE, function_address=state.callstack.top.func_addr)
                state.callstack.pop()
                state._inspect('return', BP_AFTER)
Beispiel #2
0
def test_self_modifying_code():
    p = angr.Project(os.path.join(test_location, 'cgc/stuff'))
    pg = p.factory.simgr(p.factory.entry_state(add_options={o.STRICT_PAGE_ACCESS}))
    pg.step(until=lambda lpg: len(lpg.active) != 1)
    retval = pg.one_deadended.regs.ebx
    nose.tools.assert_true(claripy.is_true(retval == 65))

    pgu = p.factory.simgr(p.factory.entry_state(add_options={o.STRICT_PAGE_ACCESS} | o.unicorn))
    pgu.step(until=lambda lpg: len(lpg.active) != 1)
    retval = pgu.one_deadended.regs.ebx
    nose.tools.assert_true(claripy.is_true(retval == 65))

    nose.tools.assert_true(pg.one_deadended.history.bbl_addrs.hardcopy == pgu.one_deadended.history.bbl_addrs.hardcopy)
Beispiel #3
0
    def preconstrain_file(self, content, simfile, set_length=False):
        """
        Preconstrain the contents of a file.

        :param content:     The content to preconstrain the file to. Can be a bytestring or a list thereof.
        :param simfile:     The actual simfile to preconstrain
        """
        repair_entry_state_opts = False
        if o.TRACK_ACTION_HISTORY in self.state.options:
            repair_entry_state_opts = True
            self.state.options -= {o.TRACK_ACTION_HISTORY}

        if set_length: # disable read bounds
            simfile.has_end = False

        pos = 0
        for write in content:
            if type(write) is int:
                write = bytes([write])
            data, length, pos = simfile.read(pos, len(write), short_reads=False)
            if not claripy.is_true(length == len(write)):
                raise AngrError("Bug in either SimFile or in usage of preconstrainer: couldn't get requested data from file")
            self.preconstrain(write, data)

        # if the file is a stream, reset its position
        if simfile.pos is not None:
            simfile.pos = 0

        if set_length: # enable read bounds; size is now maximum size
            simfile.has_end = True

        if repair_entry_state_opts:
            self.state.options |= {o.TRACK_ACTION_HISTORY}
Beispiel #4
0
def test_type_annotation():
    my_ty = angr.sim_type.SimTypeTop()
    ptr = claripy.BVS('ptr', 32).annotate(angr.type_backend.TypeAnnotation(angr.sim_type.SimTypePointer(my_ty, label=[])))
    ptroffset = ptr + 4

    bt = angr.type_backend.TypeBackend()
    tv = bt.convert(ptroffset)
    nose.tools.assert_is(tv.ty.pts_to, my_ty)
    nose.tools.assert_true(claripy.is_true(tv.ty.offset == 4))
Beispiel #5
0
    def _convert_claripy_bool_ast(self, cond):
        """
        Convert recovered reaching conditions from claripy ASTs to ailment Expressions

        :return: None
        """

        if isinstance(cond, ailment.Expr.Expression):
            return cond

        if cond.op == "BoolS" and claripy.is_true(cond):
            return cond
        if cond in self._condition_mapping:
            return self._condition_mapping[cond]

        _mapping = {
            'Not': lambda cond_: ailment.Expr.UnaryOp(None, 'Not', self._convert_claripy_bool_ast(cond_.args[0])),
            'And': lambda cond_: ailment.Expr.BinaryOp(None, 'LogicalAnd', (
                self._convert_claripy_bool_ast(cond_.args[0]),
                self._convert_claripy_bool_ast(cond_.args[1]),
            )),
            'Or': lambda cond_: ailment.Expr.BinaryOp(None, 'LogicalOr', (
                self._convert_claripy_bool_ast(cond_.args[0]),
                self._convert_claripy_bool_ast(cond_.args[1]),
            )),
            'ULE': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpULE',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            '__le__': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpLE',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            'UGT': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpUGT',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            '__gt__': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpGT',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            '__eq__': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpEQ',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            '__ne__': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpNE',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            '__xor__': lambda cond_: ailment.Expr.BinaryOp(None, 'Xor',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            'BVV': lambda cond_: ailment.Expr.Const(None, None, cond_.args[0], cond_.size()),
            'BoolV': lambda cond_: ailment.Expr.Const(None, None, True, 1) if cond_.args[0] is True
                                                                        else ailment.Expr.Const(None, None, False, 1),
        }

        if cond.op in _mapping:
            return _mapping[cond.op](cond)
        raise NotImplementedError(("Condition variable %s has an unsupported operator %s. "
                                   "Consider implementing.") % (cond, cond.op))
Beispiel #6
0
def test_ite_reverse():
    a = claripy.BVS('a', 32)
    cases = [(a == i, claripy.BVV(i, 32)) for i in range(30)]
    ast = claripy.ite_cases(cases, -1)
    ext_cases = list(claripy.reverse_ite_cases(ast))

    assert sum(1 if case.op == 'And' else 0 for case, _ in ext_cases)
    for case, val in ext_cases:
        if case.op == 'And':
            assert claripy.is_true(val == -1)
        else:
            assert any(case is orig_case and val is orig_val for orig_case, orig_val in cases)
Beispiel #7
0
def test_true_false_cache():
    claripy.backends._quick_backends.append(claripy.backends.z3)

    a = claripy.BVS("a_WILL_BE_VIOLATED", 32)
    c = a == a+1
    assert claripy.is_false(c)
    c.args[1].args = (a, claripy.BVV(0, 32))
    assert claripy.is_false(c)
    assert not claripy.is_true(c)
    assert not claripy.is_false(a == a)

    claripy.backends._quick_backends[-1:] = [ ]
Beispiel #8
0
    def _make_ites(self, seq):

        # search for a == ^a pairs

        while True:
            for node_0 in seq.nodes:
                if not type(node_0) is CodeNode:
                    continue
                rcond_0 = node_0.reaching_condition
                if rcond_0 is None:
                    continue
                for node_1 in seq.nodes:
                    if not type(node_1) is CodeNode:
                        continue
                    if node_0 is node_1:
                        continue
                    rcond_1 = node_1.reaching_condition
                    if rcond_1 is None:
                        continue
                    cond_ = claripy.simplify(claripy.Not(rcond_0) == rcond_1)
                    if claripy.is_true(cond_):
                        # node_0 and node_1 should be structured using an if-then-else
                        self._make_ite(seq, node_0, node_1)
                        break
            else:
                break

        # make all conditionally-reachable nodes ConditionNodes
        for i in range(len(seq.nodes)):
            node = seq.nodes[i]
            if node.reaching_condition is not None and not claripy.is_true(node.reaching_condition):
                if isinstance(node.node, ConditionalBreakNode):
                    # Put conditions together and simplify them
                    cond = claripy.And(node.reaching_condition, self._bool_variable_from_ail_condition(node.node.condition))
                    new_node = CodeNode(ConditionalBreakNode(node.node.addr, cond, node.node.target), None)
                else:
                    new_node = ConditionNode(node.addr, None, node.reaching_condition, node,
                                             None)
                seq.nodes[i] = new_node
Beispiel #9
0
    def dbg_repr(self, indent=0):
        indent_str = indent * " "
        s = ""
        if self.reaching_condition is not None and not claripy.is_true(self.reaching_condition):
            s += (indent_str + "if (<block-missing>; %s)\n" +
                 indent_str + "{\n" +
                 indent_str + "  %s\n" +
                 indent_str + "}") % \
                              (self.reaching_condition, self.node)
        else:
            s += indent_str + str(self.node)

        return s
Beispiel #10
0
    def run(self, lib_handle, name_addr):
        if lib_handle.symbolic:
            raise angr.errors.SimValueError("GetProcAddress called with symbolic library handle %s" % lib_handle)
        lib_handle = self.state.solver.eval(lib_handle)

        if lib_handle == 0:
            obj = self.project.loader.main_object
        else:
            for obj in self.project.loader.all_pe_objects:
                if obj.mapped_base == lib_handle:
                    break
            else:
                l.warning("GetProcAddress: invalid library handle %s", lib_handle)
                return 0

        if claripy.is_true(name_addr < 0x10000):
            # this matches the bogus name specified in the loader...
            ordinal = self.state.solver.eval(name_addr)
            name = 'ordinal.%d.%s' % (ordinal, obj.provides)
        else:
            name = self.state.mem[name_addr].string.concrete.decode('utf-8')

        full_name = '%s.%s' % (obj.provides, name)
        self.procs.add(full_name)

        sym = obj.get_symbol(name)
        if sym is None and name.endswith('@'):
            # There seems to be some mangling parsing being done in the linker?
            # I don't know what I'm doing
            for suffix in ['Z', 'XZ']:
                sym = obj.get_symbol(name + suffix)
                if sym is not None:
                    name = name + suffix
                    break

        if sym is None:
            l.info("GetProcAddress: object %s does not contain %s", obj.provides, name)
            return 0

        sym = sym.resolve_forwarder()
        if sym is None:
            l.warning("GetProcAddress: forwarding failed for %s from %s", name, obj.provides)
            return 0

        name = sym.name # fix ordinal names
        full_name = '%s.%s' % (obj.provides, name)
        self.procs.add(full_name)

        l.debug("GetProcAddress: Imported %s (%#x) from %s", name, sym.rebased_addr, obj.provides)
        return sym.rebased_addr
Beispiel #11
0
    def _load_bytes(self, addr, max_size, state=None, clemory=None):
        if not clemory:
            if state is None:
                raise SimEngineError('state and clemory cannot both be None in _load_bytes().')
            if o.ABSTRACT_MEMORY in state.options:
                # abstract memory
                clemory = state.memory.regions['global'].memory.mem._memory_backer
            else:
                # symbolic memory
                clemory = state.memory.mem._memory_backer

        buff, size = "", 0

        # Load from the clemory if we can
        smc = self._support_selfmodifying_code
        if state:
            try:
                p = state.memory.permissions(addr)
                if p.symbolic:
                    smc = True
                else:
                    smc = claripy.is_true(p & 2 != 0)
            except: # pylint: disable=bare-except
                smc = True # I don't know why this would ever happen, we checked this right?

        if not smc or not state:
            try:
                buff, size = clemory.read_bytes_c(addr)
            except KeyError:
                pass

        # If that didn't work, try to load from the state
        if size == 0 and state:
            if addr in state.memory and addr + max_size - 1 in state.memory:
                buff = state.se.eval(state.memory.load(addr, max_size, inspect=False), cast_to=str)
                size = max_size
            else:
                good_addrs = []
                for i in xrange(max_size):
                    if addr + i in state.memory:
                        good_addrs.append(addr + i)
                    else:
                        break

                buff = ''.join(chr(state.se.eval(state.memory.load(i, 1, inspect=False))) for i in good_addrs)
                size = len(buff)

        size = min(max_size, size)
        return buff, size
Beispiel #12
0
 def extract(self, state, addr, concrete=False):
     if self.length is None:
         out = None
         last_byte = state.memory.load(addr, 1)
         addr += 1
         while not claripy.is_true(last_byte == 0):
             out = last_byte if out is None else out.concat(last_byte)
             last_byte = state.memory.load(addr, 1)
             addr += 1
     else:
         out = state.memory.load(addr, self.length)
     if not concrete:
         return out if out is not None else claripy.BVV(0, 0)
     else:
         return state.solver.eval(out, cast_to=bytes) if out is not None else ''
Beispiel #13
0
def test_extract_concat_simplify():
    a = claripy.BVS("a", 32)
    assert a[31:0] is a
    assert a[31:8].concat(a[7:0]) is a  # pylint:disable=no-member
    assert a[31:16].concat(a[15:8], a[7:0]) is a  # pylint:disable=no-member
    assert a[31:24].concat(a[23:16], a[15:8], a[7:0]) is a  # pylint:disable=no-member

    a = claripy.BVS("a", 32)
    b = a + 100
    b_concat = b[31:8].concat(b[7:0])
    a100 = a + 100
    assert claripy.is_false(b_concat == a100) is False
    assert list(claripy.Solver().eval(b_concat == a100, 2)) == [ True ]
    assert b_concat is a100
    assert claripy.is_true(b_concat == a100)
Beispiel #14
0
 def extract(self, state, addr, concrete=False):
     if self.length is None:
         out = None
         last_byte = state.memory.load(addr, 2)
         addr += 2
         while not claripy.is_true(last_byte == 0):
             out = last_byte if out is None else out.concat(last_byte)
             last_byte = state.memory.load(addr, 2)
             addr += 2
     else:
         out = state.memory.load(addr, self.length*2)
     if out is None: out = claripy.BVV(0, 0)
     if not concrete:
         return out
     else:
         return u''.join(chr(state.solver.eval(x.reversed if state.arch.memory_endness == 'Iend_LE' else x)) for x in out.chop(16))
Beispiel #15
0
 def extract(self, state, addr, concrete=False):
     if self.length is None:
         out = None
         last_byte = state.memory.load(addr, 1)
         # if we try to extract a symbolic string, it's likely that we are going to be trapped in a very large loop.
         if state.solver.symbolic(last_byte):
             raise ValueError("Trying to extract a symbolic string at %#x" % state.solver.eval(addr))
         addr += 1
         while not claripy.is_true(last_byte == 0):
             out = last_byte if out is None else out.concat(last_byte)
             last_byte = state.memory.load(addr, 1)
             addr += 1
     else:
         out = state.memory.load(addr, self.length)
     if not concrete:
         return out if out is not None else claripy.BVV(0, 0)
     else:
         return state.solver.eval(out, cast_to=bytes) if out is not None else ''
Beispiel #16
0
 def extract(self, state, addr, concrete=False):
     if self.length is None:
         out = None
         last_byte = state.memory.load(addr, 1)
         # if we try to extract a symbolic string, it's likely that we are going to be trapped in a very large loop.
         if state.solver.symbolic(last_byte):
             raise ValueError("Trying to extract a symbolic string at %#x" % state.solver.eval(addr))
         addr += 1
         while not claripy.is_true(last_byte == 0):
             out = last_byte if out is None else out.concat(last_byte)
             last_byte = state.memory.load(addr, 1)
             addr += 1
     else:
         out = state.memory.load(addr, self.length)
     if not concrete:
         return out if out is not None else claripy.BVV(0, 0)
     else:
         return state.solver.eval(out, cast_to=bytes) if out is not None else ''
Beispiel #17
0
    def run(self, lib_handle, name_addr):
        if lib_handle.symbolic:
            raise angr.errors.SimValueError(
                "GetProcAddress called with symbolic library handle %s" %
                lib_handle)
        lib_handle = self.state.se.any_int(lib_handle)

        for obj in self.project.loader.all_pe_objects:
            if obj.mapped_base == lib_handle:
                break
        else:
            l.warning("GetProcAddress: invalid library handle %s", lib_handle)
            return 0

        if claripy.is_true(name_addr < 0x10000):
            # this matches the bogus name specified in the loader...
            ordinal = self.state.se.any_int(name_addr)
            name = 'ordinal.%d' % ordinal
        else:
            name = self.state.mem[name_addr].string.concrete

        full_name = '%s.%s' % (obj.provides, name)
        self.procs.add(full_name)

        sym = obj.get_symbol(name)
        if sym is None and name.endswith('@'):
            # There seems to be some mangling parsing being done in the linker?
            # I don't know what I'm doing
            for suffix in ['Z', 'XZ']:
                sym = obj.get_symbol(name + suffix)
                if sym is not None:
                    name = name + suffix
                    break

        if sym is None:
            l.warning("GetProcAddress: object %s does not contain %s",
                      obj.provides, name)
            return 0
        else:
            name = sym.name  # fix ordinal names
            full_name = '%s.%s' % (obj.provides, name)
            self.procs.add(full_name)

        return sym.rebased_addr
Beispiel #18
0
    def _make_condition_nodes(self, seq):

        # make all conditionally-reachable nodes ConditionNodes
        for i in range(len(seq.nodes)):
            node = seq.nodes[i]

            if isinstance(node, CodeNode):
                if isinstance(node.node, SequenceNode):
                    self._make_condition_nodes(node.node)

                if node.reaching_condition is not None and not claripy.is_true(node.reaching_condition):
                    if isinstance(node.node, ConditionalBreakNode):
                        # Put conditions together and simplify them
                        cond = claripy.And(node.reaching_condition, node.node.condition)
                        new_node = CodeNode(ConditionalBreakNode(node.node.addr, cond, node.node.target), None)
                    else:
                        new_node = ConditionNode(node.addr, None, node.reaching_condition, node,
                                                 None)
                    seq.nodes[i] = new_node
Beispiel #19
0
 def extract(self, state, addr, concrete=False):
     if self.length is None:
         out = None
         last_byte = state.memory.load(addr, 2)
         addr += 2
         while not claripy.is_true(last_byte == 0):
             out = last_byte if out is None else out.concat(last_byte)
             last_byte = state.memory.load(addr, 2)
             addr += 2
     else:
         out = state.memory.load(addr, self.length * 2)
     if out is None: out = claripy.BVV(0, 0)
     if not concrete:
         return out
     else:
         return u''.join(
             unichr(
                 state.se.eval(x.reversed if state.arch.memory_endness ==
                               'Iend_LE' else x)) for x in out.chop(16))
Beispiel #20
0
 def extract(self, state, addr, concrete=False):
     if self.length is None:
         out = None
         last_byte = state.memory.load(addr, 2)
         # if we try to extract a symbolic string, it's likely that we are going to be trapped in a very large loop.
         if state.solver.symbolic(last_byte):
             raise ValueError("Trying to extract a symbolic string at %#x" % state.solver.eval(addr))
         addr += 2
         while not claripy.is_true(last_byte == 0):
             out = last_byte if out is None else out.concat(last_byte)
             last_byte = state.memory.load(addr, 2)
             addr += 2
     else:
         out = state.memory.load(addr, self.length*2)
     if out is None: out = claripy.BVV(0, 0)
     if not concrete:
         return out
     else:
         return u''.join(chr(state.solver.eval(x.reversed if state.arch.memory_endness == 'Iend_LE' else x)) for x in out.chop(16))
Beispiel #21
0
 def extract(self, state, addr, concrete=False):
     if self.length is None:
         out = None
         last_byte = state.memory.load(addr, 2)
         # if we try to extract a symbolic string, it's likely that we are going to be trapped in a very large loop.
         if state.solver.symbolic(last_byte):
             raise ValueError("Trying to extract a symbolic string at %#x" % state.solver.eval(addr))
         addr += 2
         while not claripy.is_true(last_byte == 0):
             out = last_byte if out is None else out.concat(last_byte)
             last_byte = state.memory.load(addr, 2)
             addr += 2
     else:
         out = state.memory.load(addr, self.length*2)
     if out is None: out = claripy.BVV(0, 0)
     if not concrete:
         return out
     else:
         return u''.join(chr(state.solver.eval(x.reversed if state.arch.memory_endness == 'Iend_LE' else x)) for x in out.chop(16))
Beispiel #22
0
    def preconstrain_file(self, content, simfile, set_length=False):
        """
        Preconstrain the contents of a file.

        :param content:     The content to preconstrain the file to. Can be a bytestring or a list thereof.
        :param simfile:     The actual simfile to preconstrain
        """
        repair_entry_state_opts = False
        if o.TRACK_ACTION_HISTORY in self.state.options:
            repair_entry_state_opts = True
            self.state.options -= {o.TRACK_ACTION_HISTORY}

        if set_length:  # disable read bounds
            simfile.has_end = False

        pos = 0
        for write in content:
            if type(write) is int:
                write = bytes([write])
            data, length, pos = simfile.read(pos,
                                             len(write),
                                             disable_actions=True,
                                             inspect=False,
                                             short_reads=False)
            if not claripy.is_true(length == len(write)):
                raise AngrError(
                    "Bug in either SimFile or in usage of preconstrainer: couldn't get requested data from file"
                )
            self.preconstrain(write, data)

        # if the file is a stream, reset its position
        if simfile.pos is not None:
            simfile.pos = 0

        if set_length:  # enable read bounds; size is now maximum size
            simfile.has_end = True

        if repair_entry_state_opts:
            self.state.options |= {o.TRACK_ACTION_HISTORY}
Beispiel #23
0
    def _convert_claripy_bool_ast(self, cond):
        """
        Convert recovered reaching conditions from claripy ASTs to ailment Expressions

        :return: None
        """

        if claripy.is_true(cond):
            return cond
        if cond in self._condition_mapping:
            return self._condition_mapping[cond]

        _mapping = {
            'Not':
            lambda cond_: ailment.Expr.UnaryOp(
                None, 'Not', self._convert_claripy_bool_ast(cond_.args[0])),
        }

        if cond.op in _mapping:
            return _mapping[cond.op](cond)
        raise NotImplementedError(
            ("Condition variable %s has an unsupported operator %s. "
             "Consider implementing.") % cond.op)
Beispiel #24
0
    def _handle_LoadG(self, stmt):
        guard = self._expr(stmt.guard)
        guard_v = guard.one_value()

        if claripy.is_true(guard_v):
            # FIXME: full conversion support
            if stmt.cvt.find('Ident') < 0:
                l.warning('Unsupported conversion %s in LoadG.', stmt.cvt)
            load_expr = pyvex.expr.Load(stmt.end, stmt.cvt_types[1], stmt.addr)
            wr_tmp_stmt = pyvex.stmt.WrTmp(stmt.dst, load_expr)
            self._handle_WrTmp(wr_tmp_stmt)
        elif claripy.is_false(guard_v):
            wr_tmp_stmt = pyvex.stmt.WrTmp(stmt.dst, stmt.alt)
            self._handle_WrTmp(wr_tmp_stmt)
        else:
            if stmt.cvt.find('Ident') < 0:
                l.warning('Unsupported conversion %s in LoadG.', stmt.cvt)
            load_expr = pyvex.expr.Load(stmt.end, stmt.cvt_types[1], stmt.addr)

            load_expr_v = self._expr(load_expr)
            alt_v = self._expr(stmt.alt)

            data = load_expr_v.merge(alt_v)
            self._handle_WrTmpData(stmt.dst, data)
Beispiel #25
0
    def _handle_StoreG(self, stmt: pyvex.IRStmt.StoreG):
        guard = self._expr(stmt.guard)
        guard_v = guard.one_value()

        if claripy.is_true(guard_v):
            addr = self._expr(stmt.addr)
            if len(addr.values) == 1:
                addrs = next(iter(addr.values.values()))
                size = stmt.data.result_size(self.tyenv) // 8
                data = self._expr(stmt.data)
                self._store_core(addrs, size, data)
        elif claripy.is_false(guard_v):
            pass
        else:
            # guard.data == {True, False}
            # get current data
            addr = self._expr(stmt.addr)
            if len(addr.values) == 1:
                addrs = next(iter(addr.values.values()))
                size = stmt.data.result_size(self.tyenv) // 8
                data_old = self._load_core(addrs, size, stmt.endness)
                data = self._expr(stmt.data)

                self._store_core(addrs, size, data, data_old=data_old)
Beispiel #26
0
    def _load_bytes(self, addr, max_size, state=None, clemory=None):
        if not clemory:
            if state is None:
                raise SimEngineError('state and clemory cannot both be None in _load_bytes().')
            if o.ABSTRACT_MEMORY in state.options:
                # abstract memory
                clemory = state.memory.regions['global'].memory.mem._memory_backer
            else:
                # symbolic memory
                clemory = state.memory.mem._memory_backer

        buff, size = b"", 0

        # Load from the clemory if we can
        smc = self._support_selfmodifying_code
        if state and not smc:
            try:
                p = state.memory.permissions(addr)
                if p.symbolic:
                    smc = True
                else:
                    smc = claripy.is_true(p & 2 != 0)
            except: # pylint: disable=bare-except
                smc = True # I don't know why this would ever happen, we checked this right?

        if not smc or not state:
            try:
                start, backer = next(clemory.backers(addr))
            except StopIteration:
                pass
            else:
                if start <= addr:
                    offset = addr - start
                    buff = pyvex.ffi.from_buffer(backer) + offset
                    size = len(backer) - offset

        # If that didn't work, try to load from the state
        if size == 0 and state:
            fallback = True
            if addr in state.memory and addr + max_size - 1 in state.memory:
                try:
                    buff = state.solver.eval(state.memory.load(addr, max_size, inspect=False), cast_to=bytes)
                    size = max_size
                    fallback = False
                except SimError:
                    l.warning("Cannot load bytes at %#x. Fallback to the slow path.", addr)

            if fallback:
                buff_lst = [ ]
                symbolic_warned = False
                for i in range(max_size):
                    if addr + i in state.memory:
                        try:
                            byte = state.memory.load(addr + i, 1, inspect=False)
                            if byte.symbolic and not symbolic_warned:
                                symbolic_warned = True
                                l.warning("Executing symbolic code at %#x", addr + i)
                            buff_lst.append(state.solver.eval(byte))
                        except SimError:
                            break
                    else:
                        break

                buff = bytes(buff_lst)
                size = len(buff)

        size = min(max_size, size)
        return buff, size
Beispiel #27
0
def test_rcr():
    p = angr.Project(os.path.join(os.path.dirname(__file__), '../../binaries/tests/i386/rcr_test'))
    result = p.factory.successors(p.factory.entry_state()).successors[0]
    nose.tools.assert_true(claripy.is_true(result.regs.cl == 8))
    def setup_callsite(self, state, ret_addr, args, stack_base=None, alloc_base=None, grow_like_stack=True):
        """
        This function performs the actions of the caller getting ready to jump into a function.

        :param state:           The SimState to operate on
        :param ret_addr:        The address to return to when the called function finishes
        :param args:            The list of arguments that that the called function will see
        :param stack_base:      An optional pointer to use as the top of the stack, circa the function entry point
        :param alloc_base:      An optional pointer to use as the place to put excess argument data
        :param grow_like_stack: When allocating data at alloc_base, whether to allocate at decreasing addresses

        The idea here is that you can provide almost any kind of python type in `args` and it'll be translated to a
        binary format to be placed into simulated memory. Lists (representing arrays) must be entirely elements of the
        same type and size, while tuples (representing structs) can be elements of any type and size.
        If you'd like there to be a pointer to a given value, wrap the value in a `PointerWrapper`. Any value
        that can't fit in a register will be automatically put in a
        PointerWrapper.

        If stack_base is not provided, the current stack pointer will be used, and it will be updated.
        If alloc_base is not provided, the current stack pointer will be used, and it will be updated.
        You might not like the results if you provide stack_base but not alloc_base.

        grow_like_stack controls the behavior of allocating data at alloc_base. When data from args needs to be wrapped
        in a pointer, the pointer needs to point somewhere, so that data is dumped into memory at alloc_base. If you
        set alloc_base to point to somewhere other than the stack, set grow_like_stack to False so that sequencial
        allocations happen at increasing addresses.
        """
        allocator = AllocHelper(alloc_base if alloc_base is not None else state.regs.sp,
                grow_like_stack,
                self.arch.memory_endness == 'Iend_LE')

        if self.func_ty is not None:
            vals = [self._standardize_value(arg, ty, state, allocator.dump) for arg, ty in zip(args, self.func_ty.args)]
        else:
            vals = [self._standardize_value(arg, None, state, allocator.dump) for arg in args]

        arg_session = self.arg_session
        arg_locs = [None]*len(args)
        for i, (arg, val) in enumerate(zip(args, vals)):
            if self.is_fp_value(arg) or \
                    (self.func_ty is not None and isinstance(self.func_ty.args[i], SimTypeFloat)):
                arg_locs[i] = arg_session.next_arg(is_fp=True, size=val.length/8)
                continue
            if val.length > state.arch.bits or (self.func_ty is None and isinstance(arg, (str, unicode, list, tuple))):
                vals[i] = allocator.dump(val, state)
            elif val.length < state.arch.bits:
                if self.arch.memory_endness == 'Iend_LE':
                    vals[i] = val.concat(claripy.BVV(0, state.arch.bits - val.length))
                else:
                    vals[i] = claripy.BVV(0, state.arch.bits - val.length).concat(val)
            arg_locs[i] = arg_session.next_arg(is_fp=False, size=vals[i].length/8)

        if alloc_base is None:
            state.regs.sp = allocator.ptr

        if stack_base is None:
            state.regs.sp -= self.stack_space(arg_locs)

            # handle alignment
            while claripy.is_true((state.regs.sp + self.STACKARG_SP_DIFF) % self.STACK_ALIGNMENT != 0):
                state.regs.sp -= 1

        for loc, val in zip(arg_locs, vals):
            loc.set_value(state, val, endness='Iend_BE', stack_base=stack_base)
        self.return_addr.set_value(state, ret_addr, stack_base=stack_base)
Beispiel #29
0
def test_rcr():
    p = angr.Project(
        os.path.join(os.path.dirname(__file__), '..', '..', 'binaries',
                     'tests', 'i386', 'rcr_test'))
    result = p.factory.successors(p.factory.entry_state()).successors[0]
    nose.tools.assert_true(claripy.is_true(result.regs.cl == 8))
Beispiel #30
0
    def convert_claripy_bool_ast_core(self, cond, memo):
        if isinstance(cond, ailment.Expr.Expression):
            return cond

        if cond.op in {"BoolS", "BoolV"} and claripy.is_true(cond):
            return ailment.Expr.Const(None, None, True, 1)
        if cond in self._condition_mapping:
            return self._condition_mapping[cond]
        if cond.op in {"BVS", "BoolS"
                       } and cond.args[0] in self._condition_mapping:
            return self._condition_mapping[cond.args[0]]

        def _binary_op_reduce(op, args, signed=False):
            r = None
            for arg in args:
                if r is None:
                    r = self.convert_claripy_bool_ast(arg, memo=memo)
                else:
                    # TODO: Keep track of tags
                    r = ailment.Expr.BinaryOp(
                        None, op,
                        (r, self.convert_claripy_bool_ast(arg, memo=memo)),
                        signed)
            return r

        def _unary_op_reduce(op, arg):
            r = self.convert_claripy_bool_ast(arg, memo=memo)
            # TODO: Keep track of tags
            return ailment.Expr.UnaryOp(None, op, r)

        _mapping = {
            'Not':
            lambda cond_: _unary_op_reduce('Not', cond_.args[0]),
            'And':
            lambda cond_: _binary_op_reduce('LogicalAnd', cond_.args),
            'Or':
            lambda cond_: _binary_op_reduce('LogicalOr', cond_.args),
            '__le__':
            lambda cond_: _binary_op_reduce('CmpLE', cond_.args, signed=True),
            'SLE':
            lambda cond_: _binary_op_reduce('CmpLE', cond_.args, signed=True),
            '__lt__':
            lambda cond_: _binary_op_reduce('CmpLT', cond_.args, signed=True),
            'SLT':
            lambda cond_: _binary_op_reduce('CmpLT', cond_.args, signed=True),
            'UGT':
            lambda cond_: _binary_op_reduce('CmpGT', cond_.args),
            'UGE':
            lambda cond_: _binary_op_reduce('CmpGE', cond_.args),
            '__gt__':
            lambda cond_: _binary_op_reduce('CmpGT', cond_.args, signed=True),
            '__ge__':
            lambda cond_: _binary_op_reduce('CmpGE', cond_.args, signed=True),
            'SGT':
            lambda cond_: _binary_op_reduce('CmpGT', cond_.args, signed=True),
            'SGE':
            lambda cond_: _binary_op_reduce('CmpGE', cond_.args, signed=True),
            'ULT':
            lambda cond_: _binary_op_reduce('CmpLT', cond_.args),
            'ULE':
            lambda cond_: _binary_op_reduce('CmpLE', cond_.args),
            '__eq__':
            lambda cond_: _binary_op_reduce('CmpEQ', cond_.args),
            '__ne__':
            lambda cond_: _binary_op_reduce('CmpNE', cond_.args),
            '__add__':
            lambda cond_: _binary_op_reduce('Add', cond_.args, signed=False),
            '__sub__':
            lambda cond_: _binary_op_reduce('Sub', cond_.args),
            '__mul__':
            lambda cond_: _binary_op_reduce('Mul', cond_.args),
            '__xor__':
            lambda cond_: _binary_op_reduce('Xor', cond_.args),
            '__or__':
            lambda cond_: _binary_op_reduce('Or', cond_.args, signed=False),
            '__and__':
            lambda cond_: _binary_op_reduce('And', cond_.args),
            '__lshift__':
            lambda cond_: _binary_op_reduce('Shl', cond_.args),
            '__rshift__':
            lambda cond_: _binary_op_reduce('Sar', cond_.args),
            '__floordiv__':
            lambda cond_: _binary_op_reduce('Div', cond_.args),
            'LShR':
            lambda cond_: _binary_op_reduce('Shr', cond_.args),
            'BVV':
            lambda cond_: ailment.Expr.Const(None, None, cond_.args[0],
                                             cond_.size()),
            'BoolV':
            lambda cond_: ailment.Expr.Const(None, None, True, 1)
            if cond_.args[0] is True else ailment.Expr.Const(
                None, None, False, 1),
            'Extract':
            lambda cond_: self._convert_extract(*cond_.args, memo=memo),
        }

        if cond.op in _mapping:
            return _mapping[cond.op](cond)
        raise NotImplementedError(
            ("Condition variable %s has an unsupported operator %s. "
             "Consider implementing.") % (cond, cond.op))
Beispiel #31
0
 def __eq__(self, other):
     return self.name == other.name and self.source == other.source and claripy.is_true(
         self.offset == other.offset)
Beispiel #32
0
    def _load_bytes(self, addr, max_size, state=None, clemory=None):
        if not clemory:
            if state is None:
                raise SimEngineError(
                    'state and clemory cannot both be None in _load_bytes().')
            if o.ABSTRACT_MEMORY in state.options:
                # abstract memory
                clemory = state.memory.regions[
                    'global'].memory.mem._memory_backer
            else:
                # symbolic memory
                clemory = state.memory.mem._memory_backer

        buff, size = "", 0

        # Load from the clemory if we can
        smc = self._support_selfmodifying_code
        if state:
            try:
                p = state.memory.permissions(addr)
                if p.symbolic:
                    smc = True
                else:
                    smc = claripy.is_true(p & 2 != 0)
            except:  # pylint: disable=bare-except
                smc = True  # I don't know why this would ever happen, we checked this right?

        if not smc or not state:
            try:
                buff, size = clemory.read_bytes_c(addr)
            except KeyError:
                pass

        # If that didn't work, try to load from the state
        if size == 0 and state:
            fallback = True
            if addr in state.memory and addr + max_size - 1 in state.memory:
                try:
                    buff = state.se.eval(state.memory.load(addr,
                                                           max_size,
                                                           inspect=False),
                                         cast_to=str)
                    size = max_size
                    fallback = False
                except SimError:
                    l.warning(
                        "Cannot load bytes at %#x. Fallback to the slow path.",
                        addr)

            if fallback:
                buff_lst = []
                for i in xrange(max_size):
                    if addr + i in state.memory:
                        try:
                            buff_lst.append(
                                chr(
                                    state.se.eval(
                                        state.memory.load(addr + i,
                                                          1,
                                                          inspect=False))))
                        except SimError:
                            break
                    else:
                        break

                buff = ''.join(buff_lst)
                size = len(buff)

        size = min(max_size, size)
        return buff, size
    def convert_claripy_bool_ast(self, cond):
        """
        Convert recovered reaching conditions from claripy ASTs to ailment Expressions

        :return: None
        """

        if isinstance(cond, ailment.Expr.Expression):
            return cond

        if cond.op == "BoolS" and claripy.is_true(cond):
            return cond
        if cond in self._condition_mapping:
            return self._condition_mapping[cond]

        def _binary_op_reduce(op, args, signed=False):
            r = None
            for arg in args:
                if r is None:
                    r = self.convert_claripy_bool_ast(arg)
                else:
                    r = ailment.Expr.BinaryOp(
                        None, op, (r, self.convert_claripy_bool_ast(arg)),
                        signed)
            return r

        _mapping = {
            'Not':
            lambda cond_: ailment.Expr.UnaryOp(
                None, 'Not', self.convert_claripy_bool_ast(cond_.args[0])),
            'And':
            lambda cond_: _binary_op_reduce('LogicalAnd', cond_.args),
            'Or':
            lambda cond_: _binary_op_reduce('LogicalOr', cond_.args),
            '__le__':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'CmpLE',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), True),
            'SLE':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'CmpLE',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), True),
            '__lt__':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'CmpLT',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), True),
            'SLT':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'CmpLT',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), True),
            'UGT':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'CmpGT',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), False),
            'UGE':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'CmpGE',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), False),
            '__gt__':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'CmpGT',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), True),
            '__ge__':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'CmpGE',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), True),
            'SGT':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'CmpGT',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), True),
            'SGE':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'CmpGE',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), True),
            'ULT':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'CmpLT',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), False),
            'ULE':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'CmpLE',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), False),
            '__eq__':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'CmpEQ',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), False),
            '__ne__':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'CmpNE',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), False),
            '__add__':
            lambda cond_: _binary_op_reduce('Add', cond_.args, signed=False),
            '__sub__':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'Sub',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), False),
            '__mul__':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'Mul',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), False),
            '__xor__':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'Xor',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), False),
            '__or__':
            lambda cond_: _binary_op_reduce('Or', cond_.args, signed=False),
            '__and__':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'And',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), False),
            '__lshift__':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'Shl',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), False),
            '__rshift__':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'Sar',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), False),
            'LShR':
            lambda cond_: ailment.Expr.BinaryOp(
                None, 'Shr',
                tuple(map(self.convert_claripy_bool_ast, cond_.args)), False),
            'BVV':
            lambda cond_: ailment.Expr.Const(None, None, cond_.args[0],
                                             cond_.size()),
            'BoolV':
            lambda cond_: ailment.Expr.Const(None, None, True, 1)
            if cond_.args[0] is True else ailment.Expr.Const(
                None, None, False, 1),
        }

        if cond.op in _mapping:
            return _mapping[cond.op](cond)
        raise NotImplementedError(
            ("Condition variable %s has an unsupported operator %s. "
             "Consider implementing.") % (cond, cond.op))
Beispiel #34
0
    def _convert_claripy_bool_ast(self, cond):
        """
        Convert recovered reaching conditions from claripy ASTs to ailment Expressions

        :return: None
        """

        if isinstance(cond, ailment.Expr.Expression):
            return cond

        if cond.op == "BoolS" and claripy.is_true(cond):
            return cond
        if cond in self._condition_mapping:
            return self._condition_mapping[cond]

        _mapping = {
            'Not': lambda cond_: ailment.Expr.UnaryOp(None, 'Not', self._convert_claripy_bool_ast(cond_.args[0])),
            'And': lambda cond_: ailment.Expr.BinaryOp(None, 'LogicalAnd', (
                self._convert_claripy_bool_ast(cond_.args[0]),
                self._convert_claripy_bool_ast(cond_.args[1]),
            )),
            'Or': lambda cond_: ailment.Expr.BinaryOp(None, 'LogicalOr', (
                self._convert_claripy_bool_ast(cond_.args[0]),
                self._convert_claripy_bool_ast(cond_.args[1]),
            )),
            'ULE': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpULE',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            '__le__': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpLE',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            '__lt__': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpLT',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            'UGT': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpUGT',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            '__gt__': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpGT',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            '__eq__': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpEQ',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            '__ne__': lambda cond_: ailment.Expr.BinaryOp(None, 'CmpNE',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            '__add__': lambda cond_: ailment.Expr.BinaryOp(None, 'Add',
                                                           tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                           ),
            '__xor__': lambda cond_: ailment.Expr.BinaryOp(None, 'Xor',
                                                          tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                          ),
            '__and__': lambda cond_: ailment.Expr.BinaryOp(None, 'And',
                                                           tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                           ),
            'LShR': lambda cond_: ailment.Expr.BinaryOp(None, 'Shr',
                                                        tuple(map(self._convert_claripy_bool_ast, cond_.args)),
                                                        ),
            'BVV': lambda cond_: ailment.Expr.Const(None, None, cond_.args[0], cond_.size()),
            'BoolV': lambda cond_: ailment.Expr.Const(None, None, True, 1) if cond_.args[0] is True
                                                                        else ailment.Expr.Const(None, None, False, 1),
        }

        if cond.op in _mapping:
            return _mapping[cond.op](cond)
        raise NotImplementedError(("Condition variable %s has an unsupported operator %s. "
                                   "Consider implementing.") % (cond, cond.op))
Beispiel #35
0
    def _load_bytes(self, addr, max_size, state=None, clemory=None):
        if not clemory:
            if state is None:
                raise SimEngineError('state and clemory cannot both be None in _load_bytes().')
            if o.ABSTRACT_MEMORY in state.options:
                # abstract memory
                clemory = state.memory.regions['global'].memory.mem._memory_backer
            else:
                # symbolic memory
                clemory = state.memory.mem._memory_backer

        buff, size = b"", 0

        # Load from the clemory if we can
        smc = self._support_selfmodifying_code
        if state:
            try:
                p = state.memory.permissions(addr)
                if p.symbolic:
                    smc = True
                else:
                    smc = claripy.is_true(p & 2 != 0)
            except: # pylint: disable=bare-except
                smc = True # I don't know why this would ever happen, we checked this right?

        if not smc or not state:
            try:
                start, backer = next(clemory.backers(addr))
            except StopIteration:
                pass
            else:
                if start <= addr:
                    offset = addr - start
                    buff = pyvex.ffi.from_buffer(backer) + offset
                    size = len(backer) - offset

        # If that didn't work, try to load from the state
        if size == 0 and state:
            fallback = True
            if addr in state.memory and addr + max_size - 1 in state.memory:
                try:
                    buff = state.solver.eval(state.memory.load(addr, max_size, inspect=False), cast_to=bytes)
                    size = max_size
                    fallback = False
                except SimError:
                    l.warning("Cannot load bytes at %#x. Fallback to the slow path.", addr)

            if fallback:
                buff_lst = [ ]
                for i in range(max_size):
                    if addr + i in state.memory:
                        try:
                            buff_lst.append(state.solver.eval(state.memory.load(addr + i, 1, inspect=False)))
                        except SimError:
                            break
                    else:
                        break

                buff = bytes(buff_lst)
                size = len(buff)

        size = min(max_size, size)
        return buff, size
Beispiel #36
0
def test_wrapped_intervals():
    #SI = claripy.StridedInterval

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

    #
    # Signedness/unsignedness conversion
    #

    si1 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=0xffffffff)
    nose.tools.assert_equal(si1.model._signed_bounds(), [ (0x0, 0x7fffffff), (-0x80000000, -0x1) ])
    nose.tools.assert_equal(si1.model._unsigned_bounds(), [ (0x0, 0xffffffff) ])

    #
    # Addition
    #

    # Plain addition
    si1 = claripy.SI(bits=32, stride=1, lower_bound=-1, upper_bound=1)
    si2 = claripy.SI(bits=32, stride=1, lower_bound=-1, upper_bound=1)
    si3 = claripy.SI(bits=32, stride=1, lower_bound=-2, upper_bound=2)
    nose.tools.assert_true((si1 + si2).identical(si3))
    si4 = claripy.SI(bits=32, stride=1, lower_bound=0xfffffffe, upper_bound=2)
    nose.tools.assert_true((si1 + si2).identical(si4))
    si5 = claripy.SI(bits=32, stride=1, lower_bound=2, upper_bound=-2)
    nose.tools.assert_false((si1 + si2).identical(si5))

    # Addition with overflowing cardinality
    si1 = claripy.SI(bits=8, stride=1, lower_bound=0, upper_bound=0xfe)
    si2 = claripy.SI(bits=8, stride=1, lower_bound=0xfe, upper_bound=0xff)
    nose.tools.assert_true((si1 + si2).model.is_top)

    # Addition that shouldn't get a TOP
    si1 = claripy.SI(bits=8, stride=1, lower_bound=0, upper_bound=0xfe)
    si2 = claripy.SI(bits=8, stride=1, lower_bound=0, upper_bound=0)
    nose.tools.assert_false((si1 + si2).model.is_top)

    #
    # Subtraction
    #

    si1 = claripy.SI(bits=8, stride=1, lower_bound=10, upper_bound=15)
    si2 = claripy.SI(bits=8, stride=1, lower_bound=11, upper_bound=12)
    si3 = claripy.SI(bits=8, stride=1, lower_bound=-2, upper_bound=4)
    nose.tools.assert_true((si1 - si2).identical(si3))

    #
    # Multiplication
    #

    # integer multiplication
    si1 = claripy.SI(bits=32, to_conv=0xffff)
    si2 = claripy.SI(bits=32, to_conv=0x10000)
    si3 = claripy.SI(bits=32, to_conv=0xffff0000)
    nose.tools.assert_true((si1 * si2).identical(si3))

    # intervals multiplication
    si1 = claripy.SI(bits=32, stride=1, lower_bound=10, upper_bound=15)
    si2 = claripy.SI(bits=32, stride=1, lower_bound=20, upper_bound=30)
    si3 = claripy.SI(bits=32, stride=1, lower_bound=200, upper_bound=450)
    nose.tools.assert_true((si1 * si2).identical(si3))

    #
    # Division
    #

    # integer division
    si1 = claripy.SI(bits=32, to_conv=10)
    si2 = claripy.SI(bits=32, to_conv=5)
    si3 = claripy.SI(bits=32, to_conv=2)
    nose.tools.assert_true((si1 / si2).identical(si3))

    si3 = claripy.SI(bits=32, to_conv=0)
    nose.tools.assert_true((si2 / si1).identical(si3))

    # intervals division
    si1 = claripy.SI(bits=32, stride=1, lower_bound=10, upper_bound=100)
    si2 = claripy.SI(bits=32, stride=1, lower_bound=10, upper_bound=20)
    si3 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=10)
    nose.tools.assert_true((si1 / si2).identical(si3))

    #
    # Comparisons
    #

    # -1 == 0xff
    si1 = claripy.SI(bits=8, stride=1, lower_bound=-1, upper_bound=-1)
    si2 = claripy.SI(bits=8, stride=1, lower_bound=0xff, upper_bound=0xff)
    nose.tools.assert_true(claripy.is_true(si1 == si2))

    # -2 != 0xff
    si1 = claripy.SI(bits=8, stride=1, lower_bound=-2, upper_bound=-2)
    si2 = claripy.SI(bits=8, stride=1, lower_bound=0xff, upper_bound=0xff)
    nose.tools.assert_true(claripy.is_true(si1 != si2))

    # [-2, -1] < [1, 2] (signed arithmetic)
    si1 = claripy.SI(bits=8, stride=1, lower_bound=1, upper_bound=2)
    si2 = claripy.SI(bits=8, stride=1, lower_bound=-2, upper_bound=-1)
    nose.tools.assert_true(claripy.is_true(si2.SLT(si1)))

    # [-2, -1] <= [1, 2] (signed arithmetic)
    nose.tools.assert_true(claripy.is_true(si2.SLE(si1)))

    # [0xfe, 0xff] > [1, 2] (unsigned arithmetic)
    nose.tools.assert_true(claripy.is_true(si2.UGT(si1)))

    # [0xfe, 0xff] >= [1, 2] (unsigned arithmetic)
    nose.tools.assert_true(claripy.is_true(si2.UGE(si1)))
Beispiel #37
0
    def get_patches(self):
        cfg = self.patcher.cfg
        patches = []

        pnum = 0
        used_spec_chars = []
        for func, (func_name, func_obj) in self.ident.matches.items():
            if func_name not in PRINTF_VARIANTS:
                continue
            if func_obj.format_spec_char is None:
                l.warning("func_obj.format_spec_char is None")
                continue

            fmt_arg_pos = PRINTF_VARIANTS[func_name]
            callers = set.union(
                set(),
                *(cfg.get_predecessors(node)
                  for node in cfg.get_all_nodes(func.addr)))

            handled_addrs = set()
            func_to_cfg = {}
            for caller in callers:
                if caller.addr in handled_addrs:
                    continue

                try:
                    args, _ = self.ident.get_call_args(func, caller.addr)
                except KeyError:
                    continue

                fmt_str = args[fmt_arg_pos]
                if not claripy.is_true(claripy.Or(*(claripy.And(seg.min_addr <= fmt_str, fmt_str <= seg.max_addr)\
                        for seg in self.ro_segments))):
                    # we bad
                    break

                handled_addrs.add(caller.addr)
            else:
                # patch not necessary for this function
                continue

            pnum += 1  # we need this to ensure always different labels
            used_spec_chars.append(func_obj.format_spec_char)
            check = """
                ; is the address not in RO memory?
                cmp dword [esp+{stack_offset}], {{max_ro_addr}}
                jbe _end_printfcheck_%d

                ; int 3
                ; is the address in the flag page?
                cmp dword [esp+{stack_offset}], {flag_page}
                jb _check_for_percent_%d
                cmp dword [esp+{stack_offset}], {flag_page_almost_end}
                ja _check_for_percent_%d

                ; they're trying to read from the flag page! f**k them.
                jmp 0x41414141

            _check_for_percent_%d:
                push esi ; = pointer to string
                mov esi, [esp+{stack_offset_2}]
                push eax
                xor eax, eax; hash

            _loop_printfcheck_%d:
                cmp byte [esi], 0
                je _final_check_printfcheck_%d
                xor al, byte[esi]
                cmp byte[esi], {format_spec_char}
                jne _continue_printfcheck_%d
                    mov ah, 0x1
                _continue_printfcheck_%d:
                    inc esi
                    jmp _loop_printfcheck_%d

            _final_check_printfcheck_%d:
                test ah, ah
                je _restore_printfcheck_%d
                test al, al ; avoid al==0 as we do in the hash algorithm
                jne _do_not_inc_%d
                    inc al
                _do_not_inc_%d: ; the dynamic hash will always be bigger than 0, the hash list is null terminated
                    mov esi, {{hash_list_{format_spec_char}}}
                _hash_check_loop_%d:
                    cmp byte[esi], 0 ; the end of the list has been reached
                    je 0x41414141
                    cmp byte[esi], al ; esi points to the hash list
                    je _restore_printfcheck_%d
                    inc esi
                    jmp _hash_check_loop_%d

            _restore_printfcheck_%d:
                pop eax
                pop esi

            _end_printfcheck_%d:
            """.format(
                stack_offset=(fmt_arg_pos + 1) * 4,
                stack_offset_2=(fmt_arg_pos + 2) * 4,
                flag_page=FLAG_PAGE,
                flag_page_almost_end=FLAG_PAGE + 0xffc,
                format_spec_char=ord(func_obj.format_spec_char),
            ) % tuple([pnum] * 18)

            patches.append(
                InsertCodePatch(func.addr,
                                check,
                                priority=250,
                                name="noflagprintf_%d" % pnum))
            l.info("function at %#08x protected" % func.addr)

        if patches:
            max_ro_addr = max(seg.max_addr for seg in self.ro_segments)
            patches.append(AddLabelPatch(max_ro_addr, name="max_ro_addr"))

        # print repr(self.hash_dict)
        for fspec in set(used_spec_chars):
            hash_list = b"".join(self.hash_dict[fspec]) + b"\x00"
            patches.append(
                AddRODataPatch(hash_list,
                               name="hash_list_{format_spec_char}".format(
                                   format_spec_char=ord(fspec))))
        # print "\n".join(map(str,patches))
        return patches
    ss.add(z == itz)
    ss.add(itz != 0)
    nose.tools.assert_equal(ss.eval(y/x, 100), ( 2, ))
    nose.tools.assert_equal(sorted(ss.eval(x, 100)), [ 1, 10, 100 ])
    nose.tools.assert_equal(sorted(ss.eval(y, 100)), [ 2, 20, 200 ])

def test_ite_reverse():
    a = claripy.BVS('a', 32)
    cases = [(a == i, claripy.BVV(i, 32)) for i in range(30)]
    ast = claripy.ite_cases(cases, -1)
    ext_cases = list(claripy.reverse_ite_cases(ast))

    assert sum(1 if case.op == 'And' else 0 for case, _ in ext_cases)
    for case, val in ext_cases:
        if case.op == 'And':
            assert claripy.is_true(val == -1)
        else:
            assert any(case is orig_case and val is orig_val for orig_case, orig_val in cases)

def test_bool():
    bc = claripy.backends.concrete

    a = claripy.And(*[False, False, True])
    nose.tools.assert_equal(bc.convert(a), False)
    a = claripy.And(*[True, True, True])
    nose.tools.assert_equal(bc.convert(a), True)

    o = claripy.Or(*[False, False, True])
    nose.tools.assert_equal(bc.convert(o), True)
    o = claripy.Or(*[False, False, False])
    nose.tools.assert_equal(bc.convert(o), False)
Beispiel #39
0
    def _search_value(self):
        if self._arm:
            armins = self._string_to_insn(self._insbytes)
            if not self._arm64:
                if not self._armthumb:
                    # ARM instructions
                    if armins & 0x0C000000 == 0x04000000:
                        # LDR
                        thoughtval = armins & 0xFFF
                        if thoughtval != self.value:
                            raise ValueNotFoundError
                        imm12 = self._imm(12)
                        self.patch_value_expression = imm12.zero_extend(self.bits-12)
                        self.patch_bytes_expression = claripy.Concat(
                                BVV(armins >> 12, 20),
                                imm12
                            )
                        self._test_values = (1, 0xfff)
                    elif armins & 0x0E000000 == 0x02000000:
                        # Data processing w/ immediate
                        shiftval = (armins & 0xF00) >> 7
                        thoughtval = armins & 0xFF
                        thoughtval = ror(thoughtval, shiftval, 32)
                        if thoughtval != self.value:
                            raise ValueNotFoundError
                        shift = self._imm(4, 'shift')
                        imm8 = self._imm(8)
                        self.patch_value_expression = claripy.RotateRight(
                                imm8.zero_extend(32-8), shift.zero_extend(32-4)*2
                            )
                        self.patch_bytes_expression = claripy.Concat(
                                BVV(armins >> 12, 20),
                                shift,
                                imm8
                            )
                        self._test_values = (1, 0xff, 0xff000000)
                    elif armins & 0x0E400090 == 0x00400090:
                        # LDRH
                        thoughtval = (armins & 0xF) | ((armins & 0xF00) >> 4)
                        if thoughtval != self.value:
                            raise ValueNotFoundError
                        hinib = self._imm(4, 'hinib')
                        lonib = self._imm(4, 'lonib')
                        self.patch_value_expression = claripy.Concat(hinib, lonib).zero_extend(self.bits-8)
                        self.patch_bytes_expression = claripy.Concat(
                                BVV(armins >> 12, 20),
                                hinib,
                                BVV((armins >> 4) & 0xF, 4),
                                lonib
                            )
                        self._test_values = (1, 0xff)
                    elif armins & 0x0E000000 == 0x0C000000:
                        # Coprocessor data transfer
                        # i.e. FLD/FST
                        thoughtval = armins & 0xFF
                        thoughtval *= 4
                        if thoughtval != self.value:
                            raise ValueNotFoundError
                        imm8 = self._imm(8)
                        self.patch_value_expression = imm8.zero_extend(self.bits-8) << 2
                        self.patch_bytes_expression = claripy.Concat(
                                BVV(armins >> 8, 24),
                                imm8
                            )
                        self._test_values = (4, 0x3fc)
                    else:
                        raise ValueNotFoundError

                else:
                    # THUMB instructions
                    # https://ece.uwaterloo.ca/~ece222/ARM/ARM7-TDMI-manual-pt3.pdf
                    if self._inslen == 2:
                        # 16 bit instructions
                        if armins & 0xF000 in (0x9000, 0xA000):
                            # SP-relative LDR/STR, also SP-addiition
                            # page 26, 28
                            # unsigned offsets only, 10 bit imm stored w/o last two bits
                            thoughtval = armins & 0xFF
                            thoughtval *= 4
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm8 = self._imm(8)
                            self.patch_value_expression = imm8.zero_extend(self.bits-8) << 2
                            self.patch_bytes_expression = claripy.Concat(
                                    BVV(armins >> 8, 8),
                                    imm8
                                )
                            self._test_values = (4, 0x3fc)
                        elif armins & 0xFF00 == 0xB000:
                            # Add/sub offset to SP
                            # page 30
                            # uses sign bit, 9 bit imm stored w/o last two bits
                            thoughtval = armins & 0x7F
                            thoughtval *= 4
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm7 = self._imm(7)
                            self.patch_value_expression = imm7.zero_extend(self.bits-7) << 2
                            self.patch_bytes_expression = claripy.Concat(
                                    BVV(armins >> 7, 9),
                                    imm7
                                )
                            self._test_values = (4, 0x1fc)
                        elif armins & 0xFC00 == 0x1C00:
                            # ADD/SUB (immediate format)
                            # page 7
                            # uses sign bit, 3 bit immediate
                            thoughtval = (armins & 0x01C0) >> 6
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm3 = self._imm(3)
                            self.patch_value_expression = imm3.zero_extend(self.bits-3)
                            self.patch_bytes_expression = claripy.Concat(
                                    BVV(armins >> 9, 7),
                                    imm3,
                                    BVV(armins & 0x3F, 6)
                                )
                            self._test_values = (1, 7)
                        elif armins & 0xE000 == 0x2000:
                            # Move/Compare/Add/Subtract immediate
                            # page 9
                            # Unsigned 8 bit immediate
                            thoughtval = armins & 0xFF
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm8 = self._imm(8)
                            self.patch_value_expression = imm8.zero_extend(self.bits-8)
                            self.patch_bytes_expression = claripy.Concat(
                                    BVV(armins >> 8, 8),
                                    imm8
                                )
                            self._test_values = (1, 0xff)
                        elif armins & 0xF000 == 0x6000:
                            # Register-relative LDR/STR
                            # page 22
                            # unsigned 7 bit imm stored w/o last two bits
                            thoughtval = ((armins >> 6) & 0x1F) << 2
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm5 = self._imm(5)
                            self.patch_value_expression = imm5.zero_extend(self.bits-5) << 2
                            self.patch_bytes_expression = claripy.Concat(
                                    BVV(armins >> 11, 5),
                                    imm5,
                                    BVV(armins & 0x3F, 6)
                                )
                            self._test_values = (4, 0x7c)
                        elif armins & 0xF000 == 0x7000:
                            # Register-relative LDRB/STRB
                            # page 22
                            # unsigned 5 bit imm
                            thoughtval = (armins >> 6) & 0x1F
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm5 = self._imm(5)
                            self.patch_value_expression = imm5.zero_extend(self.bits-5)
                            self.patch_bytes_expression = claripy.Concat(
                                    BVV(armins >> 11, 5),
                                    imm5,
                                    BVV(armins & 0x3F, 6)
                                )
                            self._test_values = (1, 0x1f)
                        else:
                            raise ValueNotFoundError

                    elif self._inslen == 4:
                        # 32 bit instructions
                        # http://read.pudn.com/downloads159/doc/709030/Thumb-2SupplementReferenceManual.pdf
                        if armins & 0xFE1F0000 == 0xF81F0000 or \
                           armins & 0xFE800000 == 0xF8800000:
                            # Load/Store
                            # page 66, formats 1-2
                            # imm12 with designated sign bit
                            thoughtval = armins & 0xFFF
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm12 = self._imm(12)
                            self.patch_value_expression = imm12.zero_extend(self.bits-12)
                            self.patch_bytes_expression = claripy.Concat(
                                    BVV(armins >> 12, 20),
                                    imm12
                                )
                            self._test_values = (1, 0xfff)
                        elif armins & 0xFE800900 == 0xF8000800:
                            # Load/Store
                            # page 66, formats 3-4
                            # imm8 with designated sign bit
                            thoughtval = armins & 0xFF
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm8 = self._imm(8)
                            self.patch_value_expression = imm8.zero_extend(self.bits-8)
                            self.patch_bytes_expression = claripy.Concat(
                                    BVV(armins >> 8, 24),
                                    imm8
                                )
                            self._test_values = (1, 0xff)
                        elif armins & 0xFE800900 == 0xF8000900:
                            # Load/Store
                            # page 66, formats 5-6
                            # imm8, sign extended
                            thoughtval = armins & 0x7F
                            if armins & 0x80 == 0x80:
                                thoughtval = (thoughtval ^ 0x7F) + 1
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm8 = self._imm(8)
                            self.patch_value_expression = imm8.sign_extend(self.bits-8)
                            self.patch_bytes_expression = claripy.Concat(
                                    BVV(armins >> 8, 24),
                                    imm8
                                )
                            self._test_values = (-0x80, 0x7f)
                        elif armins & 0xFB408000 == 0xF2000000:
                            # Add/Sub
                            # page 53, format 2
                            # 12 bit immediate split into 3 bitfields
                            thoughtval = armins & 0xFF
                            thoughtval |= (armins & 0x7000) >> 4
                            thoughtval |= (armins & 0x04000000) >> 15
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm8 = self._imm(8)
                            imm3 = self._imm(3)
                            imm1 = self._imm(1)
                            self.patch_value_expression = claripy.Concat(
                                    imm1,
                                    imm3,
                                    imm8
                                ).zero_extend(self.bits-12)
                            self.patch_bytes_expression = claripy.Concat(
                                    BVV(armins >> 27, 5),
                                    imm1,
                                    BVV((armins & 0x03FF8000) >> 15, 11),
                                    imm3,
                                    BVV((armins & 0xF00) >> 8, 4),
                                    imm8
                                )
                            self._test_values = (1, 0xfff)
                        elif armins & 0xFB408000 == 0xF2400000:
                            # Move
                            # page 53, format 3
                            # 16 bit immediate split into 4 bitfields
                            thoughtval = armins & 0xFF
                            thoughtval |= (armins & 0x7000) >> 4
                            thoughtval |= (armins & 0x04000000) >> 15
                            thoughtval |= (armins & 0xF0000) >> 4
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm8 = self._imm(8)
                            imm3 = self._imm(3)
                            imm1 = self._imm(1)
                            imm4 = self._imm(1)
                            self.patch_value_expression = claripy.Concat(
                                    imm4,
                                    imm1,
                                    imm3,
                                    imm8
                                ).zero_extend(self.bits-12)
                            self.patch_bytes_expression = claripy.Concat(
                                    BVV(armins >> 27, 5),
                                    imm1,
                                    BVV((armins & 0x03F00000) >> 20, 6),
                                    imm4,
                                    BVV((armins & 0x00008000) >> 15, 1),
                                    imm3,
                                    BVV((armins & 0xF00) >> 8, 4),
                                    imm8
                                )
                            self._test_values = (1, 0xffff)
                        elif armins & 0xFA008000 == 0xF0000000:
                            # Data processing, modified 12 bit imm, aka EVIL
                            # page 53
                            # wow. just. wow.
                            imm12 = armins & 0xFF
                            imm12 |= (armins & 0x7000) >> 4
                            imm12 |= (armins & 0x04000000) >> 15
                            # decoding algorithm from page 93
                            if imm12 & 0xC00 == 0:
                                if imm12 & 0x300 == 0:
                                    thoughtval = imm12
                                elif imm12 & 0x300 == 0x100:
                                    thoughtval = imm12 & 0xFF
                                    thoughtval |= thoughtval << 16
                                elif imm12 & 0x300 == 0x200:
                                    thoughtval = (imm12 & 0xFF) << 8
                                    thoughtval |= thoughtval << 16
                                elif imm12 & 0x300 == 0x300:
                                    thoughtval = imm12 & 0xFF
                                    thoughtval |= thoughtval << 8
                                    thoughtval |= thoughtval << 16
                                else:
                                    assert False
                            else:
                                thoughtval = ror(0x80 | (imm12 & 0x7F), imm12 >> 7, 32)
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm12 = self._imm(12)
                            ITE = claripy.If
                            CAT = claripy.Concat
                            ROR = claripy.RotateRight
                            imm8 = imm12[7:0]
                            imm7 = imm12[6:0]
                            imm3 = imm12[10:8]
                            imm1 = imm12[11]
                            zero = BVV(0, 8)
                            bit = BVV(1, 1)
                            monster = ITE(imm12[11:10] == 0,
                                        ITE(imm12[9] == 0,
                                            ITE(imm12[8] == 0,
                                                imm12[7:0].zero_extend(32-8),
                                                CAT(zero, imm8, zero, imm8)
                                            ),
                                            ITE(imm12[8] == 0,
                                                CAT(imm8, zero, imm8, zero),
                                                CAT(imm8, imm8, imm8, imm8)
                                            )
                                        ),
                                        ROR(CAT(bit, imm7).zero_extend(32-8),
                                            imm12[11:7].zero_extend(32-5)
                                        )
                                      )
                            self.patch_value_expression = monster
                            self.patch_bytes_expression = claripy.Concat(
                                    BVV(armins >> 27, 5),
                                    imm1,
                                    BVV((armins & 0x03FF8000) >> 15, 11),
                                    imm3,
                                    BVV((armins & 0xF00) >> 8, 4),
                                    imm8
                                )
                            self._test_values = (0xff00ff00, 0x00ff00ff, 0xffffffff, 0xff, 0xff000000)
                        else:
                            raise ValueNotFoundError
                    else:
                        raise FidgetUnsupportedError("You found a THUMB instruction longer than 32 bits??")

            else:
                self.bit_length = 64
                # aarch64 instructions
                # can't find a reference doc?????? I'm pulling these from VEX, guest_arm64_toIR.c
                if armins & 0x7f800000 in (0x28800000, 0x29800000, 0x29000000):
                    # LDP/SDP
                    # line 4791
                    # 7 bit immediate signed offset, scaled by load size (from MSB)
                    shift = 3 if armins & 0x80000000 else 2
                    simm7 = (armins & 0x3f8000) >> 15
                    simm7 = resign_int(simm7, 7)
                    simm7 <<= shift
                    if simm7 != self.value:
                        raise ValueNotFoundError
                    imm7 = self._imm(7)
                    self.patch_value_expression = imm7.sign_extend(self.bits-7) << shift
                    self.patch_bytes_expression = claripy.Concat(
                            BVV((armins & 0xffc00000) >> 22, 10),
                            imm7,
                            BVV(armins & 0x7fff, 15)
                        )
                    self._test_values = (-0x40 << shift, 0x3f << shift)
                elif (armins & 0x3f800000 == 0x39000000) or \
                     (armins & 0x3f800000 == 0x39800000 and \
                          ((armins >> 30) | ((armins >> 22) & 1)) in (4, 2, 3, 0, 1)):
                    # LDR/STR, LDRS
                    # line 4639, 5008
                    # 12 bit immediate unsigned offset, scaled by load size (from 2 MSB)
                    shift = (armins & 0xc0000000) >> 30
                    offs = (armins & 0x3ffc00) >> 10
                    offs <<= shift
                    if offs != self.value:
                        raise ValueNotFoundError
                    imm12 = self._imm(12)
                    self.patch_value_expression = imm12.zero_extend(self.bits-12) << shift
                    self.patch_bytes_expression = claripy.Concat(
                            BVV((armins & 0xffc00000) >> 22, 10),
                            imm12,
                            BVV(armins & 0x3ff, 10)
                        )
                    self._test_values = (1 << shift, 0xfff << shift)
                elif armins & 0x1f000000 == 0x11000000:
                    # ADD/SUB imm
                    # line 2403
                    # 12 bit shifted unsigned immediate
                    if not armins & 0x80000000:
                        self.bit_length = 32
                    shift = (armins >> 22) & 3
                    imm12 = (armins >> 10) & 0xfff
                    imm12 <<= 12*shift
                    if imm12 != self.value:
                        raise ValueNotFoundError
                    shift = self._imm(1, 'shift')
                    imm12 = self._imm(12)
                    shift_full = shift.zero_extend(self.bits-1)*12
                    self.patch_value_expression = imm12.zero_extend(self.bits-12) << shift_full
                    self.patch_bytes_expression = claripy.Concat(
                            BVV(armins >> 24, 8),
                            BVV(0, 1),
                            shift,
                            imm12,
                            BVV(armins & 0x3ff, 10)
                        )
                    self._test_values = (1, 0xfff, 0xfff000)
                elif armins & 0x3fa00000 == 0x38000000:
                    # LDUR/STUR
                    # Line 4680
                    # 9 bit signed immediate offset
                    imm9 = (armins >> 12) & 0x1ff
                    imm9 = resign_int(imm9, 9)
                    if imm9 != self.value:
                        raise ValueNotFoundError
                    imm9 = self._imm(9)
                    self.patch_value_expression = imm9.sign_extend(self.bits-9)
                    self.patch_bytes_expression = claripy.Concat(
                            BVV(armins >> 21, 11),
                            imm9,
                            BVV(armins & 0xfff, 12)
                        )
                    self._test_values = (-0x100, 0xff)

                else:
                    raise ValueNotFoundError


            if not self.sanity_check():
                raise ValueNotFoundError
        else:
            insn = self._string_to_insn(self._insbytes)
            insn = BVV(insn, self._inslen*8)
            for word_size in (64, 32, 16, 8):
                if word_size > self.bits:
                    continue
                for bit_offset in range(0, insn.length-word_size+1, 8):
                    result = insn[bit_offset+word_size-1:bit_offset]
                    result = result.sign_extend(self.bits-word_size)
                    if claripy.is_true(result == self.value):
                        imm = self._imm(word_size)
                        self.patch_value_expression = imm.sign_extend(self.bits-word_size)
                        if bit_offset + word_size >= insn.length:
                            acc = imm
                        else:
                            acc = claripy.Concat(insn[insn.length-1:bit_offset+word_size], imm)
                        if bit_offset != 0:
                            acc = claripy.Concat(acc, insn[bit_offset-1:0])

                        if self._project.arch.memory_endness == 'Iend_LE':
                            self.patch_bytes_offset = bit_offset//8
                        else:
                            self.patch_bytes_offset = self._inslen - (bit_offset + word_size)//8

                        self.patch_bytes_size = word_size//8
                        self.patch_bytes_expression = acc
                        self._test_values = (-(1 << word_size) >> 1, ((1 << word_size) >> 1) - 1)

                        if self.sanity_check():
                            break   # found

                    if self._project.arch.name == 'PPC64':
                        # On PPC64, the lowest two bits of immediate values can be used for other things
                        # Mask those out
                        result = (result & ~3).sign_extend(self.bits-word_size)
                        if not claripy.is_true(result == self.value):
                            continue
                        imm = self._imm(word_size-2)
                        self.patch_value_expression = claripy.Concat(
                                imm,
                                BVV(0, 2)
                            ).sign_extend(self.bits-word_size)
                        if bit_offset + word_size >= insn.length:
                            acc = imm
                        else:
                            acc = claripy.Concat(insn[insn.length-1:bit_offset+word_size], imm)
                        acc = claripy.Concat(acc, insn[bit_offset+1:0])

                        if self._project.arch.memory_endness == 'Iend_LE':
                            self.patch_bytes_offset = bit_offset//8
                        else:
                            self.patch_bytes_offset = self._inslen - (bit_offset + word_size)//8

                        self.patch_bytes_size = word_size//8
                        self.patch_bytes_expression = acc
                        self._test_values = (-(1 << word_size) >> 1, ((1 << word_size) >> 1) - 4)
                        if self.sanity_check():
                            break   # found
                else:
                    # inner loop did not break: not found
                    continue
                # inner loop broke: found
                break
            else:
                # outer loop did not break: inner loop did not break: not found
                raise ValueNotFoundError
            # outer loop broke: inner loop broke: found
            return
Beispiel #40
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))))

    #
    # 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))))
Beispiel #41
0
    def _manage_callstack(state):
        # condition for call = Ijk_Call
        # condition for ret = stack pointer drops below call point
        if state.history.jumpkind == 'Ijk_Call':
            state._inspect('call', BP_BEFORE, function_address=state.regs._ip)
            new_func_addr = state._inspect_getattr('function_address', None)
            if new_func_addr is not None and not claripy.is_true(
                    new_func_addr == state.regs._ip):
                state.regs._ip = new_func_addr

            try:
                if state.arch.call_pushes_ret:
                    ret_addr = state.mem[state.regs._sp].long.concrete
                else:
                    ret_addr = state.solver.eval(state.regs._lr)
            except SimSolverModeError:
                # Use the address for UnresolvableCallTarget instead.
                ret_addr = state.project.simos.unresolvable_call_target

            try:
                state_addr = state.addr
            except (SimValueError, SimSolverModeError):
                state_addr = None

            try:
                stack_ptr = state.solver.eval(state.regs._sp)
            except SimSolverModeError:
                stack_ptr = 0

            new_frame = CallStack(
                call_site_addr=state.history.recent_bbl_addrs[-1],
                func_addr=state_addr,
                stack_ptr=stack_ptr,
                ret_addr=ret_addr,
                jumpkind='Ijk_Call')
            state.callstack.push(new_frame)

            state._inspect('call', BP_AFTER)
        else:
            while True:
                cur_sp = state.solver.max(state.regs._sp) if state.has_plugin(
                    'symbolizer') else state.regs._sp
                if not state.solver.is_true(
                        cur_sp > state.callstack.top.stack_ptr):
                    break
                state._inspect('return',
                               BP_BEFORE,
                               function_address=state.callstack.top.func_addr)
                state.callstack.pop()
                state._inspect('return', BP_AFTER)

            if not state.arch.call_pushes_ret and \
                    claripy.is_true(state.regs._ip == state.callstack.ret_addr) and \
                    claripy.is_true(state.regs._sp == state.callstack.stack_ptr):
                # very weird edge case that's not actually weird or on the edge at all:
                # if we use a link register for the return address, the stack pointer will be the same
                # before and after the call. therefore we have to check for equality with the marker
                # along with this other check with the instruction pointer to guess whether it's time
                # to pop a callframe. Still better than relying on Ijk_Ret.
                state._inspect('return',
                               BP_BEFORE,
                               function_address=state.callstack.top.func_addr)
                state.callstack.pop()
                state._inspect('return', BP_AFTER)
Beispiel #42
0
    def __init__(self, *args):
        super(JQ, self).__init__(*args)

        if claripy.is_true(self.rm) == 0 and claripy.is_true(self.mem == 0):
            self.NAME = 'HF'
Beispiel #43
0
    def _runtime_unify(self,
                       state,
                       one,
                       two,
                       stack_frame=False,
                       overwrite=True):
        """
        decide if one and two need to be unified, if so add a 'UNIFY' tag

        :param state:           The analysis state that holds intermediate results
        :param one:             The first value to unify
        :param two:             The second value to unify
        :param stack_frame:     If we're only allowed to look at offsets in front of the pointer
        :param overwrite:       Whether to use the semantics that one is "overwriting" two
        """

        one_ty = self.ty_backend.convert(one).ty
        two_ty = self.ty_backend.convert(two).ty

        # if both of them are pointers!!! this gets very tricky
        if type(one_ty) is type(two_ty) is sim_type.SimTypePointer:
            one_subty = one_ty.pts_to
            two_subty = two_ty.pts_to
            one_offset = one_ty.offset
            two_offset = two_ty.offset

            if one_offset.symbolic or two_offset.symbolic:
                import ipdb
                ipdb.set_trace()
                print('yikes! (jesus christ)')

            if one_subty is two_subty:
                if one_offset is not two_subty:
                    import ipdb
                    ipdb.set_trace()
                    print('yikes? (arrays maybe. recursion probably)')
                else:
                    import ipdb
                    ipdb.set_trace()
                    print('yikes. (no object identity but yes equality)')

            # these are two different structures that we might have to unify.
            # possible cases:
            # - two structures are actually the same structure.
            # - two stack frames. flag tells us this. only deal with the argument parts
            # - a structure is present in another structure
            # TODO: do some type checking on the two structs to make sure we're not making
            # a huge mistake!!!
            else:
                if claripy.is_true(
                        one_offset == two_offset) and claripy.is_true(
                            one_offset == 0):
                    self.pass_results.append(('UNIFY', (one, two)))
                elif stack_frame:
                    for ckey, _ in two_subty.offsets.iteritems():
                        offset = ckey.ast
                        if not claripy.is_true(claripy.SGT(offset, 0)):
                            continue

                        two_value = state.memory.load(
                            two + offset,
                            size=state.arch.bytes,
                            inspect=False,
                            endness=state.arch.memory_endness)
                        one_value = state.memory.load(
                            one + offset,
                            size=state.arch.bytes,
                            inspect=False,
                            endness=state.arch.memory_endness)

                        # one last edge case consideration: if one_value doesn't have a source
                        # (since we disabled inspect, this might happen)
                        # we should manually give it a source since this is something we know
                        one_value_ty = self.ty_backend.convert(one_value).ty
                        if type(one_value_ty) is not sim_type.SimTypePointer and \
                                len(one_value_ty.label) == 0:
                            one_value = one_value.annotate(
                                TypeAnnotation(
                                    sim_type.SimTypeTop(
                                        label=[ValueSource(two_subty, offset)
                                               ])))

                        self._runtime_unify(state, one_value, two_value)

                else:
                    import ipdb
                    ipdb.set_trace()
                    # look through the structs and check offset by offset
                    # do we want to check in the initial state or elsewhere?
                    # think we should check in the current state. everything from the initial state wil be there still?
                    print('okay??')

        # when only one of them is a pointer!
        # if a source is available we should toss it to SOURCE, she'll just drop the other in!
        # if a source is not available, wait. eventually one will be available :)
        elif type(two_ty) is sim_type.SimTypePointer:
            if len(one_ty.label) > 0:
                if len(one_ty.label) > 1:
                    import ipdb
                    ipdb.set_trace()
                    print('????????????')
                self.pass_results.append(('SOURCE', one_ty.label[0]))

        # this is where overwrite semantics comes into play.
        # if one overwrites two, then we can't mark two as a pointer just because 1 is a pointer.
        # otherwise, this is the same as the previous case I guess?
        # I'm not sure what good this does
        elif type(one_ty) is sim_type.SimTypePointer:
            import ipdb
            ipdb.set_trace()
            if not overwrite:
                if len(two_ty.label) > 0:
                    if len(two_ty.label) > 1:
                        import ipdb
                        ipdb.set_trace()
                        print('????????????')
                    self.pass_results.append(('SOURCE', two_ty.label[0]))

        # If neither of them are pointers bail out. this is not a general type inference :)
        else:
            pass
Beispiel #44
0
def test_rcr():
    p = angr.Project(os.path.join(os.path.dirname(__file__), '../../binaries/tests/i386/rcr_test'))
    path = p.factory.path()
    path.step()
    nose.tools.assert_true(claripy.is_true(path.successors[0].state.regs.cl == 8))
Beispiel #45
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))

    # 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)))

    #
    # 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='boo', bits=32)
    nose.tools.assert_true(vs_1.identical(vs_1))
    nose.tools.assert_true(vs_1.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))
    vs_1.model.merge_si('global', si3)
    nose.tools.assert_false(vs_1.identical(vs_2))

    #
    # 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)

    # 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))
Beispiel #46
0
 def _is_true(self, v):
     return claripy.is_true(v)
Beispiel #47
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))

    # 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)))

    #
    # 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='boo', bits=32)
    nose.tools.assert_true(vs_1.identical(vs_1))
    nose.tools.assert_true(vs_1.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))
    vs_1.model.merge_si('global', si3)
    nose.tools.assert_false(vs_1.identical(vs_2))

    #
    # 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)

    # 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))
Beispiel #48
0
def test_wrapped_intervals():
    #SI = claripy.StridedInterval

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

    #
    # Signedness/unsignedness conversion
    #

    si1 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=0xffffffff)
    nose.tools.assert_equal(si1.model._signed_bounds(), [(0x0, 0x7fffffff),
                                                         (-0x80000000, -0x1)])
    nose.tools.assert_equal(si1.model._unsigned_bounds(), [(0x0, 0xffffffff)])

    #
    # Addition
    #

    # Plain addition
    si1 = claripy.SI(bits=32, stride=1, lower_bound=-1, upper_bound=1)
    si2 = claripy.SI(bits=32, stride=1, lower_bound=-1, upper_bound=1)
    si3 = claripy.SI(bits=32, stride=1, lower_bound=-2, upper_bound=2)
    nose.tools.assert_true((si1 + si2).identical(si3))
    si4 = claripy.SI(bits=32, stride=1, lower_bound=0xfffffffe, upper_bound=2)
    nose.tools.assert_true((si1 + si2).identical(si4))
    si5 = claripy.SI(bits=32, stride=1, lower_bound=2, upper_bound=-2)
    nose.tools.assert_false((si1 + si2).identical(si5))

    # Addition with overflowing cardinality
    si1 = claripy.SI(bits=8, stride=1, lower_bound=0, upper_bound=0xfe)
    si2 = claripy.SI(bits=8, stride=1, lower_bound=0xfe, upper_bound=0xff)
    nose.tools.assert_true((si1 + si2).model.is_top)

    # Addition that shouldn't get a TOP
    si1 = claripy.SI(bits=8, stride=1, lower_bound=0, upper_bound=0xfe)
    si2 = claripy.SI(bits=8, stride=1, lower_bound=0, upper_bound=0)
    nose.tools.assert_false((si1 + si2).model.is_top)

    #
    # Subtraction
    #

    si1 = claripy.SI(bits=8, stride=1, lower_bound=10, upper_bound=15)
    si2 = claripy.SI(bits=8, stride=1, lower_bound=11, upper_bound=12)
    si3 = claripy.SI(bits=8, stride=1, lower_bound=-2, upper_bound=4)
    nose.tools.assert_true((si1 - si2).identical(si3))

    #
    # Multiplication
    #

    # integer multiplication
    si1 = claripy.SI(bits=32, to_conv=0xffff)
    si2 = claripy.SI(bits=32, to_conv=0x10000)
    si3 = claripy.SI(bits=32, to_conv=0xffff0000)
    nose.tools.assert_true((si1 * si2).identical(si3))

    # intervals multiplication
    si1 = claripy.SI(bits=32, stride=1, lower_bound=10, upper_bound=15)
    si2 = claripy.SI(bits=32, stride=1, lower_bound=20, upper_bound=30)
    si3 = claripy.SI(bits=32, stride=1, lower_bound=200, upper_bound=450)
    nose.tools.assert_true((si1 * si2).identical(si3))

    #
    # Division
    #

    # integer division
    si1 = claripy.SI(bits=32, to_conv=10)
    si2 = claripy.SI(bits=32, to_conv=5)
    si3 = claripy.SI(bits=32, to_conv=2)
    nose.tools.assert_true((si1 / si2).identical(si3))

    si3 = claripy.SI(bits=32, to_conv=0)
    nose.tools.assert_true((si2 / si1).identical(si3))

    # intervals division
    si1 = claripy.SI(bits=32, stride=1, lower_bound=10, upper_bound=100)
    si2 = claripy.SI(bits=32, stride=1, lower_bound=10, upper_bound=20)
    si3 = claripy.SI(bits=32, stride=1, lower_bound=0, upper_bound=10)
    nose.tools.assert_true((si1 / si2).identical(si3))

    #
    # Comparisons
    #

    # -1 == 0xff
    si1 = claripy.SI(bits=8, stride=1, lower_bound=-1, upper_bound=-1)
    si2 = claripy.SI(bits=8, stride=1, lower_bound=0xff, upper_bound=0xff)
    nose.tools.assert_true(claripy.is_true(si1 == si2))

    # -2 != 0xff
    si1 = claripy.SI(bits=8, stride=1, lower_bound=-2, upper_bound=-2)
    si2 = claripy.SI(bits=8, stride=1, lower_bound=0xff, upper_bound=0xff)
    nose.tools.assert_true(claripy.is_true(si1 != si2))

    # [-2, -1] < [1, 2] (signed arithmetic)
    si1 = claripy.SI(bits=8, stride=1, lower_bound=1, upper_bound=2)
    si2 = claripy.SI(bits=8, stride=1, lower_bound=-2, upper_bound=-1)
    nose.tools.assert_true(claripy.is_true(si2.SLT(si1)))

    # [-2, -1] <= [1, 2] (signed arithmetic)
    nose.tools.assert_true(claripy.is_true(si2.SLE(si1)))

    # [0xfe, 0xff] > [1, 2] (unsigned arithmetic)
    nose.tools.assert_true(claripy.is_true(si2.UGT(si1)))

    # [0xfe, 0xff] >= [1, 2] (unsigned arithmetic)
    nose.tools.assert_true(claripy.is_true(si2.UGE(si1)))
Beispiel #49
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))))

    #
    # 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))))
Beispiel #50
0
    def _search_value(self):
        if self._arm:
            armins = self._string_to_insn(self._insbytes)
            if not self._arm64:
                if not self._armthumb:
                    # ARM instructions
                    if armins & 0x0C000000 == 0x04000000:
                        # LDR
                        thoughtval = armins & 0xFFF
                        if thoughtval != self.value:
                            raise ValueNotFoundError
                        imm12 = self._imm(12)
                        self.patch_value_expression = imm12.zero_extend(
                            self.bits - 12)
                        self.patch_bytes_expression = claripy.Concat(
                            BVV(armins >> 12, 20), imm12)
                        self._test_values = (1, 0xfff)
                    elif armins & 0x0E000000 == 0x02000000:
                        # Data processing w/ immediate
                        shiftval = (armins & 0xF00) >> 7
                        thoughtval = armins & 0xFF
                        thoughtval = ror(thoughtval, shiftval, 32)
                        if thoughtval != self.value:
                            raise ValueNotFoundError
                        shift = self._imm(4, 'shift')
                        imm8 = self._imm(8)
                        self.patch_value_expression = claripy.RotateRight(
                            imm8.zero_extend(32 - 8),
                            shift.zero_extend(32 - 4) * 2)
                        self.patch_bytes_expression = claripy.Concat(
                            BVV(armins >> 12, 20), shift, imm8)
                        self._test_values = (1, 0xff, 0xff000000)
                    elif armins & 0x0E400090 == 0x00400090:
                        # LDRH
                        thoughtval = (armins & 0xF) | ((armins & 0xF00) >> 4)
                        if thoughtval != self.value:
                            raise ValueNotFoundError
                        hinib = self._imm(4, 'hinib')
                        lonib = self._imm(4, 'lonib')
                        self.patch_value_expression = claripy.Concat(
                            hinib, lonib).zero_extend(self.bits - 8)
                        self.patch_bytes_expression = claripy.Concat(
                            BVV(armins >> 12, 20), hinib,
                            BVV((armins >> 4) & 0xF, 4), lonib)
                        self._test_values = (1, 0xff)
                    elif armins & 0x0E000000 == 0x0C000000:
                        # Coprocessor data transfer
                        # i.e. FLD/FST
                        thoughtval = armins & 0xFF
                        thoughtval *= 4
                        if thoughtval != self.value:
                            raise ValueNotFoundError
                        imm8 = self._imm(8)
                        self.patch_value_expression = imm8.zero_extend(
                            self.bits - 8) << 2
                        self.patch_bytes_expression = claripy.Concat(
                            BVV(armins >> 8, 24), imm8)
                        self._test_values = (4, 0x3fc)
                    else:
                        raise ValueNotFoundError

                else:
                    # THUMB instructions
                    # https://ece.uwaterloo.ca/~ece222/ARM/ARM7-TDMI-manual-pt3.pdf
                    if self._inslen == 2:
                        # 16 bit instructions
                        if armins & 0xF000 in (0x9000, 0xA000):
                            # SP-relative LDR/STR, also SP-addiition
                            # page 26, 28
                            # unsigned offsets only, 10 bit imm stored w/o last two bits
                            thoughtval = armins & 0xFF
                            thoughtval *= 4
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm8 = self._imm(8)
                            self.patch_value_expression = imm8.zero_extend(
                                self.bits - 8) << 2
                            self.patch_bytes_expression = claripy.Concat(
                                BVV(armins >> 8, 8), imm8)
                            self._test_values = (4, 0x3fc)
                        elif armins & 0xFF00 == 0xB000:
                            # Add/sub offset to SP
                            # page 30
                            # uses sign bit, 9 bit imm stored w/o last two bits
                            thoughtval = armins & 0x7F
                            thoughtval *= 4
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm7 = self._imm(7)
                            self.patch_value_expression = imm7.zero_extend(
                                self.bits - 7) << 2
                            self.patch_bytes_expression = claripy.Concat(
                                BVV(armins >> 7, 9), imm7)
                            self._test_values = (4, 0x1fc)
                        elif armins & 0xFC00 == 0x1C00:
                            # ADD/SUB (immediate format)
                            # page 7
                            # uses sign bit, 3 bit immediate
                            thoughtval = (armins & 0x01C0) >> 6
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm3 = self._imm(3)
                            self.patch_value_expression = imm3.zero_extend(
                                self.bits - 3)
                            self.patch_bytes_expression = claripy.Concat(
                                BVV(armins >> 9, 7), imm3,
                                BVV(armins & 0x3F, 6))
                            self._test_values = (1, 7)
                        elif armins & 0xE000 == 0x2000:
                            # Move/Compare/Add/Subtract immediate
                            # page 9
                            # Unsigned 8 bit immediate
                            thoughtval = armins & 0xFF
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm8 = self._imm(8)
                            self.patch_value_expression = imm8.zero_extend(
                                self.bits - 8)
                            self.patch_bytes_expression = claripy.Concat(
                                BVV(armins >> 8, 8), imm8)
                            self._test_values = (1, 0xff)
                        elif armins & 0xF000 == 0x6000:
                            # Register-relative LDR/STR
                            # page 22
                            # unsigned 7 bit imm stored w/o last two bits
                            thoughtval = ((armins >> 6) & 0x1F) << 2
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm5 = self._imm(5)
                            self.patch_value_expression = imm5.zero_extend(
                                self.bits - 5) << 2
                            self.patch_bytes_expression = claripy.Concat(
                                BVV(armins >> 11, 5), imm5,
                                BVV(armins & 0x3F, 6))
                            self._test_values = (4, 0x7c)
                        elif armins & 0xF000 == 0x7000:
                            # Register-relative LDRB/STRB
                            # page 22
                            # unsigned 5 bit imm
                            thoughtval = (armins >> 6) & 0x1F
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm5 = self._imm(5)
                            self.patch_value_expression = imm5.zero_extend(
                                self.bits - 5)
                            self.patch_bytes_expression = claripy.Concat(
                                BVV(armins >> 11, 5), imm5,
                                BVV(armins & 0x3F, 6))
                            self._test_values = (1, 0x1f)
                        else:
                            raise ValueNotFoundError

                    elif self._inslen == 4:
                        # 32 bit instructions
                        # http://read.pudn.com/downloads159/doc/709030/Thumb-2SupplementReferenceManual.pdf
                        if armins & 0xFE1F0000 == 0xF81F0000 or \
                           armins & 0xFE800000 == 0xF8800000:
                            # Load/Store
                            # page 66, formats 1-2
                            # imm12 with designated sign bit
                            thoughtval = armins & 0xFFF
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm12 = self._imm(12)
                            self.patch_value_expression = imm12.zero_extend(
                                self.bits - 12)
                            self.patch_bytes_expression = claripy.Concat(
                                BVV(armins >> 12, 20), imm12)
                            self._test_values = (1, 0xfff)
                        elif armins & 0xFE800900 == 0xF8000800:
                            # Load/Store
                            # page 66, formats 3-4
                            # imm8 with designated sign bit
                            thoughtval = armins & 0xFF
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm8 = self._imm(8)
                            self.patch_value_expression = imm8.zero_extend(
                                self.bits - 8)
                            self.patch_bytes_expression = claripy.Concat(
                                BVV(armins >> 8, 24), imm8)
                            self._test_values = (1, 0xff)
                        elif armins & 0xFE800900 == 0xF8000900:
                            # Load/Store
                            # page 66, formats 5-6
                            # imm8, sign extended
                            thoughtval = armins & 0x7F
                            if armins & 0x80 == 0x80:
                                thoughtval = (thoughtval ^ 0x7F) + 1
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm8 = self._imm(8)
                            self.patch_value_expression = imm8.sign_extend(
                                self.bits - 8)
                            self.patch_bytes_expression = claripy.Concat(
                                BVV(armins >> 8, 24), imm8)
                            self._test_values = (-0x80, 0x7f)
                        elif armins & 0xFB408000 == 0xF2000000:
                            # Add/Sub
                            # page 53, format 2
                            # 12 bit immediate split into 3 bitfields
                            thoughtval = armins & 0xFF
                            thoughtval |= (armins & 0x7000) >> 4
                            thoughtval |= (armins & 0x04000000) >> 15
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm8 = self._imm(8)
                            imm3 = self._imm(3)
                            imm1 = self._imm(1)
                            self.patch_value_expression = claripy.Concat(
                                imm1, imm3, imm8).zero_extend(self.bits - 12)
                            self.patch_bytes_expression = claripy.Concat(
                                BVV(armins >> 27, 5), imm1,
                                BVV((armins & 0x03FF8000) >> 15, 11), imm3,
                                BVV((armins & 0xF00) >> 8, 4), imm8)
                            self._test_values = (1, 0xfff)
                        elif armins & 0xFB408000 == 0xF2400000:
                            # Move
                            # page 53, format 3
                            # 16 bit immediate split into 4 bitfields
                            thoughtval = armins & 0xFF
                            thoughtval |= (armins & 0x7000) >> 4
                            thoughtval |= (armins & 0x04000000) >> 15
                            thoughtval |= (armins & 0xF0000) >> 4
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm8 = self._imm(8)
                            imm3 = self._imm(3)
                            imm1 = self._imm(1)
                            imm4 = self._imm(1)
                            self.patch_value_expression = claripy.Concat(
                                imm4, imm1, imm3,
                                imm8).zero_extend(self.bits - 12)
                            self.patch_bytes_expression = claripy.Concat(
                                BVV(armins >> 27, 5), imm1,
                                BVV((armins & 0x03F00000) >> 20, 6), imm4,
                                BVV((armins & 0x00008000) >> 15, 1), imm3,
                                BVV((armins & 0xF00) >> 8, 4), imm8)
                            self._test_values = (1, 0xffff)
                        elif armins & 0xFA008000 == 0xF0000000:
                            # Data processing, modified 12 bit imm, aka EVIL
                            # page 53
                            # wow. just. wow.
                            imm12 = armins & 0xFF
                            imm12 |= (armins & 0x7000) >> 4
                            imm12 |= (armins & 0x04000000) >> 15
                            # decoding algorithm from page 93
                            if imm12 & 0xC00 == 0:
                                if imm12 & 0x300 == 0:
                                    thoughtval = imm12
                                elif imm12 & 0x300 == 0x100:
                                    thoughtval = imm12 & 0xFF
                                    thoughtval |= thoughtval << 16
                                elif imm12 & 0x300 == 0x200:
                                    thoughtval = (imm12 & 0xFF) << 8
                                    thoughtval |= thoughtval << 16
                                elif imm12 & 0x300 == 0x300:
                                    thoughtval = imm12 & 0xFF
                                    thoughtval |= thoughtval << 8
                                    thoughtval |= thoughtval << 16
                            else:
                                thoughtval = ror(0x80 | (imm12 & 0x7F),
                                                 imm12 >> 7, 32)
                            if thoughtval != self.value:
                                raise ValueNotFoundError
                            imm12 = self._imm(12)
                            ITE = claripy.If
                            CAT = claripy.Concat
                            ROR = claripy.RotateRight
                            imm8 = imm12[7:0]
                            imm7 = imm12[6:0]
                            imm3 = imm12[10:8]
                            imm1 = imm12[11]
                            zero = BVV(0, 8)
                            bit = BVV(1, 1)
                            monster = ITE(
                                imm12[11:10] == 0,
                                ITE(
                                    imm12[9] == 0,
                                    ITE(imm12[8] == 0,
                                        imm12[7:0].zero_extend(32 - 8),
                                        CAT(zero, imm8, zero, imm8)),
                                    ITE(imm12[8] == 0,
                                        CAT(imm8, zero, imm8, zero),
                                        CAT(imm8, imm8, imm8, imm8))),
                                ROR(
                                    CAT(bit, imm7).zero_extend(32 - 8),
                                    imm12[11:7].zero_extend(32 - 5)))
                            self.patch_value_expression = monster
                            self.patch_bytes_expression = claripy.Concat(
                                BVV(armins >> 27, 5), imm1,
                                BVV((armins & 0x03FF8000) >> 15, 11), imm3,
                                BVV((armins & 0xF00) >> 8, 4), imm8)
                            self._test_values = (0xff00ff00, 0x00ff00ff,
                                                 0xffffffff, 0xff, 0xff000000)
                        else:
                            raise ValueNotFoundError
                    else:
                        raise FidgetUnsupportedError(
                            "You found a THUMB instruction longer than 32 bits??"
                        )

            else:
                self.bit_length = 64
                # aarch64 instructions
                # can't find a reference doc?????? I'm pulling these from VEX, guest_arm64_toIR.c
                if armins & 0x7f800000 in (0x28800000, 0x29800000, 0x29000000):
                    # LDP/SDP
                    # line 4791
                    # 7 bit immediate signed offset, scaled by load size (from MSB)
                    shift = 3 if armins & 0x80000000 else 2
                    simm7 = (armins & 0x3f8000) >> 15
                    simm7 = resign_int(simm7, 7)
                    simm7 <<= shift
                    if simm7 != self.value:
                        raise ValueNotFoundError
                    imm7 = self._imm(7)
                    self.patch_value_expression = imm7.sign_extend(self.bits -
                                                                   7) << shift
                    self.patch_bytes_expression = claripy.Concat(
                        BVV((armins & 0xffc00000) >> 22, 10), imm7,
                        BVV(armins & 0x7fff, 15))
                    self._test_values = (-0x40 << shift, 0x3f << shift)
                elif (armins & 0x3f800000 == 0x39000000) or \
                     (armins & 0x3f800000 == 0x39800000 and \
                          ((armins >> 30) | ((armins >> 22) & 1)) in (4, 2, 3, 0, 1)):
                    # LDR/STR, LDRS
                    # line 4639, 5008
                    # 12 bit immediate unsigned offset, scaled by load size (from 2 MSB)
                    shift = (armins & 0xc0000000) >> 30
                    offs = (armins & 0x3ffc00) >> 10
                    offs <<= shift
                    if offs != self.value:
                        raise ValueNotFoundError
                    imm12 = self._imm(12)
                    self.patch_value_expression = imm12.zero_extend(
                        self.bits - 12) << shift
                    self.patch_bytes_expression = claripy.Concat(
                        BVV((armins & 0xffc00000) >> 22, 10), imm12,
                        BVV(armins & 0x3ff, 10))
                    self._test_values = (1 << shift, 0xfff << shift)
                elif armins & 0x1f000000 == 0x11000000:
                    # ADD/SUB imm
                    # line 2403
                    # 12 bit shifted unsigned immediate
                    if not armins & 0x80000000:
                        self.bit_length = 32
                    shift = (armins >> 22) & 3
                    imm12 = (armins >> 10) & 0xfff
                    imm12 <<= 12 * shift
                    if imm12 != self.value:
                        raise ValueNotFoundError
                    shift = self._imm(1, 'shift')
                    imm12 = self._imm(12)
                    shift_full = shift.zero_extend(self.bits - 1) * 12
                    self.patch_value_expression = imm12.zero_extend(
                        self.bits - 12) << shift_full
                    self.patch_bytes_expression = claripy.Concat(
                        BVV(armins >> 24, 8), BVV(0, 1), shift, imm12,
                        BVV(armins & 0x3ff, 10))
                    self._test_values = (1, 0xfff, 0xfff000)
                elif armins & 0x3fa00000 == 0x38000000:
                    # LDUR/STUR
                    # Line 4680
                    # 9 bit signed immediate offset
                    imm9 = (armins >> 12) & 0x1ff
                    imm9 = resign_int(imm9, 9)
                    if imm9 != self.value:
                        raise ValueNotFoundError
                    imm9 = self._imm(9)
                    self.patch_value_expression = imm9.sign_extend(self.bits -
                                                                   9)
                    self.patch_bytes_expression = claripy.Concat(
                        BVV(armins >> 21, 11), imm9, BVV(armins & 0xfff, 12))
                    self._test_values = (-0x100, 0xff)

                else:
                    raise ValueNotFoundError

            if not self.sanity_check():
                raise ValueNotFoundError
        else:
            insn = self._string_to_insn(self._insbytes)
            insn = BVV(insn, self._inslen * 8)
            for word_size in (64, 32, 16, 8):
                if word_size > self.bits:
                    continue
                for bit_offset in xrange(0, insn.length - word_size + 1, 8):
                    result = insn[bit_offset + word_size - 1:bit_offset]
                    result = result.sign_extend(self.bits - word_size)
                    if claripy.is_true(result == self.value):
                        imm = self._imm(word_size)
                        self.patch_value_expression = imm.sign_extend(
                            self.bits - word_size)
                        if bit_offset + word_size >= insn.length:
                            acc = imm
                        else:
                            acc = claripy.Concat(
                                insn[insn.length - 1:bit_offset + word_size],
                                imm)
                        if bit_offset != 0:
                            acc = claripy.Concat(acc, insn[bit_offset - 1:0])

                        if self._project.arch.memory_endness == 'Iend_LE':
                            self.patch_bytes_offset = bit_offset / 8
                        else:
                            self.patch_bytes_offset = self._inslen - (
                                bit_offset + word_size) / 8

                        self.patch_bytes_size = word_size / 8
                        self.patch_bytes_expression = acc
                        self._test_values = (-(1 << word_size) >> 1,
                                             ((1 << word_size) >> 1) - 1)

                        if self.sanity_check():
                            break  # found

                    if self._project.arch.name == 'PPC64':
                        # On PPC64, the lowest two bits of immediate values can be used for other things
                        # Mask those out
                        result = (result & ~3).sign_extend(self.bits -
                                                           word_size)
                        if not claripy.is_true(result == self.value):
                            continue
                        imm = self._imm(word_size - 2)
                        self.patch_value_expression = claripy.Concat(
                            imm, BVV(0, 2)).sign_extend(self.bits - word_size)
                        if bit_offset + word_size >= insn.length:
                            acc = imm
                        else:
                            acc = claripy.Concat(
                                insn[insn.length - 1:bit_offset + word_size],
                                imm)
                        acc = claripy.Concat(acc, insn[bit_offset + 1:0])

                        if self._project.arch.memory_endness == 'Iend_LE':
                            self.patch_bytes_offset = bit_offset / 8
                        else:
                            self.patch_bytes_offset = self._inslen - (
                                bit_offset + word_size) / 8

                        self.patch_bytes_size = word_size / 8
                        self.patch_bytes_expression = acc
                        self._test_values = (-(1 << word_size) >> 1,
                                             ((1 << word_size) >> 1) - 4)
                        if self.sanity_check():
                            break  # found
                else:
                    # inner loop did not break: not found
                    continue
                # inner loop broke: found
                break
            else:
                # outer loop did not break: inner loop did not break: not found
                raise ValueNotFoundError
            # outer loop broke: inner loop broke: found
            return
Beispiel #51
0
    def convert_claripy_bool_ast_core(self, cond, memo):
        if isinstance(cond, ailment.Expr.Expression):
            return cond

        if cond.op == "BoolS" and claripy.is_true(cond):
            return cond
        if cond.args[0] in self._condition_mapping:
            return self._condition_mapping[cond.args[0]]

        def _binary_op_reduce(op, args, annotations: Iterable[claripy.Annotation], signed=False):
            r = None
            for arg in args:
                if r is None:
                    r = self.convert_claripy_bool_ast(arg, memo=memo)
                else:
                    try:
                        tag_annotation = next(iter(anno for anno in annotations if isinstance(anno, TagsAnnotation)))
                        tags = tag_annotation.tags
                    except StopIteration:
                        tags = {}
                    r = ailment.Expr.BinaryOp(None, op, (r, self.convert_claripy_bool_ast(arg, memo=memo)), signed,
                                              **tags
                                              )
            return r

        def _unary_op_reduce(op, arg, annotations: Iterable[claripy.Annotation]):
            r = self.convert_claripy_bool_ast(arg, memo=memo)
            try:
                tag_annotation = next(iter(anno for anno in annotations if isinstance(anno, TagsAnnotation)))
                tags = tag_annotation.tags
            except StopIteration:
                tags = {}
            return ailment.Expr.UnaryOp(None, op, r, **tags)

        _mapping = {
            'Not': lambda cond_: _unary_op_reduce('Not', cond_.args[0], cond_.annotations),
            'And': lambda cond_: _binary_op_reduce('LogicalAnd', cond_.args, cond_.annotations),
            'Or': lambda cond_: _binary_op_reduce('LogicalOr', cond_.args, cond_.annotations),
            '__le__': lambda cond_: _binary_op_reduce('CmpLE', cond_.args, cond_.annotations, signed=True),
            'SLE': lambda cond_: _binary_op_reduce('CmpLE', cond_.args, cond_.annotations, signed=True),
            '__lt__': lambda cond_: _binary_op_reduce('CmpLT', cond_.args, cond_.annotations, signed=True),
            'SLT': lambda cond_: _binary_op_reduce('CmpLT', cond_.args, cond_.annotations, signed=True),
            'UGT': lambda cond_: _binary_op_reduce('CmpGT', cond_.args, cond_.annotations),
            'UGE': lambda cond_: _binary_op_reduce('CmpGE', cond_.args, cond_.annotations),
            '__gt__': lambda cond_: _binary_op_reduce('CmpGT', cond_.args, cond_.annotations, signed=True),
            '__ge__': lambda cond_: _binary_op_reduce('CmpGE', cond_.args, cond_.annotations, signed=True),
            'SGT': lambda cond_: _binary_op_reduce('CmpGT', cond_.args, cond_.annotations, signed=True),
            'SGE': lambda cond_: _binary_op_reduce('CmpGE', cond_.args, cond_.annotations, signed=True),
            'ULT': lambda cond_: _binary_op_reduce('CmpLT', cond_.args, cond_.annotations),
            'ULE': lambda cond_: _binary_op_reduce('CmpLE', cond_.args, cond_.annotations),
            '__eq__': lambda cond_: _binary_op_reduce('CmpEQ', cond_.args, cond_.annotations),
            '__ne__': lambda cond_: _binary_op_reduce('CmpNE', cond_.args, cond_.annotations),
            '__add__': lambda cond_: _binary_op_reduce('Add', cond_.args, cond_.annotations, signed=False),
            '__sub__': lambda cond_: _binary_op_reduce('Sub', cond_.args, cond_.annotations),
            '__mul__': lambda cond_: _binary_op_reduce('Mul', cond_.args, cond_.annotations),
            '__xor__': lambda cond_: _binary_op_reduce('Xor', cond_.args, cond_.annotations),
            '__or__': lambda cond_: _binary_op_reduce('Or', cond_.args, cond_.annotations, signed=False),
            '__and__': lambda cond_: _binary_op_reduce('And', cond_.args, cond_.annotations),
            '__lshift__': lambda cond_: _binary_op_reduce('Shl', cond_.args, cond_.annotations),
            '__rshift__': lambda cond_: _binary_op_reduce('Sar', cond_.args, cond_.annotations),
            'LShR': lambda cond_: _binary_op_reduce('Shr', cond_.args, cond_.annotations),
            'BVV': lambda cond_: ailment.Expr.Const(None, None, cond_.args[0], cond_.size()),
            'BoolV': lambda cond_: ailment.Expr.Const(None, None, True, 1) if cond_.args[0] is True
                                                                        else ailment.Expr.Const(None, None, False, 1),
            'Extract': lambda cond_: self._convert_extract(*cond_.args, cond_.annotations, memo=memo),
        }

        if cond.op in _mapping:
            return _mapping[cond.op](cond)
        raise NotImplementedError(("Condition variable %s has an unsupported operator %s. "
                                   "Consider implementing.") % (cond, cond.op))
Beispiel #52
0
def test_rcr():
    p = angr.Project(os.path.join(os.path.dirname(__file__), '..', '..',
                                  'binaries', 'tests', 'i386', 'rcr_test'),
                     auto_load_libs=False)
    result = p.factory.successors(p.factory.entry_state()).successors[0]
    assert claripy.is_true(result.regs.cl == 8)