Exemple #1
0
def create_func_by_prefix(func_name, prefix, force=False):
    addrs = []
    start_addr = 0
    func_addr = 0
    while func_addr != idc.BADADDR:
        func_addr = ida_search.find_binary(start_addr, idc.BADADDR, prefix, 16,
                                           idc.SEARCH_DOWN)
        if func_addr == idc.BADADDR:
            break

        # already existing function but it is not the right prefix
        addr = idc.get_func_attr(func_addr, idc.FUNCATTR_START)
        if addr != idc.BADADDR and func_addr != addr:
            if not force:
                start_addr = func_addr + 4
                continue

            idc.del_func(addr)
            idc.del_items(func_addr)

        # add_func is not applied to the existing function
        idc.add_func(func_addr)

        func_name = set_entry_name(func_addr, func_name)
        print("%s: 0x%x" % (func_name, func_addr))

        addrs.append(func_addr)
        start_addr = func_addr + 4

    return addrs
Exemple #2
0
 def add_stub_func(va, sc, nm):
     idaapi.patch_bytes(va, binascii.unhexlify(sc))
     idc.create_insn(va)
     idc.add_func(va)
     mykutils.makename_safe(va, self._stubname(nm))
     cmt = ('%s implementation generated by FLARE Code Grafter' % (nm))
     idc.set_cmt(va, cmt, 1)
Exemple #3
0
    def resolve(self, alphabet, nids, symbols, libraries):

        if self.INFO > Relocation.R_X86_64_ORBIS_GOTPCREL_LOAD:
            self.INDEX = self.INFO >> 32
            self.INFO &= 0xFF
            symbol = next(value for key, value in enumerate(symbols)
                          if key + 2 == self.INDEX)[1]
        else:
            self.INDEX = 0

        # Library
        try:
            lid1 = alphabet[symbol[12:13]]

            # [base64]#
            if symbol[13:14] == '#':
                library = libraries[lid1]

            # [base64][base64]#
            elif symbol[14:15] == '#':
                lid2 = alphabet[symbol[13:14]]
                library = libraries[lid1 + lid2]

            else:
                raise

        # Not a NID
        except:
            library = ''

        # Function Name (Offset) == Symbol Value + AddEnd (S + A)
        # Library Name  (Offset) == Symbol Value (S)
        # Resolve the NID...
        idc.set_cmt(idc.get_qword(self.OFFSET) - 0x6, 'NID: ' + symbol, False)
        function = nids.get(symbol[:11], symbol)

        # Rename the Jump Function...
        idc.set_name(self.OFFSET, '__imp_' + function,
                     SN_NOCHECK | SN_NOWARN | SN_FORCE)

        # Rename the Real Function...
        idc.add_func(idc.get_qword(self.OFFSET) - 0x6)
        idc.set_name(
            idc.get_qword(self.OFFSET) - 0x6, function, SN_NOCHECK | SN_NOWARN)

        try:
            import_node = idaapi.netnode(library, 0, True)
            import_node.supset(ea2node(self.OFFSET), function)

            # Requires customized loader.i / ida_loader.py(d)
            idaapi.import_module(library, None, import_node.index(), None,
                                 'linux')

        except:
            pass

        return self.type()
def define_func(addr, name):

    if addr & 1:
        addr -= 1
        idaapi.split_sreg_range(addr, idaapi.str2reg("T"), 1, idaapi.SR_user)
    else:
        idaapi.split_sreg_range(addr, idaapi.str2reg("T"), 0, idaapi.SR_user)

    if idaapi.create_insn(addr):
        idc.add_func(addr)
        idaapi.set_name(addr, name, idaapi.SN_FORCE)
Exemple #5
0
            def format_vfunc_name(self, ea, current_func_name,
                                  proposed_func_name, class_name,
                                  parent_class_names):
                if current_func_name.startswith("j_"):  # jump
                    current_func_name = current_func_name.lstrip("j_")

                if current_func_name.startswith("qword_"):
                    idc.auto_mark_range(ea, ea + 1, idc.AU_CODE)
                    idc.create_insn(ea)
                    idc.add_func(ea)
                    current_func_name = api.get_addr_name(ea)
                    print(
                        "Info: qword in vtbl of {1} at 0x{0:X}, it may be an offset to undefined code"
                        .format(ea, class_name))

                # Previously renamed as a vfunc
                if current_func_name.startswith(class_name):
                    # return the proposed func name in case it was updated since last run
                    current_class_name = current_func_name.rsplit(".", 1)[0]
                    return "{0}.{1}".format(current_class_name,
                                            proposed_func_name)

                # This should have been handled in the parent class
                if any(
                        current_func_name.startswith(name)
                        for name in parent_class_names):
                    return ""

                if current_func_name.startswith("sub_"):
                    return "{0}.{1}".format(class_name, proposed_func_name)

                if current_func_name.startswith("nullsub_"):
                    return "{0}.{1}_nullsub".format(class_name,
                                                    proposed_func_name)

                if current_func_name.startswith("loc_"):
                    return "{0}.{1}_loc".format(class_name, proposed_func_name)

                if current_func_name.startswith("locret_"):
                    return "{0}.{1}_locret".format(class_name,
                                                   proposed_func_name)

                # Name it later in a child class when it gets overridden
                if current_func_name == "_purecall":
                    return ""

                # Mangled func names, thanks IDA
                if current_func_name.startswith(
                        "?") or current_func_name.startswith("_"):
                    return "{0}.{1}".format(class_name, proposed_func_name)

                return None
Exemple #6
0
    def resolve(self, address, nids, symbol):

        # Resolve the NID...
        idc.set_cmt(self.VALUE, 'NID: ' + symbol, False)
        function = nids.get(symbol[:11], symbol)

        #print('Function: %s | number: %s' % (function, idaapi.get_func_num(self.VALUE)))
        if idaapi.get_func_num(self.VALUE) > 0:
            idc.del_func(self.VALUE)

        if self.VALUE > 0:
            idc.add_func(self.VALUE)
            idc.add_entry(self.VALUE, self.VALUE, function, True)
            idc.set_name(self.VALUE, function, SN_NOCHECK | SN_NOWARN)
            idc.set_cmt(address, '%s | %s' % (function, self.info()), False)
Exemple #7
0
def remake_main():
    # 先新建好所有函数, 再执行
    # -- 脚本将start~end所有函数 undefined, 在start处make function
    import ida_bytes

    start_addr = 0x0402126
    end_addr = 0x0402220

    for i in range(start_addr, end_addr):
        ida_bytes.del_items(i)

    idc.jumpto(start_addr)
    idc.add_func(start_addr)

    import ida_hexrays  # open pseudocode view
    ida_hexrays.open_pseudocode(0x0402126, ida_hexrays.OPF_NO_WAIT)
