Beispiel #1
0
 def test_issue_4_scanAritlog(self):
     """
     Date created: 2012-11-17
     In regard of issue: #4, https://bitbucket.org/daniel_plohmann/simplifire.idascope/issue/4/tarjan-algorithm-incorrect-results
     Description: A bug in the identification of looped blocks exists that will not spot blocks that are
                  contained in non-trivial and nested loops. Only blocks in trivial loops are spotted.
                  This test contains an abstraction of the algorithm of CryptoIdentifer.scanAritlog()
                  intended to finding looped blocks.
     Expected result: 7 blocks in loops (nontrivial + trivial + nested)
     Actual result: 1 block in loop (trivial)
     """
     graph_example_issue_4 = {4368288: [4368265, 4368304], 4368322: [4368355, 4368322], 4368355: [], \
         4368263: [4368265], 4368265: [4368270], 4368270: [4368274, 4368283], 4368304: [4368311], \
         4368274: [4368285], 4368311: [4368322, 4368355], 4368283: [4368285], 4368285: [4368270, 4368288], \
         4368254: [4368263, 4368311]}
     # ABSTRACTED: Removed dependency on the concrete sample where this bug appeared.
     # ABSTRACTED: Necessity to loop over all functions in the sample
     aritlog_blocks = []
     function_blocks = []
     function_dgraph = {}
     blocks_in_loops = set()
     for current_block in graph_example_issue_4:
         block = AritlogBasicBlock(current_block, 0)
         # ABSTRACTED: enumeration of instructions to build Aritlog ratings.
         function_blocks.append(block)
         # prepare graph for Tarjan's algorithm
         succeeding_blocks = [
             succ for succ in graph_example_issue_4[current_block]
         ]
         function_dgraph[current_block] = succeeding_blocks
         # add trivial loops
         if current_block in succeeding_blocks:
             blocks_in_loops.update([current_block])
     # perform Tarjan's algorithm to identify strongly connected components (= loops) in the function graph
     graph_helper = GraphHelper()
     strongly_connected = graph_helper.calculateStronglyConnectedComponents(
         function_dgraph)
     non_trivial_loops = [
         component for component in strongly_connected if len(component) > 1
     ]
     # This part in the code prior to the bugfix contains the error.
     ###############################################
     # for component in non_trivial_loops:
     #     blocks_in_loops.update(non_trivial_loops)
     ###############################################
     # component is a tuple. In the above code blocks_in_loops will consist of tuples instead of the actual
     # blocks contained in the tuples, as is evaluated against later on.
     # FIX: introduce another loop to enumerate the tuples elements.
     for component in non_trivial_loops:
         for block in component:
             blocks_in_loops.update([block])
     for block in function_blocks:
         if block.start_ea in blocks_in_loops:
             block.is_contained_in_loop = True
     aritlog_blocks.extend(function_blocks)
     num_looped_blocks = len(
         [block for block in aritlog_blocks if block.is_contained_in_loop])
     self.assertEquals(7, num_looped_blocks)
 def test_issue_4_scanAritlog(self):
     """
     Date created: 2012-11-17
     In regard of issue: #4, https://bitbucket.org/daniel_plohmann/simplifire.idascope/issue/4/tarjan-algorithm-incorrect-results
     Description: A bug in the identification of looped blocks exists that will not spot blocks that are
                  contained in non-trivial and nested loops. Only blocks in trivial loops are spotted.
                  This test contains an abstraction of the algorithm of CryptoIdentifer.scanAritlog()
                  intended to finding looped blocks.
     Expected result: 7 blocks in loops (nontrivial + trivial + nested)
     Actual result: 1 block in loop (trivial)
     """
     graph_example_issue_4 = {4368288: [4368265, 4368304], 4368322: [4368355, 4368322], 4368355: [], \
         4368263: [4368265], 4368265: [4368270], 4368270: [4368274, 4368283], 4368304: [4368311], \
         4368274: [4368285], 4368311: [4368322, 4368355], 4368283: [4368285], 4368285: [4368270, 4368288], \
         4368254: [4368263, 4368311]}
     # ABSTRACTED: Removed dependency on the concrete sample where this bug appeared.
     # ABSTRACTED: Necessity to loop over all functions in the sample
     aritlog_blocks = []
     function_blocks = []
     function_dgraph = {}
     blocks_in_loops = set()
     for current_block in graph_example_issue_4:
         block = AritlogBasicBlock(current_block, 0)
         # ABSTRACTED: enumeration of instructions to build Aritlog ratings.
         function_blocks.append(block)
         # prepare graph for Tarjan's algorithm
         succeeding_blocks = [succ for succ in graph_example_issue_4[current_block]]
         function_dgraph[current_block] = succeeding_blocks
         # add trivial loops
         if current_block in succeeding_blocks:
             blocks_in_loops.update([current_block])
     # perform Tarjan's algorithm to identify strongly connected components (= loops) in the function graph
     graph_helper = GraphHelper()
     strongly_connected = graph_helper.calculateStronglyConnectedComponents(function_dgraph)
     non_trivial_loops = [component for component in strongly_connected if len(component) > 1]
     # This part in the code prior to the bugfix contains the error.
     ###############################################
     # for component in non_trivial_loops:
     #     blocks_in_loops.update(non_trivial_loops)
     ###############################################
     # component is a tuple. In the above code blocks_in_loops will consist of tuples instead of the actual
     # blocks contained in the tuples, as is evaluated against later on.
     # FIX: introduce another loop to enumerate the tuples elements.
     for component in non_trivial_loops:
         for block in component:
             blocks_in_loops.update([block])
     for block in function_blocks:
         if block.start_ea in blocks_in_loops:
             block.is_contained_in_loop = True
     aritlog_blocks.extend(function_blocks)
     num_looped_blocks = len([block for block in aritlog_blocks if block.is_contained_in_loop])
     self.assertEquals(7, num_looped_blocks)
