示例#1
0
    def heads(self, start=None, reverse=False):
        """
        Iterates all the heads for the given function.

        :param start: Start address (defaults to start_ea or end_ea)
        :param reverse:  Direction to iterate
        :return:
        """
        if not self._flowchart:
            self._flowchart = function_tracing.FlowChart(self.start_ea)
        if not start:
            start = self.end_ea if reverse else self.start_ea

        for ea in self._flowchart.heads(start, reverse=reverse):
            yield ea
def test_flowchart():
    import idc
    from kordesii.utils import function_tracing

    # Test on simple 1 block function.
    flowchart = function_tracing.FlowChart(0x004011AA)
    blocks = list(flowchart.blocks())
    assert len(blocks) == 1
    block = blocks[0]
    assert block.start_ea == 0x00401150
    assert block.end_ea == 0x004012A0
    assert list(block.heads()) == [
        0x00401150,
        0x00401151,
        0x00401153,
        0x00401158,
        0x0040115D,
        0x00401162,
        0x00401167,
        0x0040116A,
        0x0040116F,
        0x00401174,
        0x00401179,
        0x0040117C,
        0x00401181,
        0x00401186,
        0x0040118B,
        0x0040118E,
        0x00401193,
        0x00401198,
        0x0040119D,
        0x004011A0,
        0x004011A5,
        0x004011AA,
        0x004011AF,
        0x004011B2,
        0x004011B7,
        0x004011BC,
        0x004011C1,
        0x004011C4,
        0x004011C9,
        0x004011CE,
        0x004011D3,
        0x004011D6,
        0x004011DB,
        0x004011E0,
        0x004011E5,
        0x004011E8,
        0x004011ED,
        0x004011F2,
        0x004011F7,
        0x004011FA,
        0x004011FF,
        0x00401204,
        0x00401209,
        0x0040120C,
        0x00401211,
        0x00401216,
        0x0040121B,
        0x0040121E,
        0x00401223,
        0x00401228,
        0x0040122D,
        0x00401230,
        0x00401235,
        0x0040123A,
        0x0040123F,
        0x00401242,
        0x00401247,
        0x0040124C,
        0x00401251,
        0x00401254,
        0x00401259,
        0x0040125E,
        0x00401263,
        0x00401266,
        0x0040126B,
        0x00401270,
        0x00401275,
        0x00401278,
        0x0040127D,
        0x00401282,
        0x00401287,
        0x0040128A,
        0x0040128F,
        0x00401294,
        0x00401299,
        0x0040129C,
        0x0040129E,
        0x0040129F,
    ]
    # Ensure we create a path of just the 1 block.
    path_blocks = list(flowchart.get_paths(0x004011AA))
    assert len(path_blocks) == 1
    path_block = path_blocks[0]
    assert path_block.path() == [path_block]
    # Ensure cpu context gets created correctly.
    cpu_context = path_block.cpu_context()
    assert cpu_context.ip == block.end_ea
    cpu_context = path_block.cpu_context(0x0040115D)
    assert cpu_context.ip == 0x0040115D
    # TODO: Move to testing cpu_context.
    data_ptr = cpu_context.read_data(cpu_context.registers.esp,
                                     data_type=function_tracing.DWORD)
    assert cpu_context.read_data(data_ptr) == "Idmmn!Vnsme "

    # Test on slightly more complex function with 5 blocks
    flowchart = function_tracing.FlowChart(0x004035BB)

    found_block = flowchart.find_block(0x004035AD)
    assert found_block
    assert found_block.start_ea == 0x004035AB

    blocks = list(flowchart.blocks(start=0x004035AB, reverse=True))
    assert len(blocks) == 2
    assert [(block.start_ea, block.end_ea) for block in blocks] == [
        (0x004035AB, 0x004035B1),
        (0x00403597, 0x004035AB),
    ]

    blocks = list(flowchart.blocks(start=0x004035AB))
    assert len(blocks) == 4
    assert [(block.start_ea, block.end_ea) for block in blocks] == [
        (0x004035AB, 0x004035B1),
        (0x004035BA, 0x004035BD),
        (0x004035B1, 0x004035B3),
        (0x004035B3, 0x004035BA),
    ]

    blocks = list(flowchart.blocks())
    assert len(blocks) == 5
    assert [(block.start_ea, block.end_ea) for block in blocks] == [
        (0x00403597, 0x004035AB),
        (0x004035AB, 0x004035B1),
        (0x004035BA, 0x004035BD),
        (0x004035B1, 0x004035B3),
        (0x004035B3, 0x004035BA),
    ]
    blocks = list(flowchart.blocks(reverse=True))
    print(blocks)
    assert len(blocks) == 5
    assert [(block.start_ea, block.end_ea) for block in blocks] == [
        (0x004035BA, 0x004035BD),
        (0x004035B3, 0x004035BA),
        (0x00403597, 0x004035AB),
        (0x004035B1, 0x004035B3),
        (0x004035AB, 0x004035B1),
    ]
    blocks = list(flowchart.blocks(dfs=True))
    assert len(blocks) == 5
    assert [(block.start_ea, block.end_ea) for block in blocks] == [
        (0x00403597, 0x004035AB),
        (0x004035AB, 0x004035B1),
        (0x004035B1, 0x004035B3),
        (0x004035B3, 0x004035BA),
        (0x004035BA, 0x004035BD),
    ]
    blocks = list(flowchart.blocks(reverse=True, dfs=True))
    assert len(blocks) == 5
    assert [(block.start_ea, block.end_ea) for block in blocks] == [
        (0x004035BA, 0x004035BD),
        (0x004035B3, 0x004035BA),
        (0x004035B1, 0x004035B3),
        (0x004035AB, 0x004035B1),
        (0x00403597, 0x004035AB),
    ]

    path_blocks = list(flowchart.get_paths(0x004035B1))
    assert len(path_blocks) == 1
    assert [path_block.bb.start_ea for path_block in path_blocks[0].path()
            ] == [0x00403597, 0x004035AB, 0x004035B1]

    path_blocks = list(flowchart.get_paths(0x004035BC))
    assert len(path_blocks) == 3
    assert sorted(
        [_path_block.bb.start_ea for _path_block in path_block.path()]
        for path_block in path_blocks) == [
            [0x00403597, 0x004035AB, 0x004035B1, 0x004035B3, 0x004035BA],
            [0x00403597, 0x004035AB, 0x004035B3, 0x004035BA],
            [0x00403597, 0x004035BA],
        ]