Exemple #8
0
def makeUnkPushFuncs(start_ea, end_ea):
    """
    Finds and fixes all dead functions not declared as functions following the pattern PUSH {..., LR} POP {..., PC}
    This also only makes functions until the first occurrance of a POP {..., PC}. However, this results in a
    function range error, and that can be fixed as well.
    :param start_ea: start of the range to fix
    :param end_ea: end of the range to fix
    :return:
    """
    ea, pop_ea = next.deadfunc(start_ea, end_ea, ui=False, hexOut=False)
    while ea < end_ea:
        d = Data.Data(ea)
        if d.isCode():
            print('Adding unknown push func @ %07X' % ea)
            idc.add_func(ea, pop_ea + 2)
        ea, pop_ea = next.deadfunc(pop_ea, end_ea, ui=False, hexOut=False)
Exemple #9
0
    def check_address(address):
        # Checks if given address contains virtual table. Returns True if more than 2 function pointers found
        # Also if table's addresses point to code in executable section, than tries to make functions at that addresses
        if helper.is_code_ea(address):
            return False

        if not idaapi.get_name(address):
            return False

        functions_count = 0
        while True:
            func_address = helper.get_ptr(address)
            # print "[INFO] Address 0x{0:08X}".format(func_address)
            if helper.is_code_ea(func_address) or helper.is_imported_ea(
                    func_address):
                functions_count += 1
                address += const.EA_SIZE
            else:
                segment = idaapi.getseg(func_address)
                if segment and segment.perm & idaapi.SEGPERM_EXEC:
                    idc.del_items(func_address, 1, idaapi.DELIT_SIMPLE)
                    if idc.add_func(func_address):
                        functions_count += 1
                        address += const.EA_SIZE
                        continue
                break
            idaapi.auto_wait()
        return functions_count
Exemple #10
0
def load_file(f, neflags, format):
    
    print('# PS3 Syscon Loader')
    
    # PS3 Syscon Processor and Library
    processor('arm', 'gnulnx_arm')
    
    print('# Creating ROM Segment...')
    address = 0x0
    end = address + f.size()
    
    f.file2base(address, address, end, FILEREG_PATCHABLE)
    idaapi.add_segm(0x0, address, end, 'ROM', 'CODE', 0x0)
    
    # Processor Specific Segment Details
    idc.set_segm_addressing(address, 0x1)
    idc.set_segm_alignment(address, saAbs)
    idc.set_segm_combination(address, scPriv)
    idc.set_segm_attr(address, SEGATTR_PERM, SEGPERM_MAXVAL)
    idc.set_default_sreg_value(address, 'T', 0x0)
    idc.set_default_sreg_value(address, 'DS', 0x1)
    
    print('# Waiting for the AutoAnalyzer to Complete...')
    idaapi.auto_wait()
    
    # Create some missing functions...
    while address < end:
        address = idaapi.find_binary(address, end, '?? B5', 0x10, SEARCH_DOWN)
        
        idaapi.create_insn(address)
        
        # Pablo escobar
        if idc.print_insn_mnem(address + 2) in ['LDR', 'MOVS', 'SUB']:
            idc.add_func(address)
        else:
            idaapi.do_unknown(address)
        
        address += 4
    
    print('# Done!')
    return 1

# PROGRAM END
Exemple #11
0
def try_make_function(function_start,
                      function_end=idc.BADADDR,
                      target_location=None,
                      require_term=True,
                      end_mnem_bytes=None):
    """
    Description:
        Given a function location, attempt to create a function.
        If function creation fails, delete any partially created functions.
        If function creation succeeds, ensure all of the function's bytes are analyzed as code.

    Input:
        function_start - The start_ea of the function to create
        function_end - The end_ea of the function to create. IDA will calculate if not provided.
        target_location - If provided, fail function creation if it does not include this EA
        require_term - If provided, fail function creation if the last instruction is not a ret or jmp
        end_mnem_bytes - If provided, fail function creation if the last instruction is not the provided bytes
                         Instructions are entered as space separated bytes (i.e. '55' for 'push ebp')

    Output:
        Returns a tuple (function_start, function_end) for the created function if successful, None otherwise
    """
    if function_start <= function_end:
        if idc.add_func(function_start, function_end):
            logger.debug('Created a function 0x%X - 0x%X.' %
                         (function_start, function_end))
            if require_term:
                last_mnem_ea = idc.get_item_head(
                    idaapi.get_func(function_start).end_ea - 1)
                last_mnem = idc.print_insn_mnem(last_mnem_ea)
                if (end_mnem_bytes is None and 'ret' not in last_mnem and 'jmp' not in last_mnem) or \
                        (end_mnem_bytes and idc.get_bytes(last_mnem_ea, idc.get_item_size(last_mnem_ea)).encode('hex').upper() != end_mnem_bytes.upper()):
                    idc.del_func(function_start)
                    logger.debug(
                        'Deleted function at 0x%X - the function didn\'t end with the correct mnem/bytes.'
                        % function_start)
                    return
            if target_location is not None:
                if function_start <= target_location < idaapi.get_func(
                        function_start).end_ea:
                    idc.plan_and_wait(function_start,
                                      idaapi.get_func(function_start).end_ea)
                    return function_start, function_end
                else:
                    idc.del_func(function_start)
                    logger.debug(
                        'Deleted function at 0x%X - the function didn\'t contain the target location.'
                        % function_start)
                    return
        else:
            logger.debug(
                'Tried to create a function 0x%X - 0x%X, but IDA wouldn\'t do it.'
                % (function_start, function_end))
    else:
        logger.debug('The end address was not greater than the start address!')
Exemple #12
0
def fixFunctionRanges(start_ea, end_ea):
    """
    Fixes all functions with improper returns, by finding their returns and changing their ranges
    For each function, it will ensure that it ends properly until the start of another function, or a data element
    with data xrefs to it. If it ends improperly, or there exists a matching return that is
    not part of the function, it's made part of the function
    This may not behave correctly around dead functions or null_subs. Run tools to Detect and fix those first.
    :param start_ea: start of the range to fix functions in
    :param end_ea: end of the range to fix functions in
    :return:
    """
    # only look 50 instructions ahead, for range change
    searchLimit = 50
    for func_ea in idautils.Functions(start_ea, end_ea):
        f = Function.Function(func_ea)
        # absolute end address of the function (if another function is detected or a data item with data xrefs is)
        stop_ea = f.func_ea + f.getSize()
        for i in range(stop_ea, stop_ea + searchLimit):
            if Function.isFunction(i) or Data.Data(i).getXRefsTo()[1]:
                stop_ea = i
                break
        # figure out the first return, and return type of this function. That should be consistent
        ret_ea = next.ret(f.func_ea, ui=False, hexOut=False)
        try:
            retType = InstDecoder.Inst(ret_ea).fields['magic']
            # modify the function range to include all returns
            if Function.isFunction(ret_ea):
                ret_ea = next.unkret(f.func_ea, ui=False, hexOut=False)
                # this ret_ea is not within the function, if the return type is different
                if InstDecoder.Inst(ret_ea).fields['magic'] != retType:
                    continue
            while f.func_ea < ret_ea < stop_ea:
                # detected that the function range is invalid, fix range
                print('ret %07X' % ret_ea)
                ret_ea = next.unkret(ret_ea, ui=False, hexOut=False)
                # this ret_ea is not within the function, if the return type is different
                if InstDecoder.Inst(ret_ea).fields['magic'] != retType:
                    break
                idc.add_func(func_ea, ret_ea + 2)
        except ValueError:
            continue
