Beispiel #1
0
def remFuncChunks():
    """
    deletes all functions that have function chunks in them
    and appends "function_chunks_" to their names
    """
    foundProblem = False
    for seg in idautils.Segments():
        for ea in idautils.Functions(start=idc.SegStart(seg),
                                     end=idc.SegEnd(seg)):
            f = idaapi.get_func(ea)
            # chunk f
            if f.tailqty > 0:
                foundProblem = True
                print("Removing chunk function @ %07X" % f.startEA)
                idaapi.del_func(f.startEA)
                name = idc.Name(f.startEA)
                if "function_chunks_" not in name:
                    newName = 'function_chunks_%s' % name
                    print("Renaming %s -> %s" % ((name, newName)))
                    idc.MakeName(f.startEA, newName)

    if foundProblem:
        print("Removed all function chunks!")
    else:
        print("No function chunks detected!")
Beispiel #2
0
def remove(fn):
    if type(fn) is idaapi.func_t:
        return idaapi.del_func(fn.startEA)
    return remove(by(fn))
Beispiel #3
0
##SCRIPT TO REBUILD ANATOVA FUNCTIONS

functions = []
bucket = []

for f in idautils.Functions():
    name = idc.get_func_name(f)
    if name[:2] == "j_":
        continue

    addr = f
    func = idaapi.get_func(f)
    size = func.endEA - func.startEA
    print "{} {} - {}".format(addr, name, size)
    tmp = {"addr": addr, "name": name, "size": size}
    if size == 11:
        if len(bucket) > 0:
            functions.append(bucket)
            bucket = []
    bucket.append(tmp)
functions.append(bucket)

for bucket in functions:
    init = bucket[0]['addr']
    tmp = bucket[-1]
    end = init
    for f in bucket:
        fin += f['size']
        idaapi.del_func(f['addr'])
    idaapi.add_func(init, end)
Beispiel #4
0
def remove(fn):
    if type(fn) is idaapi.func_t:
        return idaapi.del_func(fn.startEA)
    return remove(by(fn))
Beispiel #5
0
def do_hanging(S, E):
    if not process_hanging:
        return

    Verbose("STATUS put all hanging instructions in functions")

    partitioning.Init()

    # fixed parameters
    partitioning.subcfg_forward = False
    partitioning.subcfg_backward = True
    partitioning.subcfg_backforth = False

    # PHASE 1a: mark hanging blocks
    #           Here we have a problem, as basic blocks and control flow edges are not known for hanging instructions.
    #           We solve this by letting IDA define a function at the hanging instruction address.
    hanging_functions = set()
    marked_block_count = 0
    change = True
    while change:
        change = False

        for i in idapython.iter_hanging(S, E):
            if not MakeFunction(i):
                # could not create function
                Verbose(
                    "could not create function for hanging instruction at 0x%x"
                    % i)
                continue

            # print("hanging 0x%x" % i)
            change = True

            f_start = GetFunctionAttr(i, FUNCATTR_START)
            hanging_functions.add(f_start)

            # print("START 0x%x" % f_start)
            for block in idapython.iter_blocks_in_function(f_start):
                # print("marking block 0x%x-0x%x" % (block.startEA, PrevHead(block.endEA)))
                partitioning.MarkBlock(block.startEA, PrevHead(block.endEA))
                marked_block_count += 1
            #endfor blocks
        #endfor iter_hanging
    #endwhile change

    # PHASE 1b: mark ignored edges
    #TODO

    ins_to_functions(S, E)

    # PHASE 2: iteratively associate hanging blocks with function
    D.collect_links(same_function)

    if not repartition_hanging:
        return
    idapython.DumpDatabase(DumpDatabaseName('before-hanging-repart'))

    Verbose("STATUS repartition hanging instructions")

    # collect possible start points:
    # blocks that have one or more non-hanging incoming/outgoing blocks
    start_points = set()
    for block in partitioning.MarkedBlockIterator():
        added = False
        for x in idapython.BblIncomingInsns(block):
            start = block_start_address(x)
            if (start is not None) and (not partitioning.IsBlockMarked(start)):
                start_points.add(block)
                added = True
                break
        #endfor incoming

        # early continue if possible
        if added:
            continue

        for x in idapython.BblOutgoingInsns(block_end_address(block)):
            if not partitioning.IsBlockMarked(x):
                start_points.add(block)
                break
        #endfor outgoing
    #endfor marked
    Verbose("STATUS start with %d/%d" %
            (len(start_points), marked_block_count))

    total_iterations = 0
    total_moved_blocks = 0

    configurations = [[False, False, False, False, False],
                      [False, False, False, True, False],
                      [False, False, False, False, True],
                      [False, False, True, False, False],
                      [True, True, False, False, False],
                      [True, True, False, True, False],
                      [True, True, False, False, True],
                      [True, True, True, False, False]]
    for conf in configurations:
        start_points, nr_iterations, nr_moved_blocks = partitioning.repartition(
            start_points, [], conf[0], conf[1], conf[2], conf[3], conf[4],
            True, False)
        total_iterations += nr_iterations
        total_moved_blocks += nr_moved_blocks

    # final pass: iterate remaining hanging blocks
    for block in partitioning.MarkedBlockIterator():
        start_points.add(block)
    # hardcoded flags here
    start_points, nr_iterations, nr_moved_blocks = partitioning.repartition(
        start_points, [], True, True, True, False, False, True, False)
    total_iterations += nr_iterations
    total_moved_blocks += nr_moved_blocks

    Verbose("STATUS moved %d/%d blocks in %d iterations" %
            (total_moved_blocks, marked_block_count, total_iterations))

    if repartition_hanging_rehang:
        nr_rehang = 0
        for block in partitioning.MarkedBlockIterator():
            Verbose("deleting block 0x%x" % block)
            idaapi.del_func(block)
            nr_rehang += 1
        Verbose("STATUS rehung %d blocks" % nr_rehang)
