convert an xml openIOC (Stuxnet) to a graphical form

Felix Barbalet
2017-09-14T10:06:32Z

generate_ioc_chart.py

| from graphviz import Digraph
| from lxml import etree, objectify
| import random
|
| #https://stackoverflow.com/questions/30232031/how-can-i-strip-namespaces-out-of-an-lxml-tree
| def strip_ns_prefix(tree):
| query = "descendant-or-self::*[namespace-uri()!='']"
| for element in tree.xpath(query):
| element.tag = etree.QName(element).localname
| return tree
|
| xml = strip_ns_prefix(etree.parse('ea3cab0c-72ad-40cc-abbf-90846fa4afec.ioc'))
| root = xml.getroot()
| dot = Digraph()
| ioc = dot.node('root', root.find('short_description').text, style='filled', shape='box')
|
| def add_items(root, items, label='', last_label=None):
| for i in items.xpath('Indicator'):
| add_items(root, i, i.attrib['operator'], label)
| for n,i in enumerate(items.xpath('IndicatorItem')):
| assert i.attrib['condition'] == 'contains'
| dot.node(i.attrib['id'], '{}\n"{}"'.format(
| '\n'.join(i.xpath("Context[@type='mir']/@search")[0].split('/')),
| '\n'.join(i.xpath("Content[@type='string']/text()")[0].split('\\'))
| ))
| dot.edge(root, i.attrib['id'], label=label if n>0 or not last_label else last_label)
| root = i.attrib['id']
|
| # Indicator (operator) -> Indicator / IndicatorItem -> Context (search) -> Context (text)
| add_items('root', root.find('definition'))
| dot.save('ioc.gv')