Example #1
0
def is_mapped(ea, size=1, value=True):
    """Check if the given address is mapped.

    Specify a size greater than 1 to check if an address range is mapped.

    Arguments:
        ea: The linear address to check.

    Options:
        size: The number of bytes at ea to check. Default is 1.
        value: Only consider an address mapped if it has a value. For example, the contents of a
            bss section exist but don't have a static value. If value is False, consider such
            addresses as mapped. Default is True.

    Notes:
        This function is currently a hack: It only checks the first and last byte.
    """
    if size < 1:
        raise ValueError('Invalid argument: size={}'.format(size))
    # HACK: We only check the first and last byte, not all the bytes in between.
    if value:
        return idc.isLoaded(ea) and (size == 1 or idc.isLoaded(ea + size - 1))
    else:
        return idaapi.getseg(ea) and (size == 1
                                      or idaapi.getseg(ea + size - 1))
Example #2
0
    def factory(cls, string_location, string_reference, size=INVALID, offset=INVALID, key=INVALID):
        """
        Factory function to generate an EncodedString or EncodedStackString based on type.

        :param string_location:
            Data segment pointer for static strings or stack pointer for stack strings.
        :param string_reference:
            The location the string is referenced from.
            This is required to pull the stack frame when string_location is a stack pointer.
        :param size: The size of the string. Required to use self.get_bytes.
        :param offset: Used when there is an offset based accessing scheme.
        :param key: Used when there is a key that can vary by string.
        """
        if idc.isLoaded(string_location):
            return EncodedString(
                string_location, string_reference, size=size, offset=offset, key=key)

        # otherwise assume string_location is a pointer within the stack
        # (using function_tracingutils's CPU emulator) and create an EncodedStackString object.
        stack = idc.GetFrame(string_reference)
        # FIXME: This method isn't always super accurate because... IDA
        stack_offset = (
                string_location
                + function_tracingutils.RSP_OFFSET
                + idc.GetFrameLvarSize(string_reference)
                - function_tracingutils.STACK_BASE
        )

        return EncodedStackString(
            stack, stack_offset, string_reference=string_reference,
            size=size, offset=offset, key=key)
Example #3
0
def read_enc_value(ea, enc):
    """ Read encoded value
  """
    if enc == DW_EH_PE_omit:
        DEBUG("Error in read_enc_val {0:x}".format(ea))
        return idc.BADADDR, idc.BADADDR

    start = ea
    fmt, mod = enc & 0x0F, enc & 0x70

    if fmt == DW_EH_PE_ptr:
        val = read_pointer(ea)
        ea += get_address_size_in_bytes()

    elif fmt in [DW_EH_PE_uleb128, DW_EH_PE_sleb128]:
        val, ea = read_leb128(ea, fmt == DW_EH_PE_sleb128)
        if ea - start > 1:
            make_array(start, ea - start)

    elif fmt in [DW_EH_PE_sdata2, DW_EH_PE_udata2]:
        val = read_word(ea)
        ea += 2
        if fmt == DW_EH_PE_sdata2:
            val = sign_extn(val, 16)

    elif fmt in [DW_EH_PE_sdata4, DW_EH_PE_udata4]:
        val = read_dword(ea)
        ea += 4
        if fmt == DW_EH_PE_sdata4:
            val = sign_extn(val, 32)

    elif fmt in [DW_EH_PE_sdata8, DW_EH_PE_udata8]:
        val = read_qword(ea)
        ea += 8
        if f == DW_EH_PE_sdata8:
            val = sign_extn(val, 64)

    else:
        DEBUG("{0:x}: don't know how to handle {1:x}".format(start, enc))
        return idc.BADADDR, idc.BADADDR

    if mod == DW_EH_PE_pcrel:
        if val != 0:
            val += start
            val &= (1 << (get_address_size_in_bits())) - 1

    elif mod != DW_EH_PE_absptr:
        DEBUG("{0:x}: don't know how to handle {1:x}".format(start, enc))
        return BADADDR, BADADDR

    if (enc & DW_EH_PE_indirect) and val != 0:
        if not idc.isLoaded(val):
            DEBUG("{0:x}: dereference invalid pointer {1:x}".format(
                start, val))
            return idc.BADADDR, idc.BADADDR
        val = read_pointer(val)

    return val, ea
