示例#1
0
文件: javavm.py 项目: shingarov/angr
 def _get_default_concrete_value_by_type(type_, state=None):  # pylint: disable=unused-argument
     if type_ in ['byte', 'char', 'short', 'int', 'boolean']:
         return BVV(0, 32)
     elif type_ == "long":
         return BVV(0, 64)
     elif type_ == 'float':
         return FPV(0, FSORT_FLOAT)
     elif type_ == 'double':
         return FPV(0, FSORT_DOUBLE)
     # not a primitive type
     # => treat it as a reference
     return SootNullConstant()
示例#2
0
文件: __init__.py 项目: yuzeming/angr
    def _store_string_in_native_memory(self, string, addr=None):
        """
        Store given string UTF-8 encoded and zero terminated in native memory.

        :param str string:  String
        :param addr:        Native store address.
                            If not set, native memory is allocated.
        :return:            Native address of the string.
        """
        if addr is None:
            addr = self._allocate_native_memory(size=len(string)+1)
        else:
            # check if addr is symbolic
            if self.state.solver.symbolic(addr):
                l.error("Storing strings at symbolic addresses is not implemented. "
                        "Continue execution with concretized address.")
            addr = self.state.solver.eval(addr)

        # warn if string is symbolic
        if self.state.solver.symbolic(string):
            l.warning('Support for symbolic strings, passed to native code, is limited. '
                      'String will get concretized after `ReleaseStringUTFChars` is called.')

        # store chars one by one
        str_len = len(string) // 8
        for idx in range(str_len):
            str_byte = StrSubstr(idx, 1, string)
            self.state.memory.store(addr+idx, str_byte)

        # store terminating zero
        self.state.memory.store(len(string), BVV(0, 8))

        return addr
示例#3
0
    def run(self, f_p):
        self.argument_types = {0: SimTypeFd()}
        self.return_type = SimTypeInt(32, True)

        fileno = angr.SIM_PROCEDURES['posix']['fileno']
        fd = self.inline_call(fileno, f_p).ret_expr

        # let's get the memory back for the file we're interested in and find
        # the newline
        fp = self.state.posix.get_file(fd)
        pos = fp.pos

        max_str_len = self.state.libc.max_str_len

        # if there exists a limit on the file size, let's respect that, the
        # limit cannot be symbolic
        limit = max_str_len if fp.size is None else self.state.se.max_int(
            fp.size - pos)

        # limit will always be concrete, if it's zero we EOF'd
        if limit != 0:
            data = fp.read_from(1)
            data = data.zero_extend(32 - data.size())
        else:
            data = -1  #EOF
            data = BVV(data, 32)
        return data
示例#4
0
    def _get_role(self, no, key_addr, reg_name, key_name=None):
        """
        Retrieve the role of a binary by inferring whether it is a setter or a getter

        :param no: node containing the call to a set or getter function
        :param key_addr: address of the keyword used to infer the role
        :param reg_name: register containing the key_addr
        :return: The role and the function used to infer it whether the role could be inferred, None and None otherwise
        """

        p = self._current_p

        if not BinaryDependencyGraph.is_call(p.factory.block(no.addr)):
            return None

        # detect the role
        self._cpf_used = None
        f_addr = no.addr
        self._candidate_role_function = no.successors[0].addr

        # prepare the under-contrainted-based initial state
        # we do not allow untaint as we just want to see where the key data key is leading to
        self._core_taint = CoreTaint(p, interfunction_level=2, smart_call=False,
                                     follow_unsat=True,
                                     try_thumb=True,
                                     exit_on_decode_error=True, force_paths=True, allow_untaint=False,
                                     logger_obj=log)

        # the used register is not a parameter register
        if are_parameters_in_registers(p) and reg_name not in arg_reg_names(p):
            return Role.UNKNOWN

        self._current_par_name = reg_name
        self._current_key_addr = key_addr
        self._current_f_addr = f_addr

        s = get_initial_state(p, self._core_taint, f_addr)
        s = self._apply_taint(s, key_addr, key_name)
        # enter into the call
        sim = p.factory.simgr(s)
        sim.step()
        s = sim.active[0]
        if reg_name:
            setattr(s.regs, reg_name, BVV(key_addr, p.arch.bits))

        summarized_f = prepare_function_summaries(p)
        self._f_arg_vals = []
        self._set_f_vals = True

        self._core_taint.set_alarm(TIMEOUT_TAINT, n_tries=TIMEOUT_TRIES)
        try:
            self._core_taint.run(s, (), (), summarized_f=summarized_f, force_thumb=False,
                                 check_func=self._check_key_usage, init_bss=False)
        except TimeOutException:
            log.warning("Timeout Triggered")
        except Exception as e:
            log.warning(f"Exception in Coretaint: {str(e)}")

        self._core_taint.unset_alarm()
        return self._current_role
