Esempio n. 1
0
    def get_xref(self, objc_selrefs, objc_msgrefs, objc_const):
        #We're looking for references to the selector string (think char **)
        #Which is either a selref, a msgref, or a pointer to the selector from the class's const method list
        name_ptr = self.name_pointer
        is_msg_ref = False
        selector_ref = None
        #how many references from __objc_const are there? This indicates how many classes
        #reference this selector
        const_ref_count = 0
        for xref in XrefsTo(name_ptr):
            #Is this cross reference in the range of selector references?
            if objc_selrefs and xref.frm >= objc_selrefs[
                    0] and xref.frm < objc_selrefs[1]:
                is_msg_ref = False
                selector_ref = xref
            #else, is this cross reference in the range of msg references?
            elif objc_msgrefs and xref.frm >= objc_msgrefs[
                    0] and xref.frm < objc_msgrefs[1]:
                is_msg_ref = True
                selector_ref = xref
            #else, is this cross reference a pointer from a (const) method list?
            elif objc_const and xref.frm >= objc_const[
                    0] and xref.frm < objc_const[1]:
                const_ref_count += 1

        return (is_msg_ref, selector_ref, const_ref_count)
Esempio n. 2
0
 def walk_selector_refs(self):
     #sel_ref_va is the address of the selref, which itself is a pointer to the selector string
     #we're looking for cross references *to* the the address of the selref
     #If we find ones we like and replace them with a cross reference to the actual method implementation, rather than the selector
     for xref in XrefsTo(self.sel_ref_va):
         if print_insn_mnem(xref.frm) == self.CALL_MNEMONIC:
             continue
         #We found a xref *from* somewhere *to* our selref. We need to replace that with a reference
         #To the actual method implementation
         method_xref = self.add_method_xref(xref)
         self.patched_xrefs.append(method_xref)
Esempio n. 3
0
 def eFunc(self, address=None, retAddr=None, args=[]):
     if address == None: address = here()
     func = get_func(address)
     if retAddr == None:
         refs = [ref.frm for ref in XrefsTo(func.start_ea, 0)]
         if len(refs) != 0:
             retAddr = refs[0] + get_item_size(refs[0])
         else:
             print("Please offer the return address.")
             return
     self._emulate(func.start_ea, retAddr, args)
     res = self.curUC.reg_read(self.REG_RES)
     return res
Esempio n. 4
0
    def _get_xref_to_calls(ea):
        """Return a generator to iterate over all function addresses which
        call the given function.

        :param int ea: Start address of the function.
        """
        for xref in XrefsTo(ea):
            if xref.type not in CALL_JUMP_FLAGS:
                continue

            if GetFunctionName(xref.to).startswith('_ZThn'):
                continue

            yield xref.to
Esempio n. 5
0
def find_chain_helper(chain, cfg_whitelist, startaddress, depth):
    xrefs = set()
    for xref in XrefsTo(startaddress, 0):
        for f in Functions(xref.frm, xref.frm):
            xrefs.add(f)
    for xref in xrefs:
        if xref in cfg_whitelist:
            newchain = chain[:]
            newchain.append(maybe_get_name(xref))
            print_chain(newchain)
    if depth <= 1:
        return
    for xref in xrefs:
        newchain = chain[:]
        newchain.append(maybe_get_name(xref))
        find_chain_helper(newchain, cfg_whitelist, xref, depth - 1)
Esempio n. 6
0
 def eFunc(self, target=None, retAddr=None, args=[]):
     if target == None: target = here()
     address = target_to_ea(target)
     func = idaapi.get_func(address)
     if retAddr == None:
         refs = [ref.frm for ref in XrefsTo(func.start_ea, 0)]
         if len(refs) != 0:
             retAddr = refs[0] + get_item_size(refs[0])
         else:
             print("Please offer the return address.")
             return
     func_address = func.start_ea | 1 if self._is_thumb_ea(
         func.start_ea) else func.start_ea
     self._emulate(func_address, retAddr, args)
     res = self.uc.reg_read(self.REG_RES)
     return res
Esempio n. 7
0
    def _listRefsTo(self, start: int) -> List[Tuple[int, int]]:
        """Make a list of all the references to the given function.
        Args:
          func : The function references to which we are searching.
          start : The function's start offset.

        Returns:
          list : A list of tuples.
            Each tuple represents: the offsets:
            0 : the offset from where the given function was referenced by the foreign function
            1 : the function's start address
        """

        func_refs_to = XrefsTo(start, 1)
        refs_list = []
        for ref in func_refs_to:
            if idc.print_insn_mnem(ref.frm) == "":
                continue
            refs_list.append((ref.frm, start))
        return refs_list
Esempio n. 8
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)
Esempio n. 9
0
    def _add_function_strings(self):
        """Add the strings to the functions that use them."""
        for ea in self.strings.keys():
            references = tuple(XrefsTo(ea))
            del_count = 0
            for xref in references:
                func_ea = GetFunctionAttr(xref.frm, FUNCATTR_START)

                # Is the reference not a function?
                # Actually, we should compare func_ea == -1, but this seems to
                # be buggy. The -1 is probably returned as an unsigned int,
                # which results in 4294967295.
                if func_ea == 4294967295:
                    del_count += 1
                    continue

                self.get_function(func_ea).add_string(ea)

            # No need to keep strings without a reference or without a
            # reference to a function.
            if del_count == len(references):
                del self.strings[ea]