Example #4
0
def read_enc_value(ea, enc):
  """ Read encoded value
  """
  if enc == DW_EH_PE_omit:
    DEBUG("Error in read_enc_val {0:x}".format(ea))
    return idc.BADADDR, idc.BADADDR

  start = ea
  fmt, mod = enc&0x0F, enc&0x70
  
  if fmt == DW_EH_PE_ptr:
    val = read_pointer(ea)
    ea += get_address_size_in_bytes()
      
  elif fmt in [DW_EH_PE_uleb128, DW_EH_PE_sleb128]:
    val, ea = read_leb128(ea, fmt == DW_EH_PE_sleb128)
    if ea - start > 1:
      make_array(start, ea - start)

  elif fmt in [DW_EH_PE_sdata2, DW_EH_PE_udata2]:
    val = read_word(ea)
    ea += 2
    if fmt == DW_EH_PE_sdata2:
      val = sign_extn(val, 16)
      
  elif fmt in [DW_EH_PE_sdata4, DW_EH_PE_udata4]:
    val = read_dword(ea)
    ea += 4
    if fmt == DW_EH_PE_sdata4:
      val = sign_extn(val, 32)
      
  elif fmt in [DW_EH_PE_sdata8, DW_EH_PE_udata8]:
    val = read_qword(ea)
    ea += 8
    if f == DW_EH_PE_sdata8:
      val = sign_extn(val, 64)
      
  else:
    DEBUG("{0:x}: don't know how to handle {1:x}".format(start, enc))
    return idc.BADADDR, idc.BADADDR

  if mod == DW_EH_PE_pcrel:   
    if val != 0:
      val += start
      val &= (1<<(get_address_size_in_bits())) - 1
  
  elif mod != DW_EH_PE_absptr:
    DEBUG("{0:x}: don't know how to handle {1:x}".format(start, enc))
    return BADADDR, BADADDR

  if (enc & DW_EH_PE_indirect) and val != 0:
    if not idc.isLoaded(val):
      DEBUG("{0:x}: dereference invalid pointer {1:x}".format(start, val))
      return idc.BADADDR, idc.BADADDR
    val = read_pointer(val)

  return val, ea
Example #5
0
 def instances(self, reload=False):
     if reload or not self._inst:
         xr = self.xrefs(reload)
         self._inst = {}
         for x in xr:
             if not idc.isLoaded(x.frm):
                 continue
             ins = self.readInst(x.frm)
             self._inst[ins['address']] = ins
     return self._inst
Example #6
0
    def make_function(self, object_version, address):
        #
        # call the architecture dependent plugin  ###########
        #
        self.arch_plugin.make_function_prehook(object_version, address)

        flags = object_version.get_object_flags()
        size = object_version.get_size()
        # create function if not already exist

        current_flags = idc.GetFlags(address)
        # if ea is func
        func = idaapi.get_func(address)
        if not idaapi.isFunc(current_flags) or (func is not None and
                                                (func.startEA != address)):
            logger.debug(
                "MakeFunction at 0x%08X : flags=0x%08X, current_flags=0x%08X" %
                (address, flags, current_flags))

            if func is not None:
                logger.debug(
                    "                                       "
                    "func.startEA[0x%08X]!=address func.endEA[0x%08X]!=(address+size[0x%08X])  "
                    % (func.startEA, func.endEA, size))
            if not idc.MakeFunction(address):
                if not idc.isLoaded(address):
                    logger.error(
                        "Failed at idc.MakeFunction at 0x%08X : data not loaded"
                        % address)
                else:
                    logger.error("Failed at idc.MakeFunction at 0x%08X" %
                                 address)
                    self.clear_function(object_version, address)
                    if not idc.MakeFunction(address):
                        logger.error("Failed at idc.MakeFunction at 0x%08X" %
                                     address)

                        #             idc.MakeUnknown(address, size, DOUNK_SIMPLE)
            if idc.AnalyzeArea(address, address + 1) != 1:
                logger.error("[0x%08X] idc.AnalyzeArea failed" % address)

                #             if(idc.AnalyzeArea(address, address+size) != 1):
                #                 logger.error("[0x%08X] idc.AnalyzeArea failed" % address)
                #             if(address == 0x0000000000411558):
                #                 raise Exception()
        if flags is not None:
            idc.SetFunctionFlags(address, flags)

        self.set_type(object_version, address)

        #
        # call the architecture dependent plugin  ###########
        #
        self.arch_plugin.make_function_posthook(object_version, address)