示例#5
0
    def _inet_pton(self, ct, caller_path, plt_path):
        """
        inet_pton summary
        :param ct: core taint engine
        :param caller_path: angr path leading to the inet_path
        :param plt_path:  angr path leading to the plt entry of inet_pton
        :return:
        """
        p = ct.p
        new_state = plt_path.active[0]

        # move data key from argument to destination addr
        addr_str = getattr(plt_path.active[0].regs, arg_reg_name(p, 1))
        cnt_str = get_string(p, addr_str.args[0], extended=True)

        # do the inet_pton conversion.
        # this is not exactly the conversion the inet_pton does, it's a trick we use to keep track of the addresses
        inet_pton_convesions[self._pton_counter] = cnt_str
        bits = p.arch.bits
        to_store = BVV(self._pton_counter, bits)
        self._pton_counter += 1

        # store it!
        dst_mem = getattr(plt_path.active[0].regs, arg_reg_name(p, 2))
        new_state.memory.store(dst_mem, to_store)

        # instead of a link register, we hook an unconstrained sim procedure
        self._p.hook(plt_path.addr, ReturnUnconstrained())
        caller_path.step().step()
示例#6
0
文件: javavm.py 项目: twizmwazin/angr
    def get_default_value_by_type(type_, state=None):
        """
        Java specify defaults values for primitive and reference types. This
        method returns the default value for a given type.

        :param str type_:   Name of type.
        :return:            Default value for this type.
        """
        if type_ in ['byte', 'char', 'short', 'int', 'boolean']:
            return BVS('default_value_{}'.format(type_), 32)
        elif type_ == "long":
            return BVS('default_value_{}'.format(type_), 64)
        elif type_ == 'float':
            return FPS('default_value_{}'.format(type_), FSORT_FLOAT)
        elif type_ == 'double':
            return FPS('default_value_{}'.format(type_), FSORT_DOUBLE)
        elif state is not None:
            if type_ == 'java.lang.String':
                return SimSootValue_StringRef.new_string(state, StringS('default_value_{}'.format(type_), 1000))
            if type_.endswith('[][]'):
                raise NotImplementedError
                # multiarray = SimSootExpr_NewMultiArray.new_array(self.state, element_type, size)
                # multiarray.add_default_value_generator(lambda s: SimSootExpr_NewMultiArray._generate_inner_array(s, element_type, sizes))
                # return  multiarray
            elif type_.endswith('[]'):
                array = SimSootExpr_NewArray.new_array(state, type_[:-2], BVV(2, 32))
                return array
            else:
                return SimSootValue_ThisRef.new_object(state, type_, symbolic=True, init_object=False)
        else:
            # not a primitive type
            # => treat it as a reference
            return SootNullConstant()
