Exemple #1
0
    def iterFuncChunks(self, ea):
        start = self.funcStart(ea)
        end = self.funcEnd(ea)

        if not start or not end:
            return []

        current = idc.FirstFuncFchunk(start)
        chunks = [current]

        while True:
            next = idc.NextFuncFchunk(start, current)

            if next != idc.BADADDR:
                current = next
                chunks.append(next)
            else:
                break

        res = []
        for chunk in chunks:
            chunk_end = idc.GetFchunkAttr(chunk, idc.FUNCATTR_END)
            res.extend(list(self.iterInstructions(chunk, chunk_end)))

        return res
Exemple #2
0
 def __chunks(cls, ea):
     '''enumerates all chunks in a function '''
     res = idc.FirstFuncFchunk(ea)
     while res != idc.BADADDR:
         (start, end) = idc.GetFchunkAttr(res, idc.FUNCATTR_START), idc.GetFchunkAttr(res, idc.FUNCATTR_END)
         yield start,end
         res = idc.NextFuncFchunk(ea, res)
     return
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
Exemple #4
0
def FunctionChunks(addr):
    result = []
    entry = idc.GetFunctionAttr(addr, idc.FUNCATTR_START)

    chunk = idc.FirstFuncFchunk(entry)
    if chunk == BADADDR:
        return result

    # list the function chunks
    result.append([chunk, idc.GetFchunkAttr(chunk, idc.FUNCATTR_END)])
    while chunk != BADADDR:
        chunk = idc.NextFuncFchunk(entry, chunk)
        if chunk != BADADDR:
            result.append([chunk, idc.GetFchunkAttr(chunk, idc.FUNCATTR_END)])

    return result
Exemple #5
0
def enumerate_function_chunks(f_start):
    """
    The function gets a list of chunks for the function.
    @f_start - first address of the function
    @return - list of chunks
    """
    # Enumerate all chunks in the function
    chunks = list()
    first_chunk = idc.FirstFuncFchunk(f_start)
    chunks.append((first_chunk, idc.GetFchunkAttr(first_chunk,
                                                  idc.FUNCATTR_END)))
    next_chunk = first_chunk
    while next_chunk != 0xffffffffL:
        next_chunk = idc.NextFuncFchunk(f_start, next_chunk)
        if next_chunk != 0xffffffffL:
            chunks.append(
                (next_chunk, idc.GetFchunkAttr(next_chunk, idc.FUNCATTR_END)))
    return chunks
Exemple #6
0
def deobfuscate_function(addr):
    if addr != idc.FirstFuncFchunk(addr):
        print "[DEOBF] Address %X is not the start of a function." % addr
        return

    # Static data.
    func_start = addr
    func_end = idc.FindFuncEnd(addr)

    # 1. Find MOV PC
    (mov_addr, mov_match) = search_forward(func_start, func_end, regex_mov)

    if mov_addr is None:
        # print "[DEOBF] No MOV PC was found in %s" % idc.GetFunctionName(func_start)
        return

    # 2. Find LDR.W ..
    ldr_addr = search_register_modifier_backward(mov_addr, func_start,
                                                 mov_match.group(1))
    ldr_match = regex_ldrw.match(
        idc.GetDisasm(ldr_addr)) if ldr_addr is not None else None

    if ldr_addr is None:
        print "[DEOBF] No LDR.W was found in %s" % idc.GetFunctionName(
            func_start)
        return

    if ldr_match is None:
        print "[DEOBF] Modifier of %s found from %X is not a LDR.W" % (
            mov_match.group(1), mov_addr)
        return

    # 3. Find table offset
    add_addr = search_register_modifier_backward(ldr_addr, func_start,
                                                 ldr_match.group(2))
    # add_match = regex_table.match(idc.GetDisasm(add_addr)) if add_addr is not None else None
    #
    # print idc.GetEnum(add_match.group(2) + 'asd')

    if add_addr is None:
        # TODO: Check if belongs to a previously found graph.
        # print "[DEOBF] No ADD was found above %X" % ldr_addr
        return

    if idc.GetOpnd(add_addr, 1) != 'PC':
        print "[DEOBF] ADD does not use PC at %X" % add_addr
        return

    ldr2_addr = search_register_modifier_backward(idc.PrevHead(add_addr),
                                                  func_start,
                                                  idc.GetOpnd(add_addr, 0))

    opp_val = idc.GetOperandValue(ldr2_addr, 1)  # Address to loc_80054
    opp_val = idc.Dword(opp_val)  # loc_80054
    opp_val = opp_val + idc.NextHead(add_addr) + 2  # Address of the table.

    # 4. Read table.
    table = []
    table_addr = opp_val

    while True:
        table_entry = idc.Dword(table_addr)
        if table_entry > 0:
            table.append(table_entry)
        table_addr = table_addr + 4
        if idc.Name(table_addr):
            break

    # - We also have to add the starting block to the table.
    table.append(func_start)

    # 5. Find subroutine boundary
    (sub_start, sub_end) = find_subroutine_boundary(opp_val, table)

    print "Start: %X - End: %X" % (sub_start, sub_end)