Exemple #13
0
    def OnRefresh(self):
        self.Clear()
        addr_id = {}

        for (tid, chain) in self.result.items():
            # Each node data will contain a tuple of the form: (Boolean->Is_thread, Int->Value, String->Label)
            # For threads the is_thread will be true and the value will hold the thread id
            # For exception handlers, is_thread=False and Value=Handler address

            # Add the thread node
            id_parent = self.AddNode( (True, tid, "Thread %X" % tid) )

            # Add each handler
            for handler in chain:
              # Check if a function is created at the handler's address
              f = idaapi.get_func(handler)
              if not f:
                  # create function
                  idc.add_func(handler, idaapi.BADADDR)

              # Node label is function name or address
              s = get_func_name(handler)
              if not s:
                  s = "%x" % handler

              # cache name
              self.names[handler] = s

              # Get the node id given the handler address
              # We use an addr -> id dictionary so that similar addresses get similar node id
              if not addr_id.has_key(handler):
                  id = self.AddNode( (False, handler, s) )
                  addr_id[handler] = id # add this ID
              else:
                  id = addr_id[handler]

              # Link handlers to each other
              self.AddEdge(id_parent, id)
              id_parent = id

        return True
Exemple #14
0
def xex_load_exports(li):
    global export_table_va

    export_table = HvImageExportTable()
    slen = ctypes.sizeof(export_table)
    bytes = ida_bytes.get_bytes(export_table_va, slen)
    fit = min(len(bytes), slen)
    ctypes.memmove(ctypes.addressof(export_table), bytes, fit)

    if export_table.Magic[0] != XEX_EXPORT_MAGIC_0 or export_table.Magic[
            1] != XEX_EXPORT_MAGIC_1 or export_table.Magic[
                2] != XEX_EXPORT_MAGIC_2:
        print("[+] Export table magic is invalid! (0x%X 0x%X 0x%X)" %
              (export_table.Magic[0], export_table.Magic[1],
               export_table.Magic[2]))
        return 0

    print("[+] Loading module exports...")
    print(export_table)

    ordinal_addrs_va = export_table_va + slen
    for i in range(0, export_table.Count):
        func_ord = export_table.Base + i
        func_va = ida_bytes.get_dword(ordinal_addrs_va + (i * 4))
        if func_va == 0:
            continue

        func_va = func_va + (export_table.ImageBaseAddress << 16)
        func_name = x360_imports.DoNameGen(idc.get_root_filename(), 0,
                                           func_ord)

        # Add to exports list & mark as func if inside a code section
        func_segmclass = ida_segment.get_segm_class(
            ida_segment.getseg(func_va))
        idc.add_entry(func_ord, func_va, func_name,
                      1 if func_segmclass == "CODE" else 0)

        if func_segmclass == "CODE":
            idc.add_func(func_va)

    return 1
Exemple #15
0
	def get_func_end(self, start):

		if (idc.add_func(start)):
			return idc.find_func_end(start)

		ea = start
		while (idc.get_wide_byte(ea) != 0xCC):
			idc.create_insn(ea)
			ea += idc.get_item_size(ea)

			if (ea - start > self.jit_max_size):
				return 0

		return ea
Exemple #16
0
    def create(cls, start, end=None):
        """
            Class method allowing to create a new function.

            :param int start: Start address for the function to create.
            :param int end: Facultative argument which indicate the end
                address of the function. If is is not provided (None, default
                value) it will try to create a function using the
                auto-analysis of IDA.
            :return: A new :class:`BipFunction` object corresponding to the
                function create. If this function was not able to create the
                new function a ``BipError`` will be raised.
        """
        if end is None:
            end = 0xffffffffffffffff  # default IDA value meaning auto analysis
        if not idc.add_func(start, end):
            raise BipError("Unable to create function at 0x{:X}".format(start))
        return cls(start)
Exemple #17
0
def fix_func_prolog(ea, end_ea=idc.BADADDR):
    global FUNC_BY_LS

    func_cnt = 0
    func = ida_funcs.get_fchunk(ea)
    if func is None:
        func = ida_funcs.get_next_func(ea)
    ea = func.start_ea

    while func is not None and ea < end_ea:
        # if current function is small enough and there exists a function right
        # next to current function
        if (func.size() <= 8 and idc.get_func_attr(
                func.end_ea, idc.FUNCATTR_START) != idc.BADADDR):
            # If the next function can be connected, there must be a basic block reference.
            # xref.type == 21 means 'fl_F', which is an ordinary flow.
            if all(
                (func.start_ea <= xref.frm < func.end_ea) and xref.type == 21
                    for xref in XrefsTo(func.end_ea)):
                if func_cnt > 0 and func_cnt % 1000 == 0:
                    print("%x <- %x: prolog merging (%d)." %
                          (func.start_ea, func.end_ea, func_cnt))
                ida_bytes.del_items(func.end_ea, ida_bytes.DELIT_EXPAND)
                ida_bytes.del_items(func.start_ea, ida_bytes.DELIT_EXPAND)
                ida_auto.auto_wait()

                status = idc.add_func(func.start_ea)
                if not status:
                    print("Error merging 0x%x <- 0x%x" %
                          (func.start_ea, func.end_ea))
                else:
                    func_cnt += 1
                    FUNC_BY_LS.discard(func.end_ea)
                ida_auto.auto_wait()

        func = ida_funcs.get_next_func(ea)
        if func:
            ea = func.start_ea

    print("Fixed %d functions" % func_cnt)