示例#7
0
文件: javavm.py 项目: shingarov/angr
 def _get_default_symbolic_value_by_type(type_, state):
     if type_ in ['byte', 'char', 'short', 'int', 'boolean']:
         return BVS('default_value_{}'.format(type_), 32)
     if type_ == "long":
         return BVS('default_value_{}'.format(type_), 64)
     if type_ == 'float':
         return FPS('default_value_{}'.format(type_), FSORT_FLOAT)
     if type_ == 'double':
         return FPS('default_value_{}'.format(type_), FSORT_DOUBLE)
     if type_ == 'java.lang.String':
         return SimSootValue_StringRef.new_string(
             state, StringS('default_value_{}'.format(type_), 1000))
     if type_.endswith('[][]'):
         raise NotImplementedError
         # multiarray = SimSootExpr_NewMultiArray.new_array(self.state, element_type, size)
         # multiarray.add_default_value_generator(lambda s: SimSootExpr_NewMultiArray._generate_inner_array(s, element_type, sizes))
         # return  multiarray
     if type_.endswith('[]'):
         array = SimSootExpr_NewArray.new_array(state, type_[:-2],
                                                BVV(2, 32))
         return array
     return SimSootValue_ThisRef.new_object(state,
                                            type_,
                                            symbolic=True,
                                            init_object=False)
示例#8
0
    def run(self, fd):
        self.argument_types = {0: SimTypeFd()}
        self.return_type = SimTypeInt(32, True)

        # let's get the memory back for the file we're interested in and find
        # the newline
        # fd should be a FILE* but for now It is a int file descriptor
        fp = self.state.posix.get_file(fd)
        pos = fp.pos

        max_str_len = self.state.libc.max_str_len

        # if there exists a limit on the file size, let's respect that, the
        # limit cannot be symbolic
        limit = max_str_len if fp.size is None else self.state.se.max_int(
            fp.size - pos)

        # limit will always be concrete, if it's zero we EOF'd
        if limit != 0:
            data = fp.read_from(1)
            data = data.zero_extend(32 - data.size())
        else:
            data = -1  #EOF
            data = BVV(data, 32)
        return data
示例#9
0
 def _read_memory(self, offset, bytes_read, state, start, end):
     # MemoryForwardMsg = RemoteMemoryReadMessage(self.origin, self.id,
     #                                            0x0, # Fake PC
     #                                            start,
     #                                            end - start)
     # self.avatar.queue.put(MemoryForwardMsg)
     #
     # r_id, r_value, r_success = self.origin.response_queue.get()
     #
     # if self.id != r_id:
     #     raise("AvatarAngrMemory received mismatching id!")
     # if r_success != True:
     #     raise Exception("AvatarAngrMemory remote memory request failed!")
     #
     # self.id += 1
     #
     # int.from_bytes(bytes_read[start, start + end], byteorder='big')
     r_value = struct.unpack("<L", bytes_read[start-offset:end-offset])[0]
     # do your stuff
     return [(start, SimMemoryObject(BVV(r_value, (end-start)*8), start))]
示例#10
0
 def _apply_taint(self, state, key_addr, keyword=None):
     """
     Apply the taint to the datakey
     :param state: the current initial state
     :param key_addr: the address of the datakey
     :param keyword: the keyword to taint (if we want to constraint the datakey)
     :return: the new state
     """
     # taint the data key
     if self._discover_data_keys:
         size = len(self._current_data_key)
     else:
         size = self._core_taint.taint_buf_size
     t = self._core_taint.get_sym_val(name=self._core_taint.taint_buf, bits=(size * 8)).reversed
     if keyword:
         # reverse to make it LE
         bvv = BVV(keyword).reversed
         state.add_constraints(t == bvv)
     # we taint the used keyword to trace its use
     state.memory.store(key_addr, t)
     return state
示例#11
0
    def run(self, f_p):

        #additional code
        trace_data = ("_IO_getc", {"f_p": (f_p, f_p.symbolic)})
        try:
            self.state.procedure_data.global_variables["trace"].append(
                trace_data)
        except KeyError:
            self.state.procedure_data.global_variables["trace"] = []
            self.state.procedure_data.global_variables["trace"].append(
                trace_data)
        #end of additional code

        self.argument_types = {0: SimTypeFd()}
        self.return_type = SimTypeInt(32, True)

        fileno = simuvex.SimProcedures['libc.so.6']['fileno']
        fd = self.inline_call(fileno, f_p).ret_expr

        # let's get the memory back for the file we're interested in and find
        # the newline
        fp = self.state.posix.get_file(fd)
        pos = fp.pos

        max_str_len = self.state.libc.max_str_len

        # if there exists a limit on the file size, let's respect that, the
        # limit cannot be symbolic
        limit = max_str_len if fp.size is None else self.state.se.max_int(
            fp.size - pos)

        # limit will always be concrete, if it's zero we EOF'd
        if limit != 0:
            data = fp.read_from(1)
            data = data.zero_extend(32 - data.size())
        else:
            data = -1  #EOF
            data = BVV(data, 32)
        return data
