def getSize(self, withPool=False):
        """
        Computes the size of the function the first time this is called, and caches that computation for later
        Parsed Comment commands:
            <endpool> specifies the last element in the pool. That element's size is included in the pool.
                      to specify a function has no pool at all, put the comment command at its last instruction.
        :param withPool: (bool) somewhat of a heuristic. Computes the pool size as simply the amount of bytes since
                         the function's code portion finished (endEA) until a new code head is detected
        :return:  Returns the size of the Function in bytes: EndEA - StartEA (if no pool selected, otherwise + pool)
        """
        if not withPool: return self.func.end_ea - self.func.start_ea
        head = self.func.end_ea

        # check if the function is set to have no pool
        instSize = self.isThumb() and 2 or 4
        endCmt = idc.Comment(self.func.end_ea - instSize)
        if endCmt and '<endpool>' in endCmt:
            return self.func.end_ea - self.func.start_ea

        while not idc.isCode(idc.GetFlags(head)):
            # manual pool computation, trust and assume that this is the last element in the pool!
            if idc.Comment(head) and '<endpool>' in idc.Comment(head):
                head += idc.get_item_size(head)
                break
            # advance to next data element
            head += idc.get_item_size(head)

        return head - self.func.start_ea
示例#2
0
    def extract_info_from_IDA(self):
        prots = ida_bytes.get_qword(self.ea + 0x10)
        if prots:
            count = ida_bytes.get_qword(prots)
            entrysize = 0x8
            p_ea = prots + 8
            for i in range(count):
                proto_ea = idc.get_qword(p_ea)
                self.prots.append(proto_ea)
                p_ea += entrysize

        type_info = ida_bytes.get_qword(self.ea + 0x48)
        for idx in range(0, 4):
            # 0: inst_meths
            # 1: class_meths
            # 2: opt_inst_meths
            # 3: opt_class_meths
            meth_list = ida_bytes.get_qword(self.ea + 0x18 + idx * 8)
            if meth_list:
                entrysize = ida_bytes.get_dword(meth_list)
                count = ida_bytes.get_dword(meth_list + 4)
                ea = meth_list + 8
                for i in range(0, count):
                    sel = idc.get_bytes(idc.Qword(ea), idc.get_item_size(idc.Qword(ea)) - 1)
                    meth_type = idc.get_bytes(idc.Qword(type_info), idc.get_item_size(idc.Qword(type_info)) - 1)
                    self.meths[sel] = meth_type
                    ea += entrysize
                    type_info += 8
示例#3
0
def lazy_read_selection():
    # HTC - Ignore the byte at end address
    sel, start, end = idaapi.read_range_selection(None)
    if not sel:
        if idc.get_item_size(idc.get_screen_ea()):
            start = idc.get_screen_ea()
            end = start + idc.get_item_size(start)
            sel = True

    if not sel:
        start = idaapi.BADADDR
        end = idaapi.BADADDR
    else:
        rFrm = RangeForm(start, end)
        rFrm.Compile()
        ok = rFrm.Execute()
        if ok == 1:
            # OK
            start = rFrm.intStartEA.value
            end = start + rFrm.intSize.value
        else:
            # Cancel
            sel = False

        rFrm.Free()

    # Ensure we have at least one byte
    if end <= start:
        sel = False

    return sel, start, end
示例#4
0
 def handle_call(self, state):
     """Updates the state of the stack string finding based on a call instruction"""
     stack_pointer = idc.get_spd(state.ea)
     next_ea = state.ea + idc.get_item_size(state.ea)
     stack_pointer_delta = idc.get_sp_delta(next_ea)
     if stack_pointer is not None and stack_pointer_delta is not None:
         next_reg = tracing.get_reg_fam(idc.print_operand(next_ea, POS_FIRST))
         # Caller cleanup handling, vulnerable to instruction reordering though.
         if next_reg and "esp" in next_reg and "add" in idc.print_insn_mnem(next_ea).lower():
             stack_pointer_delta += idc.get_sp_delta(next_ea + idc.get_item_size(next_ea))
         for index in range(stack_pointer, stack_pointer + stack_pointer_delta):
             if index in state.stack:
                 del state.stack[index]
示例#5
0
def lazy_read_selection():
    # HTC - Ignore the byte at end address
    sel, start, end = idaapi.read_range_selection(None)
    if not sel:
        if idc.get_item_size(idc.get_screen_ea()):
            start = idc.get_screen_ea()
            end = start + idc.get_item_size(start)
            sel = True
    if not sel:
        start = idaapi.BADADDR
        end = idaapi.BADADDR

    return sel, start, end
示例#6
0
    def _getDataDisasm(self):
        """
        You cannot get array data using getdisasm. The disassembly has to be extracted differently.
        This identifies the data in question, and gets its disassembly
        :return: the disasssembly of the data item
        """
        # First, do the easy cases that just work with GetDisasm
        flags = idc.GetFlags(self.ea)
        # TODO: change this so it accounts for arrays also
        if idc.is_enum0(flags):
            return self._filterComments(idc.GetDisasm(self.ea))
        if idc.is_data(flags) and (
                idc.is_byte(flags) and idc.get_item_size(self.ea) == 1
                or idc.is_word(flags) and idc.get_item_size(self.ea) == 2
                or idc.is_dword(flags) and idc.get_item_size(self.ea) == 4):
            # normal case where an int is not misread as a reference
            content = self.getContent()
            if self.getXRefsFrom()[1] and self.isPointer(content):
                disasm = idc.GetDisasm(self.ea)
                contentData = Data(content)
                # If it's a struct member, replace it with its hex, but keep the information
                if '.' in disasm and (';' not in disasm
                                      or '.' in disasm[:disasm.index(';')]):
                    disasm = 'DCD %s+0x%X // %s' % (contentData.getName(),
                                                    content - contentData.ea,
                                                    disasm[len('DCD '):])

            elif ida_bytes.is_manual(flags, 0):
                # Manual forms put in IDA, just grab it. (This is for cases where computations are applied to data)
                disasm = idc.GetDisasm(self.ea)
            else:
                # build the disassembly: this is for none-pointer symbols found in IDA (ex: word_0)
                if idc.is_byte(flags): op = 'DCB'
                elif idc.is_word(flags): op = 'DCW'
                else: op = 'DCD'
                disasm = op + ' ' + '0x%X' % content

            return self._filterComments(disasm)
        else:  # The weird case... an array. I don't know why it's weird. IDA doesn't like it!
            # It is assumed this is an array, but the type is unknown. Imply type based on disasm of first line!
            # analysis on the array is based on the very first line
            disasm = idc.GetDisasm(self.ea)
            if ';' in disasm:
                disasm = disasm[:disasm.index(';')]
            firstLineSplitDisasm = list(filter(None, re.split('[ ,]', disasm)))
            dataType = firstLineSplitDisasm[0]

            return self._getArrDisasm(len(firstLineSplitDisasm) - 1, dataType)
示例#7
0
def findMostUsedLabels(start_ea, end_ea, count, notModified=False, disp=True):
    # type: (int, int, int, bool, bool) -> list[int]
    """
    Scans through all labels in the given range and counts the ones with the highest amount of references
    :param start_ea: start of the range
    :param end_ea: end of the range
    :param count:
    :param notModified:
    :param disp:
    :return:
    """
    xrefs = []

    if count <= 0: count = 1
    for i in range(count):
        xrefs.append((0, 0))

    ea = start_ea
    while ea < end_ea:
        if not idc.get_name(ea):
            ea += idc.get_item_size(ea)
            continue
        if notModified:
            name = Data.Data(ea).getName()
            if not ('_' in name and name[name.rindex('_'):] == ('_%X' % ea)):
                continue

        currXrefs = Data.Data(ea).getXRefsTo()
        numXrefs = len(currXrefs[0]) + len(currXrefs[1])

        # add if more than least in the list and sort
        if numXrefs > xrefs[0][1]:
            xrefs[0] = (ea, numXrefs)
            xrefs = sorted(xrefs, key=lambda tup: tup[1])

        ea += idc.get_item_size(ea)

    # reverse to display most common first
    xrefs = sorted(xrefs, key=lambda tup: tup[1], reverse=True)

    if disp:
        for ea, xrefCount in xrefs:
            print('%07x <%s>: %d' % (ea, Data.Data(ea).getName(), xrefCount))

    output = []
    for ea, xrefCount in xrefs:
        output.append(ea)
    return output
