Ejemplo n.º 1
0
    def compute_block_histogram_per_edge(self, dropped_edges=set()):
        if self.symb_tree.is_empty():
            return dict(), dict(), dict()

        edges_post = dict()
        edges_pre = dict()
        root_histogram = self.__compute_block_histogram_per_edge(
            self.symb_tree.root.children[0], self.symb_tree.root, edges_post,
            edges_pre, set(), set(), dropped_edges)

        # calculate histogram pre
        for edge in edges_pre:
            visited = edges_pre[edge]
            new = dict()
            for node in visited:
                block_id = self.address_to_block[str(node.data.address)]
                insert_or_add(new, block_id, 1)
            edges_pre[edge] = new

        # add the first node block to the root histogram
        first_node_addr = self.symb_tree.root.children[0].data.address
        if first_node_addr in self.address_to_block:
            insert_or_add(root_histogram,
                          self.address_to_block[first_node_addr], 1)

        return root_histogram, edges_post, edges_pre
Ejemplo n.º 2
0
    def __compute_block_histogram_per_block(self, node, nodes_list_post,
                                            nodes_list_pre, visited_blocks,
                                            visited_nodes, dropped_nodes):
        node_id = str(node.data.address)
        child_visited_nodes = visited_nodes.copy()
        child_visited_blocks = visited_blocks.copy()

        # find out whether the addresses of child and father are in R2 CFG
        # they cannot be there due to fake angr blocks (simprocedures)
        if node_id not in self.address_to_block:
            node_block_id = None
        else:
            node_block_id = self.address_to_block[node_id]

        if node_block_id:
            child_visited_nodes.add(node)
            child_visited_blocks.add(node_block_id)

            # this edges is considered dropped. Return empty histogram
            if node_block_id in dropped_nodes:
                return dict()

        # combine nephew histograms (if any)
        children_histogram = dict()
        for child in node.children:
            child_hist = self.__compute_block_histogram_per_block(
                child, nodes_list_post, nodes_list_pre, child_visited_blocks,
                child_visited_nodes, dropped_nodes)
            combine_histograms(children_histogram, child_hist)

        my_histogram = children_histogram

        if node_block_id:
            # the current block is in R2. Add it to the histogram to be returned
            insert_or_add(my_histogram, node_block_id, 1)

            # merge my histogram to edges_list only if the current edge was not visited by parents
            # Otherwise -> double count (see TreeAnalyzerTests.test_6())
            if node_block_id not in visited_blocks:
                if node_block_id not in nodes_list_post:
                    nodes_list_post[node_block_id] = my_histogram
                else:
                    combine_histograms(nodes_list_post[node_block_id],
                                       my_histogram)

                if node_block_id not in nodes_list_pre:
                    nodes_list_pre[node_block_id] = visited_nodes
                else:
                    nodes_list_pre[node_block_id] = nodes_list_pre[
                        node_block_id].union(visited_nodes)

        # return histogram. Copy it because it can be in edges_list_post
        return dict(my_histogram)
Ejemplo n.º 3
0
    def __compute_node_count_per_edge(self, child, father, edges_list_post,
                                      edges_list_pre, visited_edges,
                                      visited_nodes, dropped_edges):
        child_id = str(child.data.address)
        father_id = str(
            father.data.block_addresses[-1]) if father.data else None
        nephew_visited_edges = visited_edges.copy()

        if child_id not in self.address_to_block:
            child_block_id = None
        else:
            child_block_id = self.address_to_block[child_id]
        if father_id not in self.address_to_block:
            father_block_id = None
        else:
            father_block_id = self.address_to_block[father_id]

        if child_block_id and father_block_id:
            nephew_visited_edges.add((father_block_id, child_block_id))

            # this edges is considered dropped. Return empty histogram
            if (father_block_id, child_block_id) in dropped_edges:
                return dict()

        # add node even if its block is not in R2
        # this is different with respect to "__compute_block_histogram_per_edge"
        nephew_visited_nodes = visited_nodes.copy()
        nephew_visited_nodes.add(child)

        nephews_blocks = 0
        for nephew in child.children:
            nephew_blocks = self.__compute_node_count_per_edge(
                nephew, child, edges_list_post, edges_list_pre,
                nephew_visited_edges, nephew_visited_nodes, dropped_edges)
            nephews_blocks += nephew_blocks

        # count the node even if its block is not in R2
        # this is different with respect to "__compute_block_histogram_per_edge"
        my_nodes = nephews_blocks + 1
        if child_block_id and father_block_id:
            edge_id = (father_block_id, child_block_id)
            if edge_id not in visited_edges:
                insert_or_add(edges_list_post, edge_id, my_nodes)
                if edge_id not in edges_list_pre:
                    edges_list_pre[edge_id] = visited_nodes
                else:
                    edges_list_pre[edge_id] = edges_list_pre[edge_id].union(
                        visited_nodes)

        return my_nodes