示例#12
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
示例#13
0
文件: javavm.py 项目: twizmwazin/angr
    def state_blank(self, addr=None, **kwargs): # pylint: disable=arguments-differ

        if not kwargs.get('mode', None): kwargs['mode'] = self.project._default_analysis_mode
        if not kwargs.get('arch', None):  kwargs['arch'] = self.arch
        if not kwargs.get('os_name', None): kwargs['os_name'] = self.name
        # enable support for string analysis
        if not kwargs.get('add_options', None): kwargs['add_options'] = []
        kwargs['add_options'] += [options.STRINGS_ANALYSIS, options.COMPOSITE_SOLVER]

        if self.is_javavm_with_jni_support:
            # If the JNI support is enabled (i.e. JNI libs are loaded), the SimState
            # needs to support both the Vex and the Soot engine. Therefore we start with
            # an initialized native state and extend this with the Soot initializations.
            # Note: Setting `addr` to a `native address` (i.e. not an SootAddressDescriptor).
            #       makes sure that the SimState is not in "Soot-mode".
            # TODO: use state_blank function from the native simos and not the super class
            state = super(SimJavaVM, self).state_blank(addr=0, **kwargs)
            native_addr_size = self.native_simos.arch.bits
            # Let the JNIEnv pointer point to the function table
            state.memory.store(addr=self.jni_env,
                               data=BVV(self.jni_function_table, native_addr_size),
                               endness=self.native_arch.memory_endness)
            # Initialize the function table
            # => Each entry usually contains the address of the function, but since we hook all functions
            #    with SimProcedures, we store the address of the corresponding hook instead.
            #    This, by construction, is exactly the address of the function table entry itself.
            for idx in range(len(jni_functions)):
                jni_function_addr = self.jni_function_table + idx * native_addr_size//8
                state.memory.store(addr=jni_function_addr,
                                   data=BVV(jni_function_addr, native_addr_size),
                                   endness=self.native_arch.memory_endness)

        else:
            # w/o JNI support, we can just use a blank state
            state = SimState(project=self.project, **kwargs)

        if not self.project.entry and not addr:
            raise ValueError("Failed to init blank state. Project entry is not set/invalid"
                             "and no address was provided.")

        # init state register
        state.regs._ip = addr if addr else self.project.entry
        state.regs._ip_binary = self.project.loader.main_object
        state.regs._invoke_return_target = None
        state.regs._invoke_return_variable = None

        # add empty stack frame
        state.memory.push_stack_frame()

        # create bottom of callstack
        new_frame = state.callstack.copy()
        new_frame.ret_addr = SootAddressTerminator()
        state.callstack.push(new_frame)

        # initialize class containing the current method
        state.javavm_classloader.get_class(state.addr.method.class_name,
                                           init_class=True, step_func=kwargs.get('step_function', None))

        # initialize the Java environment
        # TODO move this to `state_full_init?
        self.init_static_field(state, "java.lang.System", "in", "java.io.InputStream")
        self.init_static_field(state, "java.lang.System", "out", "java.io.PrintStream")

        return state