示例#8
0
def make_array(ea, size):
  if ea != idc.BADADDR and ea != 0:
    flags = idc.get_full_flags(ea)
    if not idc.isByte(flags) or idc.get_item_size(ea) != 1:
      idc.del_items(ea, idc.DOUNK_SIMPLE, 1)
      ida_bytes.create_data(ea, ida_bytes.FF_BYTE, 1, ida_idaapi.BADADDR)
    idc.make_array(ea, size)
示例#9
0
def find_binary_instruction_start(
    search_start_location,
    search_direction,
    target,
    min_location=idc.get_inf_attr(idc.INF_MIN_EA),
    max_location=idc.get_inf_attr(idc.INF_MAX_EA)):
    """
    Description:
        Given a starting location, target, and direction, find an instruction starting with the target bytes.

    Input:
        search_start_location - The EA to start searching at
        search_direction - either idc.SEARCH_UP or idc.SEARCH_DOWN
        target - The target as space separated bytes (i.e. '55' for 'push ebp')
        min_location - The minimum EA to accept results for (default: idc.get_inf_attr(idc.INF_MIN_EA))
        max_location - The maximum EA to accept results for (default: idc.get_inf_attr(idc.INF_MAX_EA))

    Output:
        Returns the first matching location if found, otherwise idc.BADADDR
    """
    target = target.upper()
    while search_start_location < max_location:
        ea = idc.find_binary(search_start_location, search_direction, target)
        if (min_location <= ea < max_location
                and ea == idc.get_item_head(ea) and idc.get_bytes(
                    ea,
                    idc.get_item_size(ea)).encode('hex').upper().startswith(
                        target.replace(' ', ''))):
            return ea
        else:
            search_start_location = ea + (1 if search_direction
                                          == idc.SEARCH_DOWN else -1)
    return idc.BADADDR
示例#10
0
        def do_unpatch_call(va_callsite):
            size = idc.get_item_size(va_callsite)
            ida_xref.del_cref(va_callsite, fva_stub, 0)
            cmt = idc.get_cmt(va_callsite, 0)

            newcmt = cmt

            # Remove automated comments
            if newcmt.startswith(g_patched_call_cmt):
                newcmt = newcmt[newcmt.find('\n') + 1:]
                if newcmt.find('\n') == -1:
                    newcmt = ''
                else:
                    newcmt = newcmt[newcmt.find('\n') + 1:]
                if newcmt.startswith(g_cmt_pointed):
                    if newcmt.find('\n') == -1:
                        newcmt = ''
                    else:
                        newcmt = newcmt[newcmt.find('\n') + 1:]

            if newcmt != cmt:
                idc.set_cmt(va_callsite, newcmt, 0)

            if idc.get_operand_type(va_callsite, 0) == ida_ua.o_mem:
                patch_import(va_callsite, idc.BADADDR)
            elif idc.get_operand_type(va_callsite, 0) == ida_ua.o_reg:
                va_imp = self._get_imp_for_register_call(va_callsite)
                if va_imp:
                    patch_pointer_width(va_imp, idc.BADADDR)
            else:
                revert_patch(va_callsite, size)
示例#11
0
    def finish_populating_widget_popup(self, form, popup):
        form_type = idaapi.get_widget_type(form)
        if form_type == idaapi.BWN_DISASM or form_type == idaapi.BWN_DUMP:
            idaapi.attach_action_to_popup(form, popup, ACTION_PASTE, None)
            idaapi.attach_action_to_popup(form, popup, ACTION_DUMPER, None)
            idaapi.attach_action_to_popup(form, popup, ACTION_JMP, None)
            t0, t1, view = idaapi.twinpos_t(), idaapi.twinpos_t(
            ), idaapi.get_current_viewer()
            if idaapi.read_selection(
                    view, t0,
                    t1) or idc.get_item_size(idc.get_screen_ea()) > 1:
                idaapi.attach_action_to_popup(form, popup, ACTION_XORDATA,
                                              None)
                idaapi.attach_action_to_popup(form, popup, ACTION_FILLNOP,
                                              None)
                for action in ACTION_CONVERT:
                    idaapi.attach_action_to_popup(form, popup, action,
                                                  "Convert/")

        if form_type == idaapi.BWN_DISASM and (ARCH, BITS) in [
            (idaapi.PLFM_386, 32),
            (idaapi.PLFM_386, 64),
            (idaapi.PLFM_ARM, 32),
        ]:
            idaapi.attach_action_to_popup(form, popup, ACTION_SCANVUL, None)