Example #7
0
 def _get_segment_bytes(self, start, end):
     """
     Obtain segment bytes, setting non-loaded bytes to NULL
     
     :param int start: segment start EA
     
     :param int end: segment end EA
     
     :return string: bytes contained in segment
     """
     # Reconstruct the segment, account for bytes which are not loaded.
     # Can't use xrange() here because we can get a "Python int too large to conver to C long" error
     seg_range = iter(itertools.count(start).next,
                      end)  # a range from start -> end
     return str(
         bytearray(
             idc.Byte(i) if idc.isLoaded(i) else 0 for i in seg_range))
Example #8
0
    def map_segment(self, address):
        """
        Given an address, map the associated segment into memory so that it can be accesses correctly.

        >>> cpu_context = ProcessorContext()
        >>> cpu_context.map_segment(0x1001A32C)

        :param int address: address within a segment to map
        """
        segStart = idc.SegStart(address)
        segEnd = idc.SegEnd(address)
        segSize = utils.align_page_up(segEnd - segStart)
        segRange = iter(itertools.count(segStart).next, (segStart + segSize))
        segBytes = str(bytearray(idc.Byte(i) if idc.isLoaded(i) else 0 for i in segRange))
        tracing_cpu_logger.debug(
            "[map_segment] :: Mapping memory for segment from 0x{:X}::0x{:X}".format(segStart, segStart + segSize))
        self.mem_write(segStart, segBytes, False)        
Example #9
0
def CALL(cpu_context, ip, mnem, opvalues):
    """
    CALL function

    Attempt to determine the number of arguments passed to the function which are purged on return
    """
    func_ea = opvalues[0].value

    if not isinstance(func_ea, (int, long)):
        cpu_logger.debug("CALL 0x{:X} :: call {!r}".format(ip, func_ea))
        cpu_logger.debug("Invalid function: {!r}".format(func_ea))
        return

    # For the called function, attempt to locate the function end and examine the "retn" instruction which
    # will contain the number of bytes to add back to SP.
    # opvalue1 = idc.GetOperandValue(ip, 0)
    cpu_logger.debug("CALL 0x{:X} :: call 0x{:X}".format(ip, func_ea))

    try:
        is_loaded = idc.isLoaded(func_ea)
    except TypeError:
        is_loaded = False

    # TODO: Disabled until we can keep track of pointer history.
    # # Emulate the effects of any known builtin functions.
    # func_name = idaapi.get_func_name(func_ea)
    # builtin_func = BUILTINS.get(func_name)
    # if builtin_func:
    #     try:
    #         args = cpu_context.get_function_args(func_ea)
    #         builtin_func(cpu_context, ip, func_name, args)
    #     except Exception as e:
    #         cpu_logger.warn(
    #             'Failed to emulate builtin function: {}() at {:#08x} with error: {}'.format(
    #                 func_name, ip, e))

    # For non-loaded files, reset esp based on number of stack arguments.
    # (We are assuming the callee is responsible for resetting the stack)
    if not is_loaded:
        try:
            func_data = utils.get_function_data(func_ea)
            for arg in func_data:
                loc_type = arg.argloc.atype()
                # Where was this parameter passed?
                if loc_type == 1:  # ALOC_STACK
                    # reset esp for each stack argument.
                    cpu_context.reg_write("RSP", cpu_context.reg_read("RSP") + cpu_context._byteness)
        except:
            # If we can't get function data for non-loaded functions, then we have no way of knowing how to handle
            # the stack...
            cpu_logger.debug(
                "{:#08x} :: Cannot identify function information for value {:#08x}. "
                "Stack pointer will not be adjusted.".format(ip, func_ea))
            return
    else:
        # Get address of retn instruction
        func_end = idc.GetFunctionAttr(func_ea, idc.FUNCATTR_END)
        if func_end == idc.BADADDR:
            cpu_logger.debug(
                "{:#08x} :: Could not retrieve retn instruction for called function: {:#08x}. "
                "Stack pointer will not be adjusted.".format(ip, func_ea))
            return

        # Find a "retn" and see if we need to adjust rsp.
        # (All retn's should have the same operand so finding any of them will work).
        # look for retn address
        ea = func_end
        while ea > func_ea:
            if idc.GetMnem(ea) == "retn":
                sp_adjust = idc.GetOperandValue(ea, 0)
                # if retn doesn't adjust the stack, -1 is returned
                if sp_adjust != -1:
                    cpu_context.reg_write("RSP", cpu_context.reg_read("RSP") + sp_adjust)
                return
            ea = idc.PrevHead(ea)