def build_module_graph(self): # Build up a list of compressed modules compressed_modules = [] for module in self.modules: compressed = { 'name': module['name'], 'input_data': [], 'output_data': [] } # TODO we are getting doubleups # Add all of our reaction's inputs and outputs for reaction in module['reactions']: for input in reaction['input_data']: if input not in compressed['input_data']: compressed['input_data'].append(input) for outputs in reaction['output_data']: for output in outputs: if output not in compressed['output_data']: compressed['output_data'].append(output) # Add our modules floating inputs and outputs for outputs in module['output_data']: for output in outputs: if output not in compressed['output_data']: compressed['output_data'].append(output) compressed_modules.append(compressed) # Our graph graph = Dot(graph_type='digraph', suppress_disconnected=True, splines=True, overlap='prism10000', layout='fdp', epsilon=0.01, start=int(random.random() * 2**32)) for m1 in compressed_modules: # Add a node for our module itself node = { 'name': '"{}"'.format(m1['name']), 'label': '"{}"'.format(m1['name']), 'shape': 'rect' } graph.add_node(Node(**node)) # Loop through our outputs for output in m1['output_data']: # Loop through the other modules inputs for m2 in compressed_modules: for input in m2['input_data']: edge = self.make_edge(m1['name'], output, m2['name'], input) if edge: graph.add_edge(edge) return graph
def build_reaction_graph(self, group_clusters=True): # A unique identifier for use in the clusters id = 0 # Our graph graph = { 'label': 'Reactions', 'graph_type': 'digraph', 'suppress_disconnected': False, 'splines': 'polyline', 'overlap': 'prism10000', 'layout': 'fdp', 'epsilon': 0.01, 'start': int(random.random() * 2**32) } graph = Dot(**graph) # Loop through each of our modules for m1 in self.modules: if group_clusters: # Add a cluster for the module cluster = Cluster(graph_name=str(id), label='"{}"'.format(m1['name'])) graph.add_subgraph(cluster); id += 1 else: cluster = graph # Add a node for our module itself if m1['output_data']: node = { 'name': '"{}"'.format(m1['name']), 'label': '"{}"'.format(m1['name']), 'shape': 'rect' } cluster.add_node(Node(**node)) for outputs in m1['output_data']: for output in outputs: # Loop through our reactions in all the other modules for m2 in self.modules: for r2 in m2['reactions']: # Get our destination fqn dst_text_dsl = type_to_string(['DSL', r2['dsl']])[4:-1] dst_reaction_identifier = '0x{0:x}<{1}>'.format(r2['address'], dst_text_dsl) dst_fqn = m2['name'] + '::' + dst_reaction_identifier for input in r2['input_data']: edge = self.make_edge(m1['name'], output, dst_fqn, input) if edge: graph.add_edge(edge) # Loop through the reactions of each module for r1 in m1['reactions']: # Get identifiers for this reaction src_text_dsl = type_to_string(['DSL', r1['dsl']])[4:-1] src_reaction_identifier = '0x{0:x}<{1}>'.format(r1['address'], src_text_dsl) src_fqn = m1['name'] + '::' + src_reaction_identifier label = r1['name'] if r1['name'] else src_text_dsl # TODO if the label is Configuration, we need to get the .yaml file to help the label node = { 'name': '"{}"'.format(src_fqn), 'label': '"{}"'.format(label), 'shape': 'rect' } # If we are not grouping clusters, put the owner module here if not group_clusters: node['label'] = '{0}\\n{1}'.format(m1['name'], label) if r1['modifiers'].get('single', False): # TODO make the outline style be dashed? pass # TODO modify the reaction if r1['modifiers'].get('sync', False): # TODO make the outline style be something?? pass # TODO modify the reaction if r1['modifiers'].get('priority', False): if r1['modifiers']['priority'] == 'LOW': node['style'] = 'filled' node['fillcolor'] = '#44FF4444' elif r1['modifiers']['priority'] == 'HIGH': node['style'] = 'filled' node['fillcolor'] = '#FF444444' # Add the node cluster.add_node(Node(**node)) # Go through our own inputs looking for single edged inputs for input in r1['input_data']: edge = self.make_edge(None, None, src_fqn, input) if edge: graph.add_edge(edge) # Go through our outputs for outputs in r1['output_data']: for output in outputs: # Loop through our reactions in all the other modules for m2 in self.modules: for r2 in m2['reactions']: # Get our destination fqn dst_text_dsl = type_to_string(['DSL', r2['dsl']])[4:-1] dst_reaction_identifier = '0x{0:x}<{1}>'.format(r2['address'], dst_text_dsl) dst_fqn = m2['name'] + '::' + dst_reaction_identifier for input in r2['input_data']: edge = self.make_edge(src_fqn, output, dst_fqn, input) if edge: graph.add_edge(edge) return graph
def graphvizPlot(graphity, allAtts): pydotMe = nx.drawing.nx_pydot.to_pydot(graphity) for node in pydotMe.get_nodes(): # get node address to be able to fetch node directly from graphity to preserve data types of attributes nodeaddr = node.to_string().split()[0].replace('\"', '') finalString = '' if node.get('calls') != '[]' or node.get('strings') != '[]': finalList = [] # fetching string and call lists directly from graphity callList = graphity.node[nodeaddr]['calls'] stringList = graphity.node[nodeaddr]['strings'] for item in callList: finalList.append(str(item[0]) + ": [C] " + str(item[1])) for otem in stringList: finalList.append(str(otem[0]) + ": [S] " + str(otem[1])) finalList.sort() finalString = '\n'.join(finalList) if node.get('functiontype') == 'Export': label = "Export " + nodeaddr + node.get('alias') label = label + "\n" + finalString node.set_fillcolor('skyblue') node.set_style('filled,setlinewidth(3.0)') node.set_label(label) elif node.get('functiontype') == 'Callback': label = "Callback " + nodeaddr + "\n" + finalString node.set_fillcolor('darkolivegreen1') node.set_style('filled,setlinewidth(3.0)') node.set_label(label) elif finalString != '': finalString = nodeaddr + "\n" + finalString node.set_fillcolor('lightpink1') node.set_style('filled,setlinewidth(3.0)') node.set_label(finalString) graphinfo = "SAMPLE " + allAtts['filename'] + "\nType: " + allAtts[ 'filetype'] + "\nSize: " + str( allAtts['filesize'] ) + "\nMD5: " + allAtts['md5'] + "\nImphash:\t\t" + allAtts[ 'imphash'] + "\nCompilation time:\t" + allAtts[ 'compilationts'] + "\nEntrypoint section:\t" + allAtts[ 'sectionep'] titleNode = Node() titleNode.set_label(graphinfo) titleNode.set_shape('rectangle') titleNode.set_fillcolor('grey') titleNode.set_style('filled') pydotMe.add_node(titleNode) graphname = allAtts['filename'] + ".png" try: # TODO pydotplus throws an error sometimes (Error: /tmp/tmp6XgKth: syntax error in line 92 near '[') look into pdp code to see why pydotMe.write_png( os.path.join(os.path.abspath(os.path.dirname(__file__)), graphname)) except Exception as e: print("ERROR drawing graph") print(str(e))
def plotSeGraph(graphity): pydotMe = nx.drawing.nx_pydot.to_pydot(graphity) for node in pydotMe.get_nodes(): finalString = '' if node.get('calls') != '[]' or node.get('strings') != '[]': # TODO THE single ugliest piece of code I ever wrote. Now I'll promise to fix this in the future, priority -1... duh finalList = [] for item in node.get('calls').split('[\''): if item.startswith('0x'): stuff = item.split('\'') finalList.append(str(stuff[0]) + ": [C] " + str(stuff[2])) try: for otherItem in node.get('strings').split('[\''): if otherItem.startswith('0x'): stuff = otherItem.split('\'') finalList.append(str(stuff[0]) + ": [S] " + str(stuff[2])) except: print "Trouble with string " + str(stuff) finalList.sort() finalString = '\n'.join(finalList) if node.get('type') == 'Export': label = "Export " + node.get('alias') label = label + "\n" + finalString node.set_fillcolor('skyblue') node.set_style('filled,setlinewidth(3.0)') node.set_label(label) elif node.get('type') == 'Callback': label = "Callback " + "\n" + finalString node.set_fillcolor('darkolivegreen1') node.set_style('filled,setlinewidth(3.0)') node.set_label(label) elif finalString != '': nodeaddr = node.to_string().split()[0] # dirrty hack ^^ finalString = nodeaddr + "\n" + finalString node.set_fillcolor('lightpink1') node.set_style('filled,setlinewidth(3.0)') node.set_label(finalString) allAtts = getAllAttributes(sys.argv[1]) graphinfo = "SAMPLE " + allAtts['filename'] + "\nType: " + allAtts['filetype'] + "\nSize: " + str(allAtts['filesize']) + "\nMD5: " + allAtts['md5'] + "\nImphash:\t\t" + allAtts['imphash'] + "\nCompilation time:\t" + allAtts['compilationts'] + "\nEntrypoint section:\t" + allAtts['sectionep'] titleNode = Node() titleNode.set_label(graphinfo) titleNode.set_shape('rectangle') titleNode.set_fillcolor('red') titleNode.set_style('filled') pydotMe.add_node(titleNode) graphname = os.path.basename(sys.argv[1]) + ".png" try: # TODO pydotplus throws an error sometimes (Error: /tmp/tmp6XgKth: syntax error in line 92 near '[') look into pdp code to see why pydotMe.write_png(os.path.join(os.path.abspath(os.path.dirname(__file__)), graphname)) except Exception as e: print "ERROR drawing graph" print str(e)
def build_module_graph(self): # Build up a list of compressed modules compressed_modules = [] for module in self.modules: compressed = { "name": module["name"], "input_data": [], "output_data": [] } # TODO we are getting doubleups # Add all of our reaction's inputs and outputs for reaction in module["reactions"]: for input in reaction["input_data"]: if input not in compressed["input_data"]: compressed["input_data"].append(input) for outputs in reaction["output_data"]: for output in outputs: if output not in compressed["output_data"]: compressed["output_data"].append(output) # Add our modules floating inputs and outputs for outputs in module["output_data"]: for output in outputs: if output not in compressed["output_data"]: compressed["output_data"].append(output) compressed_modules.append(compressed) # Our graph graph = Dot( graph_type="digraph", suppress_disconnected=True, splines=True, overlap="prism10000", layout="fdp", epsilon=0.01, start=int(random.random() * 2**32), ) for m1 in compressed_modules: # Add a node for our module itself node = { "name": '"{}"'.format(m1["name"]), "label": '"{}"'.format(m1["name"]), "shape": "rect" } graph.add_node(Node(**node)) # Loop through our outputs for output in m1["output_data"]: # Loop through the other modules inputs for m2 in compressed_modules: for input in m2["input_data"]: edge = self.make_edge(m1["name"], output, m2["name"], input) if edge: graph.add_edge(edge) return graph
def build_reaction_graph(self, group_clusters=True): # A unique identifier for use in the clusters id = 0 # Our graph graph = { "label": "Reactions", "graph_type": "digraph", "suppress_disconnected": False, "splines": "polyline", "overlap": "prism10000", "layout": "fdp", "epsilon": 0.01, "start": int(random.random() * 2**32), } graph = Dot(**graph) # Loop through each of our modules for m1 in self.modules: if group_clusters: # Add a cluster for the module cluster = Cluster(graph_name=str(id), label='"{}"'.format(m1["name"])) graph.add_subgraph(cluster) id += 1 else: cluster = graph # Add a node for our module itself if m1["output_data"]: node = { "name": '"{}"'.format(m1["name"]), "label": '"{}"'.format(m1["name"]), "shape": "rect" } cluster.add_node(Node(**node)) for outputs in m1["output_data"]: for output in outputs: # Loop through our reactions in all the other modules for m2 in self.modules: for r2 in m2["reactions"]: # Get our destination fqn dst_text_dsl = type_to_string( ["DSL", r2["dsl"]])[4:-1] dst_reaction_identifier = "0x{0:x}<{1}>".format( r2["address"], dst_text_dsl) dst_fqn = m2[ "name"] + "::" + dst_reaction_identifier for input in r2["input_data"]: edge = self.make_edge( m1["name"], output, dst_fqn, input) if edge: graph.add_edge(edge) # Loop through the reactions of each module for r1 in m1["reactions"]: # Get identifiers for this reaction src_text_dsl = type_to_string(["DSL", r1["dsl"]])[4:-1] src_reaction_identifier = "0x{0:x}<{1}>".format( r1["address"], src_text_dsl) src_fqn = m1["name"] + "::" + src_reaction_identifier label = r1["name"] if r1["name"] else src_text_dsl # TODO if the label is Configuration, we need to get the .yaml file to help the label node = { "name": '"{}"'.format(src_fqn), "label": '"{}"'.format(label), "shape": "rect" } # If we are not grouping clusters, put the owner module here if not group_clusters: node["label"] = "{0}\\n{1}".format(m1["name"], label) if r1["modifiers"].get("single", False): # TODO make the outline style be dashed? pass # TODO modify the reaction if r1["modifiers"].get("sync", False): # TODO make the outline style be something?? pass # TODO modify the reaction if r1["modifiers"].get("priority", False): if r1["modifiers"]["priority"] == "LOW": node["style"] = "filled" node["fillcolor"] = "#44FF4444" elif r1["modifiers"]["priority"] == "HIGH": node["style"] = "filled" node["fillcolor"] = "#FF444444" # Add the node cluster.add_node(Node(**node)) # Go through our own inputs looking for single edged inputs for input in r1["input_data"]: edge = self.make_edge(None, None, src_fqn, input) if edge: graph.add_edge(edge) # Go through our outputs for outputs in r1["output_data"]: for output in outputs: # Loop through our reactions in all the other modules for m2 in self.modules: for r2 in m2["reactions"]: # Get our destination fqn dst_text_dsl = type_to_string( ["DSL", r2["dsl"]])[4:-1] dst_reaction_identifier = "0x{0:x}<{1}>".format( r2["address"], dst_text_dsl) dst_fqn = m2[ "name"] + "::" + dst_reaction_identifier for input in r2["input_data"]: edge = self.make_edge( src_fqn, output, dst_fqn, input) if edge: graph.add_edge(edge) return graph