示例#14
0
def avatar_state(angr_factory, angr_target, options=frozenset(),
                 add_options=None, remove_options=None,
                 memory_backer=None, plugins=None,
                 load_register_from=None, ram_file = None, **kwargs):
    '''
    This method sets up a SimState which is usable for avatar and will be
    registered to the project's factory.
    Currently, setting up an avatar-state consists of four phases:
        1) verifying that the state options dont include unsupported memory
           options. (AvatarStates only work on SimSymbolicMemory for now)
        2) Setting up the memory plugin of the state
        3) Creating the avatar plugin for the state
        4) Creating the actual state
    '''

    def generate_permissions_backer():
        return None

    l = logging.getLogger('angr.factory')

    options = set(options)
    unsupported_options = set([o.ABSTRACT_MEMORY, o.FAST_MEMORY])

    if options & unsupported_options:
        l.warning('Discarding user-defined memory options for avatar state')
        remove_options |= (options & unsupported_options)

    if add_options is not None:
        options |= add_options
    if remove_options is not None:
        options -= remove_options


    permissions_backer = angr_factory.project.loader.memory

    if memory_backer is None:
        memory_backer = angr_factory.project.loader.memory

    permissions_backer = generate_permissions_backer()
    page_size = angr_factory.project.loader.page_size

    #SimPagedMemory requires both pages and symbolic_addresses to be dicts
    #with the same keys
    pages = {}
    symbolic_addrs = {}

    def get_effective_ram_file(start, size, ram_files):
        # old interface
        if isinstance(ram_files, dict):
            return ram_files
        # new interface
        else:
            for f in ram_files:
                if f['start'] <= start < f['start'] + f['size']:
                    return f
        # cannot find a ram file
        assert False


    for (start, end, mr) in angr_factory.origin.avatar.memory_ranges:
        if not start % page_size == 0:
            l.debug("Memory ranges starts at addres %x which is not page aligned (page size: %x)" % (start, page_size))
        if not end % page_size == 0:
            l.debug("Memory ranges ends at addres %x which is not page aligned (page size: %x)" % (end, page_size))
        # if mr.forwarded:
        if 'ram' in mr.name:
            page_num = start // page_size
            while page_num * page_size < end:
                effective_ram_file = get_effective_ram_file(page_num * page_size, page_size, ram_file)
                pages[page_num] = AvatarPage(page_num * page_size,
                                                    page_size,
                                                    origin=angr_factory.origin, ram_file = effective_ram_file)
                symbolic_addrs[page_num] = set()
                page_num += 1
    memory_storage = SimPagedMemory(page_size=page_size, pages=pages,
                                    symbolic_addrs=symbolic_addrs,
                                    check_permissions=True,
                                    memory_backer=memory_backer,
                                    permissions_backer=permissions_backer)


    sim_memory = SimSymbolicMemory(mem=memory_storage, memory_id='mem',
                                   check_permissions=True)

    if plugins is None:
        plugins = {}

    if 'memory' in plugins:
    # if plugins.has_key('memory'):
        l.warning('Discarding user-defined memory plugin for avatar state')
    plugins['memory'] = sim_memory

    avatar_state = angr_factory.blank_state(remove_options=remove_options,
                                           add_options={o.EFFICIENT_STATE_MERGING,},
                                           memory_backer=memory_backer,
                                           plugins=plugins, **kwargs)

    # avatar_state = angr_factory.blank_state(addr=0x1001, remove_options=remove_options)
    # avatar_state = angr_factory.blank_state(options=options,
    #                                         add_options=add_options,
    #                                         remove_options=remove_options,
    #                                         memory_backer=memory_backer,
    #                                         plugins=plugins, **kwargs)

    # avatar_state.globals['memcnt'] = 0

    if load_register_from is not None:
        for reg in angr_target.avatar.arch.registers.keys():
            try:
                value = BVV(load_register_from[reg],
                            avatar_state.arch.bits)
                # if reg == 'cpsr':
                #     print 'doing cpsr'
                avatar_state.registers.store(reg, value)
            except KeyError as e:
                l.warning("Register %s was not set." % str(e))
        avatar_state.scratch.ins_addr = avatar_state.regs.ip
        avatar_state.scratch.bbl_addr = avatar_state.regs.ip
        avatar_state.scratch.stmt_idx = 0

    avatar_state.history.jumpkind = 'Ijk_Boring'
    return avatar_state