Esempio n. 1
0
    def renameDword(self):
        proc_addr = self._import_table.item(self._import_table.currentRow(), 3).text()
        proc_name = str(self._import_table.item(self._import_table.currentRow(), 2).text())
        renamed = 0
        if proc_addr:
            try:
                proc_addr = int(proc_addr, 16)
                proc_bin_str = " ".join([x.encode("hex") for x in struct.pack("<I", proc_addr)])
                next_dword = idc.FindBinary(idc.MinEA(), idc.SEARCH_DOWN|idc.SEARCH_NEXT, proc_bin_str)
                while next_dword != idc.BADADDR:
                    log.debug("Trying to fix-up 0x{:08x}".format(next_dword))
                    # DWORDs can be "inaccessible" for many reasons and it requires "breaking up" the data blobs
                    # and manually fixing them

                    # Reason 1: In a dword array in an unknown section
                    if idc.isUnknown(next_dword):
                        idc.MakeUnkn(next_dword, idc.DOUNK_EXPAND)
                        idc.MakeDword(next_dword)
                    # Reason 2: In a dword array in a data section
                    elif idc.isData(next_dword):
                        hd = idc.ItemHead(next_dword)
                        idc.MakeDword(hd)
                        idc.MakeDword(next_dword)
                    # Reason 3: In a dword array in a code section (validate via "dd <dword>,")
                    elif idc.isCode(next_dword) and idc.GetDisasm(next_dword).startswith("dd "):
                        hd = idc.ItemHead(next_dword)
                        idc.MakeDword(hd)
                        idc.MakeDword(next_dword)

                    # Only perform
                    if idc.Name(next_dword).startswith(("off_", "dword_")) or idc.Name(next_dword) == "":
                        success = idc.MakeNameEx(next_dword, proc_name, idc.SN_NOWARN|idc.SN_NON_AUTO)
                        i = 0
                        new_proc_name = proc_name
                        while not success and i < 10:
                            new_proc_name = "{}{}".format(proc_name, i)
                            success = idc.MakeNameEx(next_dword, new_proc_name, idc.SN_NOWARN|idc.SN_NON_AUTO)
                            i += 1
                        if success:
                            renamed += 1
                            item = self._import_table.item(self._import_table.currentRow(), 5)
                            item.setText("{}, {}".format(str(item.text()), new_proc_name))
                            log.debug("DWORD @ 0x{:08x} now has name {}".format(next_dword, new_proc_name))
                        else:
                            log.error("Unable to auto-rename successfully, terminating search")
                            break
                    else: log.debug("Value at 0x{:08x} does not meet renaming requirements".format(next_dword))
                    next_dword = idc.FindBinary(next_dword+4, idc.SEARCH_DOWN|idc.SEARCH_NEXT, proc_bin_str)
            except Exception, e:
                log.error("Error encountered: {}".format(e))
            log.debug("Renamed {:d} instances of {}".format(renamed, proc_name))