示例#12
0
	def set_jit_info(self, method_id, start):

		end = self.get_func_end(start)

		if (end < start or end - start > self.jit_max_size):
			return

		method = next((x for x in self.as3dump if x["id"] == method_id), None)

		if (method is None):
			return

		stackvars = self.get_stack_vars(start, end)
		save_eip = self.get_save_eip(method, stackvars)

		ea = start
		while (ea < end):
	
			if ("ebp" in idc.print_operand(ea, 0) and idc.get_operand_type(ea, 1) == idc.o_imm):
	
				op0 = idc.get_operand_value(ea, 0)
				op1 = idc.get_operand_value(ea, 1)
	
				if (op0 == save_eip):
					idc.set_cmt(ea, method["instructions"][op1], 0)
		
			ea += idc.get_item_size(ea)
示例#13
0
def make_array(ea, size):
  if ea != idc.BADADDR and ea != 0:
    flags = idc.get_full_flags(ea)
    if not idc.isByte(flags) or idc.get_item_size(ea) != 1:
      idc.del_items(ea, idc.DOUNK_SIMPLE, 1)
      idc.MakeByte(ea)
    idc.MakeArray(ea, size)
示例#14
0
def get_data_symbols():
    idata_seg_selector = idc.selector_by_name(".bss")
    idata_seg_startea = idc.get_segm_by_sel(idata_seg_selector)
    idata_seg_endea = idc.get_segm_end(idata_seg_startea)
    for seg_ea in range(idata_seg_startea, idata_seg_endea):
        if idc.get_name(seg_ea):
            address = format(seg_ea, 'x')
            name = ".global"+"_"+idc.get_name(seg_ea)
            size = idc.get_item_size(seg_ea)
            dtype = ida_bytes.get_data_elsize(seg_ea, idc.get_full_flags(seg_ea))
            if size == dtype == 8:
                ownertype = "pointer"
            elif size == dtype != 8:
                ownertype = "scalar"
            elif size > dtype:
                ownertype = "array"
            else:
                continue
            for xref in idautils.XrefsTo(seg_ea):
                # print(format(xref.frm, 'x'))
                function = idc.get_func_name(xref.frm)
                # print(function)
                if function not in functions:
                    continue
                # print(function)
                if str(function) not in instruction_map:
                    instruction_map[str(function)] = {}
                instruction_map[str(function)][format(xref.frm, 'x')]=name,ownertype
                # print("Found a cross reference {}: from {:x} to variable {}".format(xref, xref.frm, name))
            metadata[".global"].append({"owner":name,"datatype":ownertype, "address":address, "size":size})
示例#15
0
def make_array(ea, size):
    if ea != idc.BADADDR and ea != 0:
        flags = idc.get_full_flags(ea)
        if not idc.isByte(flags) or idc.get_item_size(ea) != 1:
            idc.del_items(ea, idc.DOUNK_SIMPLE, 1)
            idc.MakeByte(ea)
        idc.MakeArray(ea, size)
def guessFuncSig(func_ea):
    # type: (int) -> (list[str], list[str])
    """
    Guesses the signature of the current function based on the input registers it uses (R0-R3) and
    based on the output registers it may return. (most likely R0, but sometimes multiple registers are returned)
    It also checks for whether the zero flag have been written to by the function without being used, then it would
    return the zero flag.
    :param func_ea: the linear address of the function to analyze
    :return: the list of types for the input parameters, and for the returns.
    'zf' can be included, in the return types list.
    """
    # input register parameters -- r0 through r3. If they are identified as an input, this will store
    # a string of their type. (States -- None: No param found yet. '': Parameter. But Unknown Type.
    paramTypes = [None, None, None, None]
    retType = None
    zf = False
    # flags
    updatedRegs = 0b0000  # if the register is updated, its flag is set
    # make sure to recognize push/pop like patterns. A register can be saved to be used later.
    savedRegs = 0b0000
    # This flag is cleared whenever R0 is updated.
    # It is set whenever R0 is used. This indicated whether the return is used or not
    usedRet = False
    # the returns of calls are remembered since their type can match with the current function
    callRets = None
    func = Function.Function(func_ea)

    ea = func.func_ea
    while ea < func.func_ea + func.getSize():
        insn = Instruction.Insn(ea)
        if insn.size != 0:
            # parse destination and source registers, if any
            if insn.ops[0].type == idaapi.o_reg:
                destReg = insn.ops[0].reg
                # now parse all source registers
                sourceRegisters = insn.getSourceRegisters()
                # if a destReg is R0~R3, set its flag
                raise (NotImplemented())
                # update return status to know whether the register is used after being set at the end of the function

            # traverse function calls if parameters weren't identified yet
            if insn.ops[0].type in [idaapi.o_far, idaapi.o_near
                                    ] and None in paramTypes:
                callParams, callRets = guessFuncSig(insn.ops[0].addr)
                # deduce input parameters for this function from input parameters for the called function
                for i in range(len(callParams)):
                    if not updatedRegs & i:
                        # register is passed in as input to callee! Register it as an input of this function too!
                        raise (NotImplemented())

            # handle the push/pop register saving pattern
            if insn.itype == idaapi.NN_push:
                raise (NotImplemented())
            if insn.itype == idaapi.NN_pop:
                raise (NotImplemented())

            ea += insn.size
        else:
            ea += idc.get_item_size(ea)