Ejemplo n.º 4
0
    def __compute_node_count_per_block(self, node, nodes_list_post,
                                       nodes_list_pre, visited_blocks,
                                       visited_nodes, dropped_blocks):
        node_id = str(node.data.address)
        child_visited_blocks = visited_blocks.copy()
        child_visited_nodes = visited_nodes.copy()

        if node_id not in self.address_to_block:
            node_block_id = None
        else:
            node_block_id = self.address_to_block[node_id]

        if node_block_id:
            child_visited_blocks.add(node_block_id)

            # this edges is considered dropped. Return empty histogram
            if node_block_id in dropped_blocks:
                return dict()

        # add node even if its block is not in R2
        # this is different with respect to "__compute_block_histogram_per_edge"
        child_visited_nodes.add(node)

        children_blocks = 0
        for child in node.children:
            child_blocks = self.__compute_node_count_per_block(
                child, nodes_list_post, nodes_list_pre, child_visited_blocks,
                child_visited_nodes, dropped_blocks)
            children_blocks += child_blocks

        # count the node even if its block is not in R2
        # this is different with respect to "__compute_block_histogram_per_edge"
        my_nodes = children_blocks + 1
        if node_block_id:
            if node_block_id not in visited_blocks:
                insert_or_add(nodes_list_post, node_block_id, my_nodes)
                if node_block_id not in nodes_list_pre:
                    nodes_list_pre[node_block_id] = visited_nodes
                else:
                    nodes_list_pre[node_block_id] = nodes_list_pre[
                        node_block_id].union(visited_nodes)

        return my_nodes
Ejemplo n.º 5
0
    def __compute_edges(self, child, father, res):
        child_id = str(child.data.address)
        father_id = str(
            father.data.block_addresses[-1]) if father.data else None

        if child_id not in self.address_to_block:
            child_block_id = None
        else:
            child_block_id = self.address_to_block[child_id]
        if father_id not in self.address_to_block:
            father_block_id = None
        else:
            father_block_id = self.address_to_block[father_id]

        if child_block_id and father_block_id:
            insert_or_add(res, (father_block_id, child_block_id), 1)

        for nephew in child.children:
            self.__compute_edges(nephew, child, res)
Ejemplo n.º 6
0
    def compute_block_histogram_per_block(self, dropped_nodes=set()):
        if self.symb_tree.is_empty():
            return dict(), dict(), dict()

        blocks_histogram_post = dict()
        blocks_histogram_pre = dict()
        root_histogram = self.__compute_block_histogram_per_block(
            self.symb_tree.root.children[0], blocks_histogram_post,
            blocks_histogram_pre, set(), set(), dropped_nodes)

        # calculate histogram pre
        for b in blocks_histogram_pre:
            visited = blocks_histogram_pre[b]
            new = dict()
            for node in visited:
                block_id = self.address_to_block[str(node.data.address)]
                insert_or_add(new, block_id, 1)
            blocks_histogram_pre[b] = new

        return root_histogram, blocks_histogram_post, blocks_histogram_pre
Ejemplo n.º 7
0
    def __compute_block_histogram_per_edge(self, child, father,
                                           edges_list_post, edges_list_pre,
                                           visited_edges, visited_nodes,
                                           dropped_edges):
        child_id = str(child.data.address)
        father_id = str(
            father.data.block_addresses[-1]) if father.data else None
        nephew_visited_edges = visited_edges.copy()
        nephew_visited_nodes = visited_nodes.copy()

        # find out whether the addresses of child and father are in R2 CFG
        # they cannot be there due to fake angr blocks (simprocedures)
        if child_id not in self.address_to_block:
            child_block_id = None
        else:
            child_block_id = self.address_to_block[child_id]
        if father_id not in self.address_to_block:
            father_block_id = None
        else:
            father_block_id = self.address_to_block[father_id]

        if child_block_id and father_block_id:
            nephew_visited_edges.add((father_block_id, child_block_id))

            # this edges is considered dropped. Return empty histogram
            if (father_block_id, child_block_id) in dropped_edges:
                return dict()

        if child_block_id:
            nephew_visited_nodes.add(child)

        # combine nephew histograms (if any)
        nephews_histogram = dict()
        for nephew in child.children:
            nephew_hist = self.__compute_block_histogram_per_edge(
                nephew, child, edges_list_post, edges_list_pre,
                nephew_visited_edges, nephew_visited_nodes, dropped_edges)
            combine_histograms(nephews_histogram, nephew_hist)

        my_histogram = nephews_histogram

        if child_block_id and father_block_id:
            # the current block is in R2. Add it to the histogram to be returned
            insert_or_add(my_histogram, child_block_id, 1)

            # merge my histogram to edges_list only if the current edge was not visited by parents
            # Otherwise -> double count (see TreeAnalyzerTests.test_6())
            edge_id = (father_block_id, child_block_id)
            if edge_id not in visited_edges:
                if edge_id not in edges_list_post:
                    edges_list_post[edge_id] = my_histogram
                else:
                    combine_histograms(edges_list_post[edge_id], my_histogram)

                if edge_id not in edges_list_pre:
                    edges_list_pre[edge_id] = visited_nodes
                else:
                    edges_list_pre[edge_id] = edges_list_pre[edge_id].union(
                        visited_nodes)

        # return histogram. Copy it because it can be in edges_list_post
        return dict(my_histogram)