Exemple #18
0
def analyze_linear_sweep(start_ea, end_ea=idc.BADADDR):
    global FUNC_BY_LS, FUNC_BY_LS_TIME
    if "FUNC_BY_LS" not in globals() or len(FUNC_BY_LS) == 0:
        FUNC_BY_LS = set()

    cand_cnt = 0
    func_cnt = 0
    ea = start_ea
    start_time = time.time()
    while ea < end_ea and ea != idc.BADADDR:
        ea, mode = find_next_func_cand(ea, end_ea)
        if ea == idc.BADADDR:
            break

        cand_cnt += 1
        if cand_cnt % 10000 == 0:
            print("%x: %d/%d function has been found (%d secs)" %
                  (ea, func_cnt, cand_cnt, time.time() - start_time))

        # set IDA segment register to specify ARM mode
        old_flag = idc.get_sreg(ea, "T")
        if mode == THUMB:
            idc.split_sreg_range(ea, "T", 1, idc.SR_user)
        elif mode == ARM:
            idc.split_sreg_range(ea, "T", 0, idc.SR_user)
        else:
            print("Unknown mode")
            raise NotImplemented

        # add_func ignores the existing function, but existing function is
        # already filtered when finding the candidate
        status = idc.add_func(ea)
        if status:
            func_cnt += 1
            FUNC_BY_LS.add(ea)

            # Wait IDA's auto analysis
            ida_auto.auto_wait()

            # even though add_func succeed, it may not be correct.
            # TODO: how to check the correctness? we may check the function end?
            func_end = idc.get_func_attr(ea, idc.FUNCATTR_END)
            if func_end > ea:
                ea = func_end
            else:
                # sometimes, ida returns wrong addr
                ea = next_addr_aligned(ea)

        else:
            if idc.get_func_attr(ea, idc.FUNCATTR_START) == idc.BADADDR:
                # IDA automatically make code, and this remains even though
                # add_func fails.
                ida_bytes.del_items(ea, ida_bytes.DELIT_EXPAND)

                # reset IDA segment register to previous ARM mode
                idc.split_sreg_range(ea, "T", old_flag, idc.SR_user)

                # Wait IDA's auto analysis
                ida_auto.auto_wait()

            ea = next_addr_aligned(ea)

    # linear sweep may choose wrong prologs. We merge the prologs of two
    # adjacent functions.
    if func_cnt > 0:
        fix_func_prolog(start_ea, end_ea)

    FUNC_BY_LS_TIME = time.time() - start_time
    print("Found %d/%d functions. (%d sec)" %
          (len(FUNC_BY_LS), cand_cnt, FUNC_BY_LS_TIME))