示例#17
0
def handle_test(ea, state):
    """
        If a test of a register against itself occurs and the next instruction is a jnz,
        then the register can be set to zero (code is followed linearly, jumps are ignored),
        unless the next instruction is a jmp.

        :param ea: instruction location
        :param state: the current TraceState
    """
    if idc.get_operand_type(ea, POS_FIRST) == idc.o_reg and idc.get_operand_type(ea, POS_SECOND) == idc.o_reg:
        op1 = get_opnd_replacement(ea, POS_FIRST)
        op2 = get_opnd_replacement(ea, POS_SECOND)
        next_ea = ea + idc.get_item_size(ea)
        if op1 == op2 and idc.print_insn_mnem(next_ea) == 'jnz':
            next_ea += idc.get_item_size(next_ea)
            if not idc.print_insn_mnem(next_ea).startswith('j'):
                state.set_reg_value(op1, 0, ea)
示例#18
0
 def getSize(self, withPool=False):
     """
     Computes the size of the file the first time this is called, and caches that computation for later
     :param withPool: (bool) If end_ea is a function, compute its size including its pool if it has any
     :return:  Returns the size of the file in bytes: EndEA + itemSize - StartEA
     """
     if isFunction(self.end_ea):
         return self.end_ea + Function(self.end_ea).getSize(withPool=withPool) - self.start_ea
     return (self.end_ea + idc.get_item_size(self.end_ea) - self.start_ea)
示例#19
0
文件: nop.py 项目: clayne/idapython
def nop():
    """Nops-out the current instruction and advance the cursor to the next instruction."""
    ea = idaapi.get_screen_ea()
    num_bytes = idc.get_item_size(ea)
    for i in range(num_bytes):
        ida_bytes.patch_byte(ea, 0x90)
        ea += 1
    ida_kernwin.refresh_idaview_anyway()
    ida_kernwin.jumpto(ea)
示例#20
0
    def __get_instruction_bytes_wildcarded(pattern, addr, instr_type, op1_type,
                                           op2_type):
        """Replaces bytes related to memory addresses with wildcards.

    TODO: To be replaced by ida_idp.ph_calcrel()

    Args:
      pattern: current buffer containing the bytes of the current instruction.
      addr: the address of the current instruction to be wildcarded
      instr_type: type of the current instruction
      op1_type: type of the first operand
      op2_type: type of the second operand

    Returns:
      String: hex-encoded representation of the bytes obtained at addr where
              all the operands that refers to memmory addresses are wildcarded.
    """

        type_calls = frozenset(
            [idaapi.NN_call, idaapi.NN_callfi, idaapi.NN_callni])
        type_jumps = frozenset(
            [idaapi.NN_jmp, idaapi.NN_jmpfi, idaapi.NN_jmpni])

        inst_prefix = binascii.hexlify(idc.get_bytes(addr, 1)).decode('utf-8')
        drefs = [x for x in idautils.DataRefsFrom(addr)]

        logging.debug('[VTGREP] Wildcarding: %s',
                      idc.generate_disasm_line(addr, 0))

        # Known 2 bytes opcodes
        if inst_prefix in ('0f', 'f2', 'f3'):
            pattern = binascii.hexlify(idc.get_bytes(addr, 2)).decode('utf-8')
            inst_num_bytes = 2

        # CALLs or JUMPs using 2 bytes opcodes
        elif inst_prefix == 'ff' and (instr_type in type_jumps
                                      or instr_type in type_calls):

            pattern = binascii.hexlify(idc.get_bytes(addr, 2)).decode('utf-8')
            inst_num_bytes = 2

        # A PUSH instruction using an inmediate value (mem offset)
        elif (inst_prefix == 'ff' and drefs
              and (op1_type == idaapi.o_imm or op2_type == idaapi.o_imm)):

            pattern = binascii.hexlify(idc.get_bytes(addr, 2)).decode('utf-8')
            inst_num_bytes = 2

        # No prefix is used
        else:
            pattern = inst_prefix
            inst_num_bytes = 1

        pattern += ' ' + '??' * (idc.get_item_size(addr) -
                                 inst_num_bytes) + ' '
        return pattern