Esempio n. 2
0
def find_binary_instruction_start(search_start_location, search_direction, target, min_location=idc.MinEA(),
                                  max_location=idc.MaxEA()):
    """
    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.MinEA())
        max_location - The maximum EA to accept results for (default: idc.MaxEA())

    Output:
        Returns the first matching location if found, otherwise idc.BADADDR
    """
    target = target.upper()
    while search_start_location < max_location:
        ea = idc.FindBinary(search_start_location, search_direction, target)
        if (min_location <= ea < max_location
                and ea == idc.ItemHead(ea)
                and idaapi.get_many_bytes(ea, idc.ItemSize(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
Esempio n. 3
0
def lines(start=None, end=None, reverse=False, max_steps=None):
    """
    Iterates through instructions within the start address and end addresses.

    :param start: Address of the starting instruction. (starts at beginning if not defined)
    :param end: Address of the end instruction.
    :param reverse: Iterates up if true.
    :param max_steps: If set, iteration will stop after the given number of steps.
    :yields: instructions addresses
    """
    max_ea = idaapi.cvar.inf.maxEA
    min_ea = idaapi.cvar.inf.minEA

    # Normalize start and end addresses.
    if reverse:
        if start is None:
            start = max_ea - 1
        if end is None:
            end = 0
        start = max(start, end)
    else:
        if start is None:
            start = min_ea
        if end is None:
            end = max_ea + 1
        start = min(start, end)

    func = idc.PrevHead if reverse else idc.NextHead
    ea = idc.ItemHead(start)
    while ea != idc.BADADDR:
        yield ea
        ea = func(ea, end)
Esempio n. 4
0
def ida_make_function(location):
    '''
    Description:
        From the first non-function byte, attempt to make a function.

    Input:
        location - The EA at which IDA should attempt to make a function.

    Output:
        True if it succeeded, False otherwise.
    '''
    function_start = location
    ea = location
    while not (idaapi.get_func(ea) or idc.isAlign(idc.GetFlags(ea))):
        function_start = ea
        ea = idc.PrevHead(ea)
    function_start = _un_nop(function_start, idc.NextHead)

    if idc.MakeFunction(function_start):
        last_mnem = idc.GetMnem(
            idc.ItemHead(idaapi.get_func(function_start).endEA - 1))
        if 'ret' not in last_mnem and 'jmp' not in last_mnem:
            idc.DelFunction(function_start)
            append_debug(
                'Created a function at 0x%X, but there wasn\'t a jmp or ret at the end.'
                % function_start)
            return False
        else:
            append_debug('Created a function 0x%X.' % function_start)
            return True
    else:
        return False
Esempio n. 5
0
    def ida_get_disasm(self, address, fixup=False):

        def GetMnem(asm):
            sp = asm.find(' ')
            if (sp == -1):
                return asm
            return asm[:sp]

        if self.check_address(address) != 1:
            # not a valid address
            return ''

        # return if address is in the middle of instruction / data
        if address != idc.ItemHead(address):
            return ''

        asm = self.asm_normalize(idc.GetDisasm(address))
        # for now, only support IDA syntax fixup for Intel CPU
        if not fixup or self.arch != KS_ARCH_X86:
            return asm

        # KS_ARCH_X86 mode
        # rebuild disasm code from IDA
        i = 0
        mnem = GetMnem(asm)
        if mnem == '' or mnem in ('rep', 'repne', 'repe'):
            return asm

        opers = []
        while GetOpType(address, i) > 0 and i < 6:
            t = GetOpType(address, i)
            o = GetOpnd(address, i)

            if t in (idc.o_mem, o_displ):
                parts = list(o.partition(':'))
                if parts[2] == '':
                    parts[2] = parts[0]
                    parts[0] = ''

                if '[' not in parts[2]:
                    parts[2] = '[{}]'.format(parts[2])

                o = ''.join(parts)

                if 'ptr ' not in o:
                    dtyp_name = self.get_op_dtype_name(i)
                    if dtyp_name != None:
                        o = "{} ptr {}".format(dtyp_name, o)

            opers.append(o)
            i += 1

        asm = mnem
        for o in opers:
            if o != '':
                asm = "{} {},".format(asm, o)

        asm = asm.strip(',')
        return asm
def _yara_callback(data):
    '''
    Description:
        Generic yara callback.

    Input:
        As defined by YARA. See YARA's documentation for more info.

    Output:
        A list of tuples: (offset, identifier) where offsets are always item heads
    '''
    if not data['matches']:
        return False

    for datum in data['strings']:
        if FROM_FILE:
            _YARA_MATCHES.append(
                (idc.ItemHead(idaapi.get_fileregion_ea(datum[0])), datum[1]))
        else:
            _YARA_MATCHES.append(
                (idc.ItemHead(datum[0] + SECTION_START), datum[1]))

    return yara.CALLBACK_CONTINUE
Esempio n. 7
0
def _convert_address_to_function(func):
    """Convert an address that IDA has classified incorrectly into a proper function."""
    # If everything goes wrong, we'll try to restore this function.
    orig = idc.FirstFuncFchunk(func)
    # If the address is not code, let's undefine whatever it is.
    if not idc.isCode(idc.GetFlags(func)):
        if not is_mapped(func):
            # Well, that's awkward.
            return False
        item = idc.ItemHead(func)
        itemend = idc.ItemEnd(func)
        if item != idc.BADADDR:
            _log(1, 'Undefining item {:#x} - {:#x}', item, itemend)
            idc.MakeUnkn(item, idc.DOUNK_EXPAND)
            idc.MakeCode(func)
            # Give IDA a chance to analyze the new code or else we won't be able to create a
            # function.
            idc.Wait()
            idc.AnalyseArea(item, itemend)
    else:
        # Just try removing the chunk from its current function. IDA can add it to another function
        # automatically, so make sure it's removed from all functions by doing it in loop until it
        # fails.
        for i in range(1024):
            if not idc.RemoveFchunk(func, func):
                break
    # Now try making a function.
    if idc.MakeFunction(func) != 0:
        return True
    # This is a stubborn chunk. Try recording the list of chunks, deleting the original function,
    # creating the new function, then re-creating the original function.
    if orig != idc.BADADDR:
        chunks = list(idautils.Chunks(orig))
        if idc.DelFunction(orig) != 0:
            # Ok, now let's create the new function, and recreate the original.
            if idc.MakeFunction(func) != 0:
                if idc.MakeFunction(orig) != 0:
                    # Ok, so we created the functions! Now, if any of the original chunks are not
                    # contained in a function, we'll abort and undo.
                    if all(idaapi.get_func(start) for start, end in chunks):
                        return True
            # Try to undo the damage.
            for start, _ in chunks:
                idc.DelFunction(start)
    # Everything we've tried so far has failed. If there was originally a function, try to restore
    # it.
    if orig != idc.BADADDR:
        _log(0, 'Trying to restore original function {:#x}', orig)
        idc.MakeFunction(orig)
    return False
Esempio n. 8
0
def item_off(ea):
    '''ea_t -> (int, int)'''
    head = idc.ItemHead(ea)
    end = idc.ItemEnd(head)
    ti = get_or_guess_tinfo(head)
    try:
        size = array_elem_size(ti)
    except NotArrayError:
        size = ti.get_size()
    diff = ea - head
    idx = diff / size
    rem = diff % size

    return (idx, rem)
Esempio n. 9
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 startEA of the function to create
        function_end - The endEA 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.MakeFunction(function_start, function_end):
            append_debug('Created a function 0x%X - 0x%X.' % (function_start, function_end))
            if require_term:
                last_mnem_ea = idc.ItemHead(idaapi.get_func(function_start).endEA - 1)
                last_mnem = idc.GetMnem(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 idaapi.get_many_bytes(last_mnem_ea, idc.ItemSize(last_mnem_ea)).encode('hex').upper() != end_mnem_bytes.upper()):
                    idc.DelFunction(function_start)
                    append_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).endEA:
                    idc.AnalyzeArea(function_start, idaapi.get_func(function_start).endEA)
                    return function_start, function_end
                else:
                    idc.DelFunction(function_start)
                    append_debug(
                        'Deleted function at 0x%X - the function didn\'t contain the target location.' % function_start)
                    return
        else:
            append_debug(
                'Tried to create a function 0x%X - 0x%X, but IDA wouldn\'t do it.' % (function_start, function_end))
    else:
        append_debug('The end address was not greater than the start address!')
Esempio n. 10
0
def _yara_callback(data):
    """
    Description:
        Generic yara callback.

    Input:
        As defined by YARA. See YARA's documentation for more info.

    Output:
        A list of tuples: (offset, identifier)
    """
    if not data['matches']:
        return False

    for datum in data['strings']:
        _YARA_MATCHES.append((idc.ItemHead(idaapi.get_fileregion_ea(datum[0])), datum[1]))

    return yara.CALLBACK_CONTINUE
Esempio n. 11
0
    def ida_get_item(self, address, hex_output=False):

        if self.check_address(address) != 1:
            # not a valid address
            return (None, 0)

        # return None if address is in the middle of instruction / data
        if address != idc.ItemHead(address):
            return (None, 0)

        len = idc.ItemSize(address)
        item = idaapi.get_many_bytes(address, len)

        if item is None:
            return (None, 0)

        if hex_output:
            item = to_hexstr(item)

        return (item, len)
Esempio n. 12
0
File: util.py Progetto: d-ned/mcsema
def is_block_or_instruction_head(ea):
    """Returns `True` if `ea` looks like it's the beginning of an actual
  instruction."""
    return is_internal_code(ea) and idc.ItemHead(ea) == ea
Esempio n. 13
0
def resolve_opnd(target, val):
    '''ea_t -> str | int -> op_ret'''  # XXX probably wrong
    head = idc.ItemHead(target)
    name = idc.Name(head)
    ti = get_or_guess_tinfo(head)
    return op_ret_for_ti(ti, name, target, val)
Esempio n. 14
0
def name_of_head(ea):
    '''ea -> str'''
    return idc.Name(idc.ItemHead(ea))