Exemple #19
0
def load_file(f, neflags, format):

    print('# PS4 Module Loader')
    ps = Binary(f)

    # PS4 Processor, Compiler, Library
    bitness = ps.procomp('metapc', CM_N64 | CM_M_NN | CM_CC_FASTCALL,
                         'gnulnx_x64')

    # Load Aerolib...
    nids = load_nids(idc.idadir() + '/loaders/aerolib.csv')

    # Segment Loading...
    for segm in ps.E_SEGMENTS:

        # Process Loadable Segments...
        if segm.name() in [
                'CODE', 'DATA', 'SCE_RELRO', 'DYNAMIC', 'GNU_EH_FRAME',
                'SCE_DYNLIBDATA'
        ]:

            address = segm.MEM_ADDR if segm.name() not in [
                'DYNAMIC', 'SCE_DYNLIBDATA'
            ] else segm.OFFSET + 0x1000000
            size = segm.MEM_SIZE if segm.name() not in [
                'DYNAMIC', 'SCE_DYNLIBDATA'
            ] else segm.FILE_SIZE

            print('# Processing %s Segment...' % segm.name())
            f.file2base(segm.OFFSET, address, address + segm.FILE_SIZE,
                        FILEREG_PATCHABLE)

            if segm.name() not in ['DYNAMIC', 'GNU_EH_FRAME']:

                idaapi.add_segm(0, address, address + size, segm.name(),
                                segm.type(), ADDSEG_NOTRUNC | ADDSEG_FILLGAP)

                # Processor Specific Segment Details
                idc.set_segm_addressing(address, bitness)
                idc.set_segm_alignment(address, segm.alignment())
                idc.set_segm_attr(address, SEGATTR_PERM, segm.flags())

            # Process Dynamic Segment....
            elif segm.name() == 'DYNAMIC':

                stubs = {}
                modules = {}
                libraries = {}
                f.seek(segm.OFFSET)

                offset = segm.OFFSET
                dynamic = address
                dynamicsize = size

                for entry in xrange(size / 0x10):
                    idc.set_cmt(address + (entry * 0x10),
                                Dynamic(f).process(stubs, modules, libraries),
                                False)
            '''
            # Process Exception Handling Segment...
            elif segm.name() == 'GNU_EH_FRAME':
                
                # Exception Handling Frame Header Structure
                members = [('version', 'Version', 0x1),
                           ('eh_frame_ptr_enc', 'Encoding of Exception Handling Frame Pointer', 0x1),
                           ('fde_count_enc', 'Encoding of Frame Description Entry Count', 0x1),
                           ('table_enc', 'Encoding of Table Entries', 0x1)]
                struct = segm.struct('EHFrame', members)
                
                idaapi.create_struct(address, 0x4, struct)
                
                # Exception Handling Structure
                members = [('exception', 'value', 0x8)]
                struct = segm.struct('Exception', members)
                
                for entry in xrange(size / 0x8):
                    idaapi.create_struct(address + (entry * 0x8), 0x8, struct)
            '''

        # Process SCE 'Special' Shared Object Segment...
        if segm.name() == 'SCE_DYNLIBDATA':

            # SCE Fingerprint
            idc.make_array(address, 0x14)
            idc.set_name(address, 'SCE_FINGERPRINT',
                         SN_NOCHECK | SN_NOWARN | SN_FORCE)
            idc.set_cmt(
                address, ' '.join(
                    x.encode('hex')
                    for x in idc.get_bytes(address, 0x14)).upper(), False)

            # Dynamic Symbol Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Dynamic Symbol Entry Structure
                members = [('name', 'Name (String Index)', 0x4),
                           ('info', 'Info (Binding : Type)', 0x1),
                           ('other', 'Other', 0x1),
                           ('shtndx', 'Section Index', 0x2),
                           ('value', 'Value', 0x8), ('size', 'Size', 0x8)]
                struct = segm.struct('Symbol', members)

                # Dynamic Symbol Table
                location = address + Dynamic.SYMTAB
                f.seek(segm.OFFSET + Dynamic.SYMTAB)
                symbols = {}

                for entry in xrange(Dynamic.SYMTABSZ / 0x18):
                    idaapi.create_struct(location + (entry * 0x18), 0x18,
                                         struct)
                    idc.set_cmt(location + (entry * 0x18),
                                Symbol(f).process(symbols), False)

            except:
                pass

            # Dynamic String Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Dynamic String Table
                location = address + Dynamic.STRTAB
                f.seek(segm.OFFSET + Dynamic.STRTAB)

                # Stubs
                for key in stubs:
                    idc.create_strlit(location + key, BADADDR)
                    stubs[key] = idc.get_strlit_contents(
                        location + key, BADADDR)
                    idc.set_cmt(location + key, 'Stub', False)

                #print('Stubs: %s' % stubs)

                # Modules
                for key in modules:
                    idc.create_strlit(location + key, BADADDR)
                    modules[key] = idc.get_strlit_contents(
                        location + key, BADADDR)
                    idc.set_cmt(location + key, 'Module', False)

                #print('Modules: %s' % modules)

                # Libraries and LIDs
                lids = {}
                for key, value in libraries.iteritems():
                    idc.create_strlit(location + key, BADADDR)
                    lids[value] = idc.get_strlit_contents(
                        location + key, BADADDR)
                    libraries[key] = idc.get_strlit_contents(
                        location + key, BADADDR)
                    idc.set_cmt(location + key, 'Library', False)

                #print('LIDs: %s' % lids)

                # Symbols
                for key in symbols:
                    idc.create_strlit(location + key, BADADDR)
                    symbols[key] = idc.get_strlit_contents(
                        location + key, BADADDR)
                    idc.set_cmt(location + key, 'Symbol', False)

                #print('Symbols: %s' % symbols)

            except:
                pass

            # Resolve Export Symbols
            try:
                symbols = sorted(symbols.iteritems())
                location = address + Dynamic.SYMTAB + 0x30
                f.seek(segm.OFFSET + Dynamic.SYMTAB + 0x30)

                for entry in xrange((Dynamic.SYMTABSZ - 0x30) / 0x18):
                    Symbol(f).resolve(location + (entry * 0x18), nids,
                                      symbols[entry][1])

            except:
                pass

            # Jump Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Jump Entry Structure
                members = [('offset', 'Offset (String Index)', 0x8),
                           ('info', 'Info (Symbol Index : Relocation Code)',
                            0x8), ('addend', 'AddEnd', 0x8)]
                struct = segm.struct('Jump', members)

                # PS4 Base64 Alphabet
                base64 = list(
                    'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-'
                )
                alphabet = {
                    character: index
                    for index, character in enumerate(base64)
                }
                #print('Base64 Table: %s' % alphabet)

                # Jump Table
                location = address + Dynamic.JMPTAB
                f.seek(segm.OFFSET + Dynamic.JMPTAB)

                for entry in xrange(Dynamic.JMPTABSZ / 0x18):
                    idaapi.create_struct(location + (entry * 0x18), 0x18,
                                         struct)
                    idc.set_cmt(
                        location + (entry * 0x18),
                        Relocation(f).resolve(alphabet, nids, symbols, lids),
                        False)

            except:
                pass

            # Relocation Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Relocation Entry Structure (with specific addends)
                members = [('offset', 'Offset (String Index)', 0x8),
                           ('info', 'Info (Symbol Index : Relocation Code)',
                            0x8), ('addend', 'AddEnd', 0x8)]
                struct = segm.struct('Relocation', members)

                # Relocation Table (with specific addends)
                location = address + Dynamic.RELATAB
                f.seek(segm.OFFSET + Dynamic.RELATAB)

                for entry in xrange(Dynamic.RELATABSZ / 0x18):
                    idaapi.create_struct(location + (entry * 0x18), 0x18,
                                         struct)
                    idc.set_cmt(location + (entry * 0x18),
                                Relocation(f).process(nids, symbols), False)

            except:
                pass

            # Hash Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Hash Entry Structure
                members = [('bucket', 'Bucket', 0x2), ('chain', 'Chain', 0x2),
                           ('buckets', 'Buckets', 0x2),
                           ('chains', 'Chains', 0x2)]
                struct = segm.struct('Hash', members)

                # Hash Table
                location = address + Dynamic.HASHTAB
                f.seek(segm.OFFSET + Dynamic.HASHTAB)

                for entry in xrange(Dynamic.HASHTABSZ / 0x8):
                    idaapi.create_struct(location + (entry * 0x8), 0x8, struct)

            except:
                pass

            # Dynamic Tag Table
            try:
                # --------------------------------------------------------------------------------------------------------
                # Dynamic Tag Entry Structure
                members = [('tag', 'Tag', 0x8), ('value', 'Value', 0x8)]
                struct = segm.struct('Tag', members)

                f.seek(offset)

                for entry in xrange(dynamicsize / 0x10):
                    idaapi.create_struct(dynamic + (entry * 0x10), 0x10,
                                         struct)
                    idc.set_cmt(
                        dynamic + (entry * 0x10),
                        Dynamic(f).comment(address, stubs, modules, libraries),
                        False)

            except:
                pass

    # Start Function
    idc.add_entry(ps.E_START_ADDR, ps.E_START_ADDR, 'start', True)

    print('# Waiting for the AutoAnalyzer to Complete...')
    idaapi.auto_wait()

    # Set No Return for __stack_chk_fail...
    try:
        function = idc.get_name_ea_simple('__stack_chk_fail')
        function = idaapi.get_func(function)
        function.flags |= FUNC_NORET
        idaapi.update_func(function)

    except:
        pass

    # Missed Function Creation...
    try:
        code = idaapi.get_segm_by_name('CODE')

        address = code.start_ea
        end = code.end_ea

        # Final Pass
        print('# Performing Final Pass...')
        while address < end:
            address = idaapi.find_not_func(address, SEARCH_DOWN)

            if idaapi.is_unknown(idaapi.get_flags(address)):
                idaapi.create_insn(address)
            else:
                idc.add_func(address)

            address += 4

    except:
        pass

    print('# Done!')
    return 1