示例#21
0
def find_function_ends_near(location, end_mnem_bytes=None):
    """
    Description:
        Identifies the nearest possible function ends before the next function or Align for each end mnem.

    Input:
        location - The EA to search after
        end_mnem_bytes - Try to end functions on a particular instruction
                         Instructions are entered as space separated bytes (i.e. 'C2' for 'retn')
                         The specified pattern will be used first, then the defaults will be used
                         If no pattern is specified, the defaults will be used, which prefers 'retn'

    Output:
        ends - A list of function end EAs sorted: end_mnem_bytes, retn, jmp
    """
    # foreach target bytes:
    #  step instructions down
    #  if instruction matches the target bytes, add to output list
    #   then move on to the next target bytes
    #  if we hit a function or an align, quit
    # return ends in the order
    #  end_nmem_bytes
    #  retn
    #  jmp
    #  others, sorted ascending

    max_location = None
    ea = location
    while max_location is None:
        ea = idc.next_head(ea)
        if idaapi.get_func(ea) or idc.is_align(idc.get_full_flags(ea)):
            max_location = ea
        elif ea == idc.BADADDR:
            max_location = idaapi.getseg(location).end_ea
    max_location = min(max_location, idaapi.getseg(location).end_ea)

    targets = ['C2', 'C3', 'E9', 'EA', 'EB']
    if end_mnem_bytes:
        targets.insert(0, end_mnem_bytes)

    ends = {}
    for target in targets:
        ea = find_binary_instruction_start(location,
                                           idc.SEARCH_DOWN,
                                           target,
                                           max_location=max_location)
        if ea <= max_location:
            ends[target] = ea

    return [
        end + idc.get_item_size(end) for end in (([
            ends.get(end_mnem_bytes, None),
            ends.get('C2', None),
            ends.get('C3', None)
        ]) + sorted(ends.get(target, None) for target in targets[-3:])) if end
    ]
示例#22
0
 def __init__(self, ea):
     # type: (int) -> None
     """
     :param ea: effective address of the data item
     :raise InvalidDataException: if the current item is not data (isCode)
     """
     # determine actual EA of the dataitem by analyzing its size. Going back in EA should increase the size
     # if we're in the middle of an array, or of the item. If it remains unchanged, or decreases, then we exited
     # the item.
     size = 0
     ranLoop = False
     while idc.get_item_size(ea) > size:
         ranLoop = True
         size = idc.get_item_size(ea)
         ea -= 1
     if ranLoop:
         # we just hit a failure condition, so the previous one is the correct one!
         ea += 1
     self.ea = ea
示例#23
0
def parse_vtable(ea, typename):
    os = get_os()
    if os == OS_Linux:
        ea += 8
    funcs = []

    while ea != idc.BADADDR:
        eatemp = ea
        offs = idc.get_wide_dword(ea)
        #		if ida_bytes.is_unknown(ida_bytes.get_full_flags(ea)):
        #			break

        size = idc.get_item_size(
            ea
        )  # This is bad abd abadbadbadbabdbabdad but there's no other choice here
        if size != 4:
            # This looks like it might be a bug with IDA
            # Random points of a vtable are getting turned into unknown data
            if size != 1:
                break

            s = "".join([
                "%02x" % idc.get_wide_byte(ea + i) for i in range(3, -1, -1)
            ])  #.replace("0x", "")
            if not s.lower().startswith("ffff"):
                ea = ida_bytes.next_not_tail(ea)
                continue

            offs = int(s, 16)
            ea += 3

        name = idc.get_name(offs, ida_name.GN_VISIBLE)
        if name:
            if os == OS_Linux:
                if not (name.startswith("_Z") or
                        name.startswith("__cxa")) or name.startswith("_ZTV"):
                    break  # If we've exceeded past this vtable
            elif name.startswith("??"):
                break
        else:
            if os == OS_Win:
                break

            # dd -offsettothis
            # This is even worseworsoewewrosorooese
            s = "%02x" % offs
            if not s.lower().startswith("ffff"):
                ea = ida_bytes.next_not_tail(ea)
                continue

            name = (1 << 32) - int(offs)
        funcs.append(name)

        ea = ida_bytes.next_not_tail(ea)
    return funcs, eatemp
