|
#!/usr/bin/env python |
|
|
|
__author__ = "Tommy Skaug" |
|
__license__ = "Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)" |
|
__version__ = "0.1" |
|
__status__ = "Development" |
|
|
|
#### MALTEGO-CSV |
|
# A Maltego to CSV conversion script |
|
### |
|
|
|
import lxml.etree as et |
|
from optparse import OptionParser |
|
import sys |
|
|
|
|
|
# Various GraphML elements, incl. those used in Maltego |
|
graphml = { |
|
"graph": "{http://graphml.graphdrawing.org/xmlns}graph", |
|
"vertice": "{http://graphml.graphdrawing.org/xmlns}node", |
|
"edge": "{http://graphml.graphdrawing.org/xmlns}edge", |
|
"data": "{http://graphml.graphdrawing.org/xmlns}data", |
|
"properties": "{http://maltego.paterva.com/xml/mtgx}Properties", |
|
"property": "{http://maltego.paterva.com/xml/mtgx}Property", |
|
"value": "{http://maltego.paterva.com/xml/mtgx}Value", |
|
"properties2": "{http://maltego.paterva.com/xml/mtgx}Properties2", |
|
"notes": "{http://maltego.paterva.com/xml/mtgx}Notes", |
|
"bookmarks": "{http://maltego.paterva.com/xml/mtgx}Bookmarks", |
|
"entitylist": "{http://maltego.paterva.com/xml/mtgx}MaltegoEntityList", |
|
"label": "{http://graphml.graphdrawing.org/xmlns}data[@key='label']", |
|
} |
|
|
|
|
|
def getVertices(elements): |
|
""" Takes mtg:MaltegoEntity XML elements as input, returns a list of dicts """ |
|
vertice_list=[] |
|
for e in elements: |
|
attribs = {} |
|
attribs['value']={} |
|
vertice=dict(e.getparent().getparent().items()) |
|
attribs['vertice_id']=vertice['id'] |
|
items=dict(e.items()) |
|
attribs['entity_type']=items['type'] |
|
attribs['entity_id']=items['id'] |
|
properties = e.findall(graphml.get('properties')) |
|
properties2 = e.findall(graphml.get('properties2')) |
|
notes = e.findall(graphml.get('notes')) |
|
bookmarks = e.findall(graphml.get('bookmarks')) |
|
attribs['notes']=notes |
|
|
|
for p in properties: |
|
for data in p.findall(graphml.get('property')): |
|
items=dict(data.items()) |
|
if items['name']=="ipaddress.internal" or items['name']=="whois-info": continue |
|
for d in data.findall(graphml.get('value')): |
|
attribs['value'][items['name'].replace("properties.","")]=d.text |
|
|
|
attribs['displayName']=items['displayName'] |
|
attribs['hidden']=items['hidden'] |
|
attribs['name']=items['name'].replace("properties.","") |
|
attribs['nullable']=items['nullable'] |
|
attribs['readonly']=items['readonly'] |
|
attribs['type']=items['type'] |
|
|
|
vertice_list.append(attribs) |
|
return vertice_list |
|
|
|
def printCsv(vertices): |
|
print "entity_type, value" |
|
for vertice in vertices: |
|
if options.entity_filter: |
|
if options.entity_filter==vertice['entity_type']: |
|
if vertice['entity_type']=="maltego.IPv4Address": |
|
type = "ipv4" |
|
val = vertice['value']['ipv4-address'] |
|
elif vertice['entity_type']=="maltego.Domain" or vertice['entity_type']=="maltego.DNSName": |
|
type="fqdn" |
|
val = vertice['value']['fqdn'] |
|
|
|
print u"%s,%s"%(type,val) |
|
else: |
|
if vertice['entity_type']=="maltego.IPv4Address": |
|
type = "ipv4" |
|
val = vertice['value']['ipv4-address'] |
|
elif vertice['entity_type']=="maltego.Domain" or vertice['entity_type']=="maltego.DNSName": |
|
type="fqdn" |
|
val = vertice['value']['fqdn'] |
|
print u"%s,%s"%(type,val) |
|
|
|
def main(): |
|
# By default the Maltego extraction dir layout |
|
if not options.input_file: |
|
document="Graphs/Graph1.graphml" |
|
else: |
|
document=options.input_file |
|
|
|
# The Maltego XML namespace |
|
nsmap = {'mtg': 'http://maltego.paterva.com/xml/mtgx'} |
|
|
|
# Get the GraphML XML tree from file and parse it |
|
doc = et.parse(document) |
|
|
|
# carve out all nodes, here named vertices |
|
vertices = getVertices(doc.xpath('//mtg:MaltegoEntity', namespaces=nsmap)) |
|
|
|
printCsv(vertices) |
|
|
|
if __name__ == "__main__": |
|
parser = OptionParser() |
|
parser.add_option("-f", "--file", dest="input_file", |
|
help="Filter on entity type, ", metavar="inputfile") |
|
parser.add_option("-t", "--entity-type", dest="entity_filter", |
|
help="Filter on entity type, ", metavar="entityfilter") |
|
parser.add_option("-v", "--value", |
|
action="store_false", dest="value_filter", default=True, help="Filter on values") |
|
|
|
(options, args) = parser.parse_args() |
|
|
|
main() |