Exemple #20
0
def xex_load_imports(li):
    global directory_entry_headers

    li.seek(directory_entry_headers[XEX_HEADER_IMPORTS])
    import_desc = read_struct(li, XEXImportDescriptor)

    # seperate the library names in the name table
    import_libnames = []
    cur_lib = ""
    for i in range(0, import_desc.NameTableSize):
        name_char = li.read(1)

        if name_char == '\0' or name_char == '\xCD':
            if cur_lib != "":
                import_libnames.append(cur_lib)
                cur_lib = ""
        else:
            cur_lib += name_char

    # read each import library table
    for i in range(0, import_desc.ModuleCount):
        table_addr = li.tell()
        table_header = read_struct(li, XEXImportTable)
        libname = import_libnames[table_header.ModuleIndex]
        variables = {}
        for i in range(0, table_header.ImportCount):
            record_addr = read_dwordBE(li)

            record_value = ida_bytes.get_dword(record_addr)
            record_type = (record_value & 0xFF000000) >> 24
            ordinal = record_value & 0xFFFF

            import_name = x360_imports.DoNameGen(libname, 0, ordinal)
            if record_type == 0:
                # variable
                idc.create_data(record_addr, idc.FF_WORD, 2, idc.BADADDR)
                idc.create_data(record_addr + 2, idc.FF_WORD, 2, idc.BADADDR)
                idc.make_array(record_addr, 2)
                idc.set_name(record_addr, "__imp__" + import_name)
                variables[ordinal] = record_addr

            elif record_type == 1:
                # thunk
                # have to rewrite code to set r3 & r4 like xorlosers loader does
                # r3 = module index afaik
                # r4 = ordinal
                # important to note that basefiles extracted via xextool have this rewrite done already, but raw basefile from XEX doesn't!
                # todo: find out how to add to imports window like xorloser loader...

                ida_bytes.put_dword(record_addr + 0,
                                    0x38600000 | table_header.ModuleIndex)
                ida_bytes.put_dword(record_addr + 4, 0x38800000 | ordinal)
                idc.add_func(record_addr, record_addr + 0x10)
                idc.set_name(record_addr, import_name)

                # add comment to thunk like xorloser's loader
                idc.set_cmt(
                    record_addr + 4,
                    "%s :: %s" % (libname.rsplit('.', 1)[0], import_name), 1)

                # this should mark the func as a library function, but it doesn't do anything for some reason
                # tried a bunch of things like idaapi.autoWait() before running it, just crashes IDA with internal errors...
                idc.set_func_flags(
                    record_addr,
                    idc.get_func_flags(record_addr) | idc.FUNC_LIB)

                # thunk means it's not a variable, so remove from variables dict
                if ordinal in variables:
                    variables.pop(ordinal)

            else:
                print(
                    "[+] %s import %d (%s) (@ 0x%X) unknown type %d!" %
                    (libname, ordinal, import_name, record_addr, record_type))

        # remove "__imp__" part from variable import names
        for ordinal in variables:
            import_name = x360_imports.DoNameGen(libname, 0, ordinal)
            idc.set_name(variables[ordinal], import_name)

        # Seek to end of this import table
        li.seek(table_addr + table_header.TableSize)

    return
Exemple #21
0
def analyze_func_ptr(start_ea, end_ea):
    global FUNC_BY_PTR, FUNC_BY_PTR_TIME
    if "FUNC_BY_PTR" not in globals() or len(FUNC_BY_PTR) == 0:
        FUNC_BY_PTR = set()

    ea = start_ea
    func_cnt = 0
    name_cnt = 0
    start_time = time.time()

    while ea != idc.BADADDR and ea <= end_ea:
        status, ea = is_assigned(ea)
        if status:
            continue

        # now check function pointer
        func_ptr = ida_bytes.get_dword(ea)

        # TODO: skip other segments that are not code.

        # for those already assigned functions, we need to check the segment range.
        if not (start_ea <= func_ptr < end_ea):
            ea = next_addr_aligned(ea, 4)
            continue

        # we only target thumb function to reduce false positives
        if func_ptr & 1 == 0:
            ea = next_addr_aligned(ea, 4)
            continue

        func_ptr = func_ptr - 1
        func_start = idc.get_func_attr(func_ptr, idc.FUNCATTR_START)
        if func_start != idc.BADADDR and func_start != func_ptr:
            # this is not a proper function pointer
            ea = next_addr_aligned(ea, 4)
            continue

        # new thumb function has been found!
        if func_start == idc.BADADDR:
            old_flag = idc.get_sreg(func_ptr, "T")
            idc.split_sreg_range(func_ptr, "T", 1, idc.SR_user)
            status = idc.add_func(func_ptr)
            if not status:
                # IDA automatically make code, and this remains even
                # though add_func fails.
                ida_bytes.del_items(func_ptr, ida_bytes.DELIT_EXPAND)
                idc.split_sreg_range(func_ptr, "T", old_flag, idc.SR_user)

                ea = next_addr_aligned(ea, 4)
                continue

            func_cnt += 1
            FUNC_BY_PTR.add(ea)
            if func_cnt % 10000 == 0:
                print("%x: %d functions has been found. (%0.3f secs)" %
                      (ea, func_cnt, time.time() - start_time))

        # If we find a function, we try to assign a name. The name may be
        # derived by C++ structure.
        if analyze_funcname(ea, func_ptr):
            name_cnt += 1
            func_name = idc.get_func_name(func_ptr)
            if name_cnt % 10000 == 0:
                print("%x: %d names has been found. (%0.3f secs)" %
                      (ea, name_cnt, time.time() - start_time))
            # print("%x: %x => %s" % (ea, func_ptr, func_name))

        ea = next_addr_aligned(ea, 4)

    FUNC_BY_PTR_TIME = time.time() - start_time
    print("Found %d functions, renamed %d functions (%0.3f secs)" %
          (len(FUNC_BY_PTR), name_cnt, FUNC_BY_PTR_TIME))
Exemple #22
0
 def apply(self):
     if self.data_at_address:
         ida_bytes.del_items(self.address, ida_bytes.DELIT_SIMPLE)
     idc.add_func(self.address)
     return True
Exemple #23
0
 def __call__(self):
     idc.add_func(self.start_ea, self.end_ea)