示例#24
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!')
示例#25
0
def _emit_fnbytes(emit_instr_cb, header, footer, indent, fva=None, warn=True):
    """Emit function bytes in a format defined by the callback and
    headers/footers provided.

    Warns if any instruction operands are not consistent with
    position-independent code, in which case the user may need to templatize
    the position-dependent portions.
    """
    fva = fva or idc.here()
    fva = idc.get_func_attr(fva, idc.FUNCATTR_START)
    va_end = idc.get_func_attr(fva, idc.FUNCATTR_END)

    # Operand types observed in position-independent code:
    optypes_position_independent = set([
        ida_ua.o_reg,  # 1: General Register (al,ax,es,ds...)
        ida_ua.o_phrase,  # 3: Base + Index
        ida_ua.o_displ,  # 4: Base + Index + Displacement
        ida_ua.o_imm,  # 5: Immediate
        ida_ua.o_near,  # 7: Immediate Near Address
    ])

    # Notably missing because I want to note and handle these if/as they are
    # encountered:
    # ida_ua.o_idpspec0 = 8: FPP register
    # ida_ua.o_idpspec1 = 9: 386 control register
    # ida_ua.o_idpspec2 = 10: 386 debug register
    # ida_ua.o_idpspec3 = 11: 386 trace register

    va = fva
    nm = idc.get_name(fva)
    optypes_found = set()
    s = header.format(name=nm)
    while va not in (va_end, idc.BADADDR):
        size = idc.get_item_size(va)
        the_bytes = idc.get_bytes(va, size)

        for i in range(0, 8):
            optype = idc.get_operand_type(va, i)
            if optype:
                optypes_found.add(optype)

        s += indent + emit_instr_cb(va, the_bytes, size)
        va = idc.next_head(va)
    s += footer

    position_dependent = optypes_found - optypes_position_independent
    if position_dependent:
        msg = ('This code may have position-dependent operands (optype %s)' %
               (', '.join([str(o) for o in position_dependent])))
        if warn:
            Warning(msg)
        else:
            logger.warn(msg)

    return s
示例#26
0
    def extract_info_from_IDA(self):
        for xref in idautils.XrefsTo(self.ea):
            frm = xref.frm
            if idc.SegName(frm) == '__objc_classrefs':
                self.classref = frm
            if idc.SegName(frm) == '__objc_superrefs':
                self.superref = frm

        base_ivars = ida_bytes.get_qword(self.info + 0x30)
        if base_ivars and idc.SegName(base_ivars) == '__objc_const':
            entrysize = ida_bytes.get_dword(base_ivars)
            count = ida_bytes.get_dword(base_ivars + 4)
            ea = base_ivars + 8
            for i in range(count):
                offset = ida_bytes.get_dword(idc.get_qword(ea))
                _type = idc.get_bytes(idc.Qword(ea + 0X10), idc.get_item_size(idc.Qword(ea + 0X10)) - 1)
                _name = idc.get_bytes(idc.Qword(ea + 0X08), idc.get_item_size(idc.Qword(ea + 0X08)) - 1)
                # self.ivars[offset] = _type
                self.ivars[_name] = _type
                ea += entrysize

        base_props = ida_bytes.get_qword(self.info + 0x40)
        if base_props and idc.SegName(base_props) == '__objc_const':
            entrysize = ida_bytes.get_dword(base_props)
            count = ida_bytes.get_dword(base_props + 4)
            ea = base_props + 8
            for i in range(count):
                _type = idc.get_bytes(idc.Qword(ea + 0X08), idc.get_item_size(idc.Qword(ea + 0X08)) - 1)
                _name = idc.get_bytes(idc.Qword(ea), idc.get_item_size(idc.Qword(ea)) - 1)
                self.props[_name] = _type
                ea += entrysize

        base_prots = ida_bytes.get_qword(self.info + 0x28)
        if base_prots and idc.SegName(base_prots) == '__objc_const':
            count = ida_bytes.get_qword(base_prots)
            entrysize = 0x8
            p_ea = base_prots + 8
            for i in range(count):
                proto_ea = idc.get_qword(p_ea)
                self.prots.append(proto_ea)
                Protocol.add_implementing_class(proto_ea, self.ea)
                p_ea += entrysize