Esempio n. 10
0
    def export(self, vtables):
        """
        @vtables: List of tuples with vtable information
                  [(ins_addr, vtable), ... ]
                  
        There is a small mistake. Some .data references will be tagged as being 
        vtables. This is due to the way we detect them on pin. In IDA pro it should
        be easy to mark just only the ones that refer to .text but I could not find
        a way to get that information from idapython.
        """

        # We build a dictionary with the ins addr referencing the vtable as the key
        dict_ = {}
        for vtable in vtables:
            # Add all the vtable references found while tracing to the set
            dict_.setdefault(vtable[0], set()).add(vtable[1])

        for (key, val) in dict_.iteritems():
            prev_comment = idc.GetCommentEx(vtable[0], False)

            # Check if we already have commented this line. This will avoid duplicating info.
            if not prev_comment or "VTables found:" in prev_comment:
                prev_comment = "VTables found:\n"

            prev_comment += "\n".join(map(lambda x: "0x%.8x" % x, val))

            # vtable[0] == instruction address
            idc.MakeComm(key, prev_comment)

            # Check if we already have a cross reference
            for v in val:
                if key in [ref.frm for ref in XrefsTo(v, 0)]:
                    continue

                # Add a data reference
                if add_dref(key, v, dr_R) != True:
                    idaapi.msg(
                        "Could not create cross reference from %x to %x\n" %
                        (key, v))
    def _get_iOS6_syscall_addrs(self):
        """
        currently always returns True

        bottom of syscall table

        __DATA:__const:802F2A28                 sysent <2, 0, 0, 0x801CED69, 0, 0, _SYSCALL_RET_INT_T, 8, 0>
        __DATA:__const:802F2A40 unk_802F2A40    DCB    5                ; DATA XREF: sub_801CF720+40o
        __DATA:__const:802F2A40                                         ; sub_801CF720+48o
        __DATA:__const:802F2A41                 DCB    0
        __DATA:__const:802F2A42                 DCB    0
        __DATA:__const:802F2A43                 DCB    0
        __DATA:__const:802F2A44                 DCD sub_801D0FC0+1
        __DATA:__const:802F2A48                 DCD sub_801D0FC4+1
        __DATA:__const:802F2A4C                 DCD sub_801D0FC8+1
        __DATA:__const:802F2A50                 DCD sub_801D0FCC+1
        __DATA:__const:802F2A54                 DCD sub_801D1188+1
        __DATA:__const:802F2A58                 DCD sub_801D119C+1
        __DATA:__const:802F2A5C                 DCD sub_801D1230+1
        """
        curr_addr = self.sysent

        while curr_addr < self.data_seg.endEA:
            if len(list(XrefsTo(curr_addr,
                                0))) > 0 and curr_addr != self.sysent:
                break

            if Dword(curr_addr + 0x10) > 10:  # curr max return type is 7
                break

            addr = Dword(curr_addr + 4)

            # should add check verify target in text segment
            self.syscall_addrs.append(addr)
            curr_addr += 0x18

        return True
    def _lookup_syscall_names_from_kernel(self):
        """
        returns syscall list
        6.1.2 kernel has syscall names as strings in __TEXT:__cstring segment
        """
        syscall_ea = LocByName(string_prefix + "Syscall")

        if syscall_ea < self.cstring_seg.startEA or syscall_ea > self.cstring_seg.endEA:
            return False

        seg_start_ea = self.cstring_seg.startEA
        seg_end_ea = self.cstring_seg.endEA

        xrefs = list(XrefsTo(syscall_ea, 0))
        if len(xrefs) != 1:
            return False

        xref = xrefs[0]
        addr = xref.frm

        while addr != BADADDR:
            t = Dword(addr)

            # test if in __TEXT:__cstring segment
            if t < seg_start_ea or t > seg_end_ea:
                break

            # get Name, check for str
            tname = Name(t)
            if tname.find(string_prefix) == 0:
                str_content = GetString(t)
                self.syscall_names.append(str_content)

            addr += 4

        return True
Esempio n. 13
0
    def export(self, resolved_branches):
        dict_ = {}
        for r in resolved_branches:
            dict_.setdefault(r[0], set()).add(r[1])

        for key, val in dict_.iteritems():
            prev_comment = idc.GetCommentEx(key, False)

            if not prev_comment or "Resolved:" in prev_comment:
                prev_comment = "Resolved:\n"

            for v in val:
                prev_comment += "%s : %.8x\n" % (GetAddressName(v), v)

                # Check if we already have a cross reference
                if key in [ref.frm for ref in XrefsTo(v, 0)]:
                    continue

                if AddCodeXref(key, v, fl_CN) != True:
                    idaapi.msg(
                        "Could not create cross reference from %x to %x\n" %
                        (key, v))

            idc.MakeComm(key, prev_comment)
from idc import GetFunctionName, SegName, get_type
from sys import exit

current_function = GetFunctionName(get_screen_ea())
print('Will generate forwards for all calls from {}'.format(current_function))

called_functions = []
function_name_to_address = {}

for segea in Segments():
    if SegName(segea) != '.text':
        continue
    for funcea in Functions(segea, SegEnd(segea)):
        called_functions.extend(
            filter(lambda x: GetFunctionName(x.frm) == current_function,
                   XrefsTo(funcea)))
        function_name_to_address[GetFunctionName(funcea)] = funcea

called_functions = map(lambda x: GetFunctionName(x.to), called_functions)
called_functions = list(set(called_functions))
print('It calls {} functions!'.format(len(called_functions)))


def forwarder_generator(prototype, address):

    until_arguments = prototype[:prototype.find('(')].split(' ')
    arguments = prototype[prototype.find('(') + 1:-1]

    pointer_levels = ''

    for i, _ in enumerate(until_arguments):