def load_file(f, neflags, format):
    
    print('# PS4 Kernel Loader')
    ps = Binary(f)
    
    # PS4 Processor, Compiler, Library
    bitness = ps.procomp('metapc', CM_N64 | CM_M_NN | CM_CC_FASTCALL, 'gnulnx_x64')
    
    # Segment Loading...
    for segm in ps.E_SEGMENTS:
        if segm.name() == 'PHDR':
            kASLR = False if segm.FILE_SIZE == 0x118 else True
        
        # Process Loadable Segments...
        if segm.name() in ['CODE', 'DATA', 'SCE_RELRO']:
            address = segm.MEM_ADDR
            size = segm.MEM_SIZE
            
            # Dumped Kernel Fix-ups
            if segm.name() in ['DATA', 'SCE_RELRO'] and (idaapi.get_segm_by_name('CODE').start_ea != 0xFFFFFFFF82200000 or not kASLR):
                offset = address - idaapi.get_segm_by_name('CODE').start_ea
                dumped = segm.MEM_SIZE
            else:
                offset = segm.OFFSET
                dumped = segm.FILE_SIZE
            
            print('# Creating %s Segment...' % segm.name())
            f.file2base(offset, address, address + dumped, FILEREG_PATCHABLE)
            
            idaapi.add_segm(0, address, address + size, segm.name(), segm.type(), ADDSEG_NOTRUNC | ADDSEG_FILLGAP)
            
            # Processor Specific Segment Details
            idc.set_segm_addressing(address, bitness)
            idc.set_segm_alignment(address, segm.alignment())
            idc.set_segm_attr(address, SEGATTR_PERM, segm.flags())
        
        # Process Dynamic Segment...
        elif segm.name() == 'DYNAMIC':
            code = idaapi.get_segm_by_name('CODE')
            data = idaapi.get_segm_by_name('DATA')
            relro = idaapi.get_segm_by_name('SCE_RELRO')
            
            # ------------------------------------------------------------------------------------------------------------
            # Dynamic Tag Entry Structure
            members = [('tag', 'Tag', 0x8),
                       ('value', 'Value', 0x8)]
            struct = segm.struct('Tag', members)
            
            # Dynamic Tag Table
            stubs = {}
            modules = {}
            location = segm.MEM_ADDR
            
            # Dumps are offset by a small amount
            if code.start_ea != 0xFFFFFFFF82200000:
                dumped = code.start_ea - 0xFFFFFFFF82200000
            else:
                dumped = 0
            
            f.seek(location - code.start_ea)
            for entry in xrange(segm.MEM_SIZE / 0x10):
                idaapi.create_struct(location + (entry * 0x10), 0x10, struct)
                idc.set_cmt(location + (entry * 0x10), Dynamic(f).process(dumped, stubs, modules), False)
            
            # ------------------------------------------------------------------------------------------------------------
            # Hash Entry Structure
            members = [('bucket', 'Bucket', 0x2),
                       ('chain', 'Chain', 0x2),
                       ('buckets', 'Buckets', 0x2),
                       ('chains', 'Chains', 0x2)]
            struct = segm.struct('Hash', members)
            
            # Hash Table
            try:
                location = Dynamic.HASHTAB
                size = Dynamic.HASHTABSZ
            
            except:
                location = Dynamic.HASH
                size = Dynamic.SYMTAB - location
            
            f.seek(location - code.start_ea)
            for entry in xrange(size / 0x8):
                idaapi.create_struct(location + (entry * 0x8), 0x8, struct)
            
            if kASLR:
                # --------------------------------------------------------------------------------------------------------
                # Relocation Entry Structure (with specific addends)
                members = [('offset', 'Offset (String Index)', 0x8),
                           ('info', 'Info (Symbol Index : Relocation Code)', 0x8),
                           ('addend', 'AddEnd', 0x8)]
                struct = segm.struct('Relocation', members)
                
                # Relocation Table (with specific addends)
                location = Dynamic.RELATAB
                
                f.seek(location - code.start_ea)
                for entry in xrange(Dynamic.RELATABSZ / 0x18):
                    idaapi.create_struct(location + (entry * 0x18), 0x18, struct)
                    idc.set_cmt(location + (entry * 0x18), Relocation(f).process(dumped, code.end_ea), False)
                
                # Initialization Function
                idc.add_entry(Dynamic.INIT, Dynamic.INIT, '.init', True)
            
            else:
                # --------------------------------------------------------------------------------------------------------
                # Symbol Entry Structure
                members = [('name', 'Name (String Index)', 0x4),
                           ('info', 'Info (Binding : Type)', 0x1),
                           ('other', 'Other', 0x1),
                           ('shtndx', 'Section Index', 0x2),
                           ('offset', 'Value', 0x8),
                           ('size', 'Size', 0x8)]
                struct = segm.struct('Symbol', members)
                
                # Symbol Table
                location = Dynamic.SYMTAB
                f.seek(location - code.start_ea)
                functions = {}
                
                # .symtab
                idc.add_entry(location, location, '.symtab', False)
                
                for entry in xrange((Dynamic.STRTAB - location) / 0x18):
                    idaapi.create_struct(location + (entry * 0x18), 0x18, struct)
                    idc.set_cmt(location + (entry * 0x18), Symbol(f).process(functions), False)
                
                # --------------------------------------------------------------------------------------------------------
                # Dynamic String Table
                location = Dynamic.STRTAB
                
                # .strtab
                idc.add_entry(location, location, '.strtab', False)
                
                # Functions
                for key in functions:
                    idc.create_strlit(location + key, BADADDR)
                    functions[key] = idc.get_strlit_contents(location + key, BADADDR)
                    idc.set_cmt(location + key, 'Function', False)
                
                functions = sorted(functions.iteritems(), key = operator.itemgetter(0))
                #print('Functions: %s' % functions)
                
                # Resolve Functions
                location = Dynamic.SYMTAB
                f.seek(location - code.start_ea + 0x18)
                
                for entry in xrange((Dynamic.STRTAB - location - 0x18) / 0x18):
                    Symbol(f).resolve(functions[entry][1])
    
    # Fix-up
    if kASLR:
        address = relro.start_ea
        del_items(address, DELIT_SIMPLE, relro.end_ea - address)
        
        while address < relro.end_ea:
            create_data(address, FF_QWORD, 0x8, BADNODE)
            address += 0x8
    
    address = code.start_ea
    
    # ELF Header Structure
    members = [('File format', 0x4),
               ('File class', 0x1),
               ('Data encoding', 0x1),
               ('File version', 0x1),
               ('OS/ABI', 0x1),
               ('ABI version', 0x1),
               ('Padding', 0x7),
               ('File type', 0x2),
               ('Machine', 0x2),
               ('File version', 0x4),
               ('Entry point', 0x8),
               ('PHT file offset', 0x8),
               ('SHT file offset', 0x8),
               ('Processor-specific flags', 0x4),
               ('ELF header size', 0x2),
               ('PHT entry size', 0x2),
               ('Number of entries in PHT', 0x2),
               ('SHT entry size', 0x2),
               ('Number of entries in SHT', 0x2),
               ('SHT entry index for string table\n', 0x2)]
    
    for (comment, size) in members:
        flags = idaapi.get_flags_by_size(size)
        idc.create_data(address, flags if flags != 0 else FF_STRLIT, size, BADNODE)
        idc.set_cmt(address, comment, False)
        address += size
    
    for index, entry in enumerate(ps.E_SEGMENTS):
        # ELF Program Header Structure
        members = [('Type: %s' % entry.name(), 0x4),
                   ('Flags', 0x4),
                   ('File offset', 0x8),
                   ('Virtual address', 0x8),
                   ('Physical address', 0x8),
                   ('Size in file image', 0x8),
                   ('Size in memory image', 0x8),
                   ('Alignment\n', 0x8)]
        
        for (comment, size) in members:
            flags = idaapi.get_flags_by_size(size)
            
            idc.create_data(address, flags if flags != 0 else FF_STRLIT, size, BADNODE)
            idc.set_cmt(address, comment, False)
            address += size
    
    # Wait for the AutoAnalyzer to Complete...
    print('# Waiting for the AutoAnalyzer to Complete...')
    idaapi.auto_wait()
    
    if kASLR:
        # Start Function
        idc.add_entry(ps.E_START_ADDR, ps.E_START_ADDR, 'start', True)
        
        # Xfast_syscall
        address = idaapi.find_binary(code.start_ea, code.end_ea, '0F 01 F8 65 48 89 24 25 A8 02 00 00 65 48 8B 24', 0x10, SEARCH_DOWN)
        idaapi.do_unknown(address, 0)
        idaapi.create_insn(address)
        idaapi.add_func(address, BADADDR)
        idaapi.set_name(address, 'Xfast_syscall', SN_NOCHECK | SN_NOWARN)
        
        # --------------------------------------------------------------------------------------------------------
        # Znullptr's syscalls
        print('# Processing Znullptr\'s Syscalls...')
        
        # Syscall Entry Structure
        members = [('narg', 'Number of Arguments', 0x4),
                   ('_pad', 'Padding', 0x4),
                   ('function', 'Function', 0x8),
                   ('auevent', 'Augmented Event?', 0x2),
                   ('_pad1', 'Padding', 0x2),
                   ('_pad2', 'Padding', 0x4),
                   ('trace_args_func', 'Trace Arguments Function', 0x8),
                   ('entry', 'Entry', 0x4),
                   ('return', 'Return', 0x4),
                   ('flags', 'Flags', 0x4),
                   ('thrcnt', 'Thread Count?', 0x4)]
        struct = segm.struct('Syscall', members)
        
        znullptr(code.start_ea, code.end_ea, '4F 52 42 49 53 20 6B 65 72 6E 65 6C 20 53 45 4C 46', struct)
        
        # --------------------------------------------------------------------------------------------------------
        # Chendo's cdevsw con-struct-or
        print('# Processing Chendo\'s cdevsw structs...')
        
        # cdevsw Entry Structure
        members = [('d_version', 'Version', 0x4),
                   ('d_flags', 'Flags', 0x4),
                   ('d_name', 'Name', 0x8),
                   ('d_open', 'Open', 0x8),
                   ('d_fdopen', 'File Descriptor Open', 0x8),
                   ('d_close', 'Close', 0x8),
                   ('d_read', 'Read', 0x8),
                   ('d_write', 'Write', 0x8),
                   ('d_ioctl', 'Input/Ouput Control', 0x8),
                   ('d_poll', 'Poll', 0x8),
                   ('d_mmap', 'Memory Mapping', 0x8),
                   ('d_strategy', 'Strategy', 0x8),
                   ('d_dump', 'Dump', 0x8),
                   ('d_kqfilter', 'KQFilter', 0x8),
                   ('d_purge', 'Purge', 0x8),
                   ('d_mmap_single', 'Single Memory Mapping', 0x8),
                   ('d_spare0', 'Spare0', 0x8),
                   ('d_spare1', 'Spare1', 0x8),
                   ('d_spare2', 'Spare2', 0x8),
                   ('d_spare3', 'Spare3', 0x8),
                   ('d_spare4', 'Spare4', 0x8),
                   ('d_spare5', 'Spare5', 0x8),
                   ('d_spare6', 'Spare6', 0x4),
                   ('d_spare7', 'Spare7', 0x4)]
        struct = segm.struct('cdevsw', members)
        
        chendo(data.start_ea, data.end_ea, '09 20 12 17', struct)
    
    # --------------------------------------------------------------------------------------------------------
    # Pablo's IDC
    try:
        print('# Processing Pablo\'s Push IDC...')
        
        # Script 1) Push it real good...
        pablo(code.start_ea, code.end_ea, 'C5 FA 5A C0 C5 F2 5A C9 C5 EA 5A D2 C5 FB 59 C1')
        pablo(code.start_ea, code.end_ea, 'C5 F9 7E C0 31 C9')
        pablo(code.start_ea, code.end_ea, '48 89 E0 55 53')
        pablo(code.start_ea, code.end_ea, 'B8 2D 00 00 00 C3')
        pablo(code.start_ea, code.end_ea, '31 C0 C3')
        pablo(code.start_ea, code.end_ea, '55 48 89')
        pablo(code.start_ea, code.end_ea, '48 81 EC A0 00 00 00 C7')
        pablo(code.start_ea, code.end_ea, '48 81 EC A8 00 00 00')
        
        # Script 2) Fix-up Dumped Data Pointers...
        if dumped or not kASLR:
            print('# Processing Pablo\'s Dumped Data Pointers IDC...')
            pablo(data.start_ea, data.end_ea, '?? FF FF FF FF')
    
    except:
        pass
    
    # --------------------------------------------------------------------------------------------------------
    # Kiwidog's __stack_chk_fail
    if kASLR:
        print('# Processing Kiwidog\'s Stack Functions...')
        
        kiwidog(code.start_ea, code.end_ea, '73 74 61 63 6B 20 6F 76 65 72 66 6C 6F 77 20 64 65 74 65 63 74 65 64 3B')
    
    # --------------------------------------------------------------------------------------------------------
    # Final Pass
    print('# Performing Final Pass...')
    address = code.start_ea
    while address < code.end_ea:
        address = idaapi.find_not_func(address, SEARCH_DOWN)
        
        if idaapi.isUnknown(idaapi.getFlags(address)):
            idaapi.create_insn(address)
        else:
            idc.add_func(address)
        
        address += 4
    
    print('# Done!')
    return 1