示例#27
0
    def get_relevant_infos(self, relevant):
        find_start = False
        infos = {}
        h = idautils.Heads(relevant.startEA, relevant.endEA)
        last = None
        for i in h:
            mnem = idc.GetMnem(i)
            if (mnem == "tst.w") or (mnem == "TST.W"):
                find_start = True
                infos["fix_start"] = (i + idc.get_item_size(i))
                # infos["fix_start_inst_len"] =
            elif find_start == True and (mnem.startswith("IT ") or mnem.startswith("it ")):
                infos["fix_end"] = (i + idc.get_item_size(i) + idc.get_item_size(i + idc.get_item_size(i)))
                infos["conf_type"] = mnem[3:]
                find_start = False

            last = i
        infos["last"] = (last)

        return infos
示例#28
0
 def __init__(self, ea):
     self.ea = ea  # ea: objc_data address
     self.info = ida_bytes.get_qword(ea + 0x20)
     self.superclass = ida_bytes.get_qword(
         ida_bytes.get_qword(ea) + 0x08)  # idc.Name(self.superclass): _OBJC_METACLASS_$_UIView
     self.name = idc.get_bytes(idc.Qword(self.info + 0x18), idc.get_item_size(idc.Qword(self.info + 0x18)) - 1)
     self.classref = None
     self.superref = None
     self.prots = []
     self.ivars = dict()
     self.props = dict()
示例#29
0
    def finish_populating_widget_popup(self, form, popup):
        form_type = idaapi.get_widget_type(form)

        if form_type == idaapi.BWN_DISASM or form_type == idaapi.BWN_DUMP:
            t0, t1, view = idaapi.twinpos_t(), idaapi.twinpos_t(
            ), idaapi.get_current_viewer()
            if idaapi.read_selection(view, t0, t1) \
                    or idc.get_item_size(idc.get_screen_ea()) > 1:
                idaapi.attach_action_to_popup(form, popup, GOLANG_FUNC, None)
                idaapi.attach_action_to_popup(form, popup, GOLANG_STRING, None)
                idaapi.attach_action_to_popup(form, popup, RENAME_POINTER,
                                              None)
示例#30
0
 def is_method_a_getter(self, sel, f=None):
     base_props = ida_bytes.get_qword(self.info + 0x40)
     if not base_props:
         return False
     entrysize = ida_bytes.get_dword(base_props)
     count = ida_bytes.get_dword(base_props + 4)
     p_ea = base_props + 8
     for i in range(count):
         p_name = idc.get_bytes(idc.Qword(p_ea), idc.get_item_size(idc.Qword(p_ea)) - 1)
         if p_name == sel:
             return True
         p_ea += entrysize
     return False
示例#31
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
示例#32
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
示例#33
0
def _stop_looking_for_xrefs(ea):
  """This is a heuristic to decide whether or not we should stop looking for
  cross-references. It is relevant to IDA structs, where IDA will treat structs
  and everything in them as one single 'thing', and so all xrefs embedded within
  a struct will actually be associated with the first EA of the struct. So
  if we're in a struct or something like it, and the item size is bigger than
  the address size, then we will assume it's actually in a struct."""
  
  if is_external_segment(ea):
    return False

  if is_code(ea):
    return False

  addr_size = get_address_size_in_bytes()
  item_size = idc.get_item_size(ea)
  return item_size > addr_size
示例#34
0
	def get_stack_vars(self, start, end):

		stackvars = {}
	
		ea = start
		while (ea < end):
	
			if ("ebp" in idc.print_operand(ea, 0) and idc.get_operand_type(ea, 1) == idc.o_imm):
	
				op0 = idc.get_operand_value(ea, 0)
				op1 = idc.get_operand_value(ea, 1)
	
				if (op0 in stackvars):
					stackvars[op0]["values"].append(op1)
				else:
					stackvars[op0] = {"values": [], "hits": 0}
	
			ea += idc.get_item_size(ea)

		return stackvars