Beispiel #3
0
    def test_graphAlgorithms(self):
        """
        Date created: 2012-11-17
        In regard of issue: #4, https://bitbucket.org/daniel_plohmann/simplifire.idascope/issue/4/tarjan-algorithm-incorrect-results
        Description: A bug in the identification of looped blocks exists that will not spot blocks that are
                     contained in non-trivial and nested loops. Only blocks in trivial loops are spotted.
        """
        graph_helper = GraphHelper()

        graph_without_loops = {1: [2, 3], 2: [3], 3: [4]}
        scc_simple = graph_helper.calculateStronglyConnectedComponents(
            graph_without_loops)
        self.assertEquals([(4, ), (3, ), (2, ), (1, )], scc_simple)

        graph_with_trivial_loops = {1: [1, 2, 3], 2: [3], 3: [3, 4]}
        scc_trivial = graph_helper.calculateStronglyConnectedComponents(
            graph_with_trivial_loops)
        self.assertEquals([(4, ), (3, ), (2, ), (1, )], scc_trivial)

        graph_with_non_trivial_loops = {1: [2], 2: [3], 3: [1, 4], 4: [5]}
        scc_non_trivial = graph_helper.calculateStronglyConnectedComponents(
            graph_with_non_trivial_loops)
        self.assertEquals([(5, ), (4, ), (3, 2, 1)], scc_non_trivial)

        graph_with_non_and_trivial_loops = {
            1: [2],
            2: [3],
            3: [1, 4],
            4: [4, 5]
        }
        scc_non_and_trivial = graph_helper.calculateStronglyConnectedComponents(
            graph_with_non_and_trivial_loops)
        self.assertEquals([(5, ), (4, ), (3, 2, 1)], scc_non_and_trivial)

        graph_with_nested_loops = {
            1: [2],
            2: [3],
            3: [2, 4],
            4: [1, 5],
            5: [6]
        }
        scc_nested = graph_helper.calculateStronglyConnectedComponents(
            graph_with_nested_loops)
        self.assertEquals([(6, ), (5, ), (4, 3, 2, 1)], scc_nested)

        graph_example_issue_4 = {4368288: [4368265, 4368304], 4368322: [4368355, 4368322], 4368355: [], \
            4368263: [4368265], 4368265: [4368270], 4368270: [4368274, 4368283], 4368304: [4368311], \
            4368274: [4368285], 4368311: [4368322, 4368355], 4368283: [4368285], 4368285: [4368270, 4368288], \
            4368254: [4368263, 4368311]}
        scc_issue_4 = graph_helper.calculateStronglyConnectedComponents(
            graph_example_issue_4)
        self.assertEquals([(4368355,), (4368322,), (4368311,), (4368304,), \
            (4368283, 4368288, 4368285, 4368274, 4368270, 4368265), (4368263,), (4368254,)], scc_issue_4)
    def test_graphAlgorithms(self):
        """
        Date created: 2012-11-17
        In regard of issue: #4, https://bitbucket.org/daniel_plohmann/simplifire.idascope/issue/4/tarjan-algorithm-incorrect-results
        Description: A bug in the identification of looped blocks exists that will not spot blocks that are
                     contained in non-trivial and nested loops. Only blocks in trivial loops are spotted.
        """
        graph_helper = GraphHelper()

        graph_without_loops = {1: [2, 3], 2: [3], 3: [4]}
        scc_simple = graph_helper.calculateStronglyConnectedComponents(graph_without_loops)
        self.assertEquals([(4, ), (3, ), (2, ), (1, )], scc_simple)

        graph_with_trivial_loops = {1: [1, 2, 3], 2: [3], 3: [3, 4]}
        scc_trivial = graph_helper.calculateStronglyConnectedComponents(graph_with_trivial_loops)
        self.assertEquals([(4, ), (3, ), (2, ), (1, )], scc_trivial)

        graph_with_non_trivial_loops = {1: [2], 2: [3], 3: [1, 4], 4: [5]}
        scc_non_trivial = graph_helper.calculateStronglyConnectedComponents(graph_with_non_trivial_loops)
        self.assertEquals([(5, ), (4, ), (3, 2, 1)], scc_non_trivial)

        graph_with_non_and_trivial_loops = {1: [2], 2: [3], 3: [1, 4], 4: [4, 5]}
        scc_non_and_trivial = graph_helper.calculateStronglyConnectedComponents(graph_with_non_and_trivial_loops)
        self.assertEquals([(5, ), (4, ), (3, 2, 1)], scc_non_and_trivial)

        graph_with_nested_loops =  {1: [2], 2: [3], 3: [2, 4], 4: [1, 5], 5: [6]}
        scc_nested = graph_helper.calculateStronglyConnectedComponents(graph_with_nested_loops)
        self.assertEquals([(6, ), (5, ), (4, 3, 2, 1)], scc_nested)

        graph_example_issue_4 = {4368288: [4368265, 4368304], 4368322: [4368355, 4368322], 4368355: [], \
            4368263: [4368265], 4368265: [4368270], 4368270: [4368274, 4368283], 4368304: [4368311], \
            4368274: [4368285], 4368311: [4368322, 4368355], 4368283: [4368285], 4368285: [4368270, 4368288], \
            4368254: [4368263, 4368311]}
        scc_issue_4 = graph_helper.calculateStronglyConnectedComponents(graph_example_issue_4)
        self.assertEquals([(4368355,), (4368322,), (4368311,), (4368304,), \
            (4368283, 4368288, 4368285, 4368274, 4368270, 4368265), (4368263,), (4368254,)], scc_issue_4)