Beispiel #6
0
def delete_multichunk_funcs():
    for func_t in iter_multichunk_funcs():
        idaapi.del_func(func_t.startEA)
Beispiel #7
0
def _ChunkMovePart(inner_start, inner_end_ex, function_address):
    moved_blocks = []

    fn_print("MICRO move 0x%x-0x%x to 0x%x" %
             (inner_start, inner_end_ex, function_address))
    outer_function = idc.GetFunctionAttr(inner_start, idc.FUNCATTR_START)
    outer_start = idc.GetFchunkAttr(inner_start, idc.FUNCATTR_START)
    outer_end_ex = idc.GetFchunkAttr(inner_start, idc.FUNCATTR_END)

    function_address2 = idc.GetFunctionAttr(function_address,
                                            idc.FUNCATTR_START)

    if outer_start == 0xffffffff:
        fn_print("outer start not defined")
        outer_start = inner_start
    if outer_end_ex == 0xffffffff:
        fn_print("outer end not defined")
        outer_end_ex = inner_end_ex

    if function_address2 == outer_function:
        fn_print("don't move, already in function")
        return moved_blocks

    # remove chunk from function
    remove_chunk_ok = True
    if outer_function == BADADDR:
        fn_print("already hanging 0x%x-0x%x" % (outer_start, outer_end_ex))
    else:
        fn_print("remove 0x%x-0x%x from 0x%x" %
                 (outer_start, outer_end_ex, outer_function))
        remove_chunk_ok = FunctionRemoveChunk(outer_start)
        moved_blocks.append([outer_start, outer_end_ex])

        if not remove_chunk_ok:
            fn_print("  could not remove chunk")

            chunks = FunctionChunks(outer_start)
            if len(chunks) == 1:
                fn_print("  deleting function, moving entire chunk")
                if (inner_start != outer_start) or (inner_end_ex !=
                                                    outer_end_ex):
                    fn_print("  changed function bounds!")
                remove_chunk_ok = idaapi.del_func(outer_start)
                assert remove_chunk_ok
                inner_start = outer_start
                inner_end_ex = outer_end_ex
            else:
                fn_print("  function contains chunks %s" %
                         [['0x%x-0x%x' % (i, j)] for i, j in chunks])

                # to disable function chunk isolation
                # return moved_blocks

                if (chunks[0][0] <= inner_start) and (inner_start <
                                                      chunks[0][1]):
                    fn_print(
                        "have to move first chunk, need to work around this..."
                    )

                    fn_print("removing all but first chunk")
                    for i in range(1, len(chunks)):
                        remove_chunk_ok_2 = FunctionRemoveChunk(chunks[i][0])
                        assert remove_chunk_ok_2

                        current_address = chunks[i][0]
                        while current_address < chunks[i][1]:
                            assert InsIsData(current_address) or InsIsHanging(
                                current_address
                            ), "0x%x does not hang nor is data" % current_address
                            current_address = idc.NextHead(current_address)
                        #endwhile
                    #endfor

                    fn_print(
                        "create new function starting at second chunk (0x%x-0x%x)"
                        % (chunks[1][0], chunks[1][1]))
                    create_function_ok = FunctionCreateAt(
                        chunks[1][0], chunks[1][1])
                    moved_blocks.append([chunks[1][0], chunks[1][1]])
                    assert create_function_ok

                    if len(chunks) > 2:
                        for i in range(2, len(chunks)):
                            moved_blocks_sub = _ChunkMovePart(
                                chunks[i][0], chunks[i][1], chunks[1][0])
                            moved_blocks.extend(moved_blocks_sub)
                            assert len(moved_blocks_sub) > 0
                        #endfor
                    #endif

                    fn_print(
                        "finally removing entire function for first chunk")
                    remove_chunk_ok = idaapi.del_func(chunks[0][0])
                    moved_blocks.append([chunks[0][0], chunks[0][1]])
                    assert remove_chunk_ok

                    for i in range(1, len(chunks)):
                        ii = chunks[i][0]
                        while ii < chunks[i][1]:
                            assert not InsIsHanging(ii), "0x%x hangs" % ii
                            ii = idc.NextHead(ii)
                        #endif
                    #endfor

                    inner_start = outer_start
                    inner_end_ex = outer_end_ex
                else:
                    assert False
                #endif
            #endif
        #endif
    #endif

    assert remove_chunk_ok

    move_block_ok = False

    # regular move
    # append the desired part to the correct function
    restored_whole_chunk = False

    fn_print("moving 0x%x-0x%x" % (inner_start, inner_end_ex))

    move_block_ok = FunctionAppendChunk(function_address, inner_start,
                                        inner_end_ex)
    fn_print("   move-block %d" % move_block_ok)

    if not move_block_ok:
        if outer_start == outer_function:
            fn_print(
                "error-restore: start of function 0x%x-(0x%x-0x%x)-0x%x to 0x%x"
                % (outer_start, inner_start, inner_end_ex, outer_end_ex,
                   outer_function))
            assert outer_end_ex == inner_end_ex
            restored_whole_chunk = FunctionCreateAt(outer_start, outer_end_ex)
            moved_blocks.append([outer_start, outer_end_ex])
            assert restored_whole_chunk
        else:
            fn_print("restoring 0x%x-0x%x to 0x%x" %
                     (outer_start, outer_end_ex, outer_function))
            restored_whole_chunk = FunctionAppendChunk(outer_function,
                                                       outer_start,
                                                       outer_end_ex)
            moved_blocks.append([outer_start, outer_end_ex])
            if not restored_whole_chunk:
                real_function = idc.GetFunctionAttr(outer_start,
                                                    idc.FUNCATTR_START)
                should_be_function = outer_function
                if real_function == should_be_function:
                    restored_whole_chunk = True
                else:
                    fn_print("0x%x/0x%x" % (real_function, should_be_function))
            #endif
            assert restored_whole_chunk
    else:
        moved_blocks.append([inner_start, inner_end_ex])

    if not restored_whole_chunk:
        # add PRE-part to original function, if needed
        if outer_start < inner_start:
            fn_print(" prefix...")

            if InsIsHanging(outer_start):
                prefixmove = FunctionAppendChunk(outer_function, outer_start,
                                                 inner_start)
                moved_blocks.append([outer_start, inner_start])
                if not prefixmove:
                    fn_print(
                        "could not restore prefix 0x%x-0x%x, instead adding it to the new function too"
                        % (outer_start, inner_start))
                    prefixmove = FunctionAppendChunk(function_address,
                                                     outer_start, inner_start)
                    assert prefixmove
                    moved_blocks.append(
                        [outer_start, inner_start, function_address])
                else:
                    fn_print("restored prefix 0x%x-0x%x" %
                             (outer_start, inner_start))
                #endif
            #endif
        #endif

        # add POST-part to original function, if needed
        if inner_end_ex < outer_end_ex:
            fn_print(" postfix...")

            post_start = inner_end_ex
            while post_start < outer_end_ex:
                if InsIsData(post_start):
                    # skip data
                    post_start = idc.NextHead(post_start)
                else:
                    # found start of a block of code
                    subpost_start = post_start
                    fn_print("found subpost start 0x%x" % subpost_start)

                    subpost_end = idc.NextHead(subpost_start)
                    while subpost_end < outer_end_ex:
                        if not InsIsHanging(subpost_end):
                            break
                        subpost_end = idc.NextHead(subpost_end)
                    #endwhile subpost_start

                    # don't go past the end of the section
                    E = section_end(subpost_start)
                    if subpost_end > E:
                        subpost_end = E

                    fn_print("found subpost 0x%x-0x%x" %
                             (subpost_start, subpost_end))
                    postfixmove = FunctionAppendChunk(outer_function,
                                                      subpost_start,
                                                      subpost_end)
                    moved_blocks.append([subpost_start, subpost_end])
                    if not postfixmove:
                        fn_print(
                            "could not restore postfix 0x%x-0x%x, instead adding it to the new function too"
                            % (subpost_start, subpost_end))
                        postfixmove = FunctionAppendChunk(
                            function_address, subpost_start, subpost_end)
                        if not postfixmove:
                            DumpDatabase('assertion.idb')
                        assert postfixmove
                        moved_blocks.append([subpost_start, subpost_end])
                    else:
                        fn_print("restored postfix 0x%x-0x%x" %
                                 (subpost_start, subpost_end))
                    #endif

                    post_start = subpost_end
                #endif
            #endwhile post_start
        #endif
    #endif

    ii = outer_start
    while ii < outer_end_ex:
        assert not InsIsHanging(ii), "0x%x hangs" % ii
        ii = idc.NextHead(ii)
    #endif

    return moved_blocks