Exemple #25
0
def CallStackWalk(nn):
    class Result:
        """
        Class holding the result of one call stack item
        Each call stack item instance has the following attributes:
            caller = ea of caller
            displ  = display string
            sp     = stack pointer
        """
        def __init__(self, caller, sp):
            self.caller = caller
            self.sp = sp
            f = idaapi.get_func(caller)
            self.displ = ""
            if f:
                self.displ += idc.get_func_name(caller)
                t = caller - f.start_ea
                if t > 0: self.displ += "+" + hex(t)
            else:
                self.displ += hex(caller)
            self.displ += " [" + hex(sp) + "]"

    # get stack pointer
    sp = cpu.Esp
    seg = idaapi.getseg(sp)
    if not seg:
        return (False, "Could not locate stack segment!")

    stack_seg = Seg(seg)
    word_size = 2**(seg.bitness + 1)
    callers = []
    sp = cpu.Esp - word_size
    while sp < stack_seg.end_ea:
        sp += word_size
        ptr = idautils.GetDataList(sp, 1, word_size).next()
        seg = idaapi.getseg(ptr)
        # only accept executable segments
        if (not seg) or ((seg.perm & idaapi.SEGPERM_EXEC) == 0):
            continue
        # try to find caller
        caller = IsPrevInsnCall(ptr)
        # we have no recognized caller, skip!
        if caller is None:
            continue

        # do we have a debug name that is near?
        if nn:
            ret = nn.find(caller)
            if ret:
                ea = ret[0]
                # function exists?
                f = idaapi.get_func(ea)
                if not f:
                    # create function
                    idc.add_func(ea, idaapi.BADADDR)

        # get the flags
        f = idc.get_flags(caller)
        # no code there?
        if not is_code(f):
            create_insn(caller)

        callers.append(Result(caller, sp))
    #
    return (True, callers)