Skip to content

Instantly share code, notes, and snippets.

@xlfe
Last active September 14, 2017 22:26
Show Gist options
  • Save xlfe/6e8d644943ffc9a98db799c958436c21 to your computer and use it in GitHub Desktop.
Save xlfe/6e8d644943ffc9a98db799c958436c21 to your computer and use it in GitHub Desktop.
convert an xml openIOC (Stuxnet) to a graphical form
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')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment