Package modules :: Package reporting :: Module mmdef
[hide private]
[frames] | no frames]

Source Code for Module modules.reporting.mmdef

  1  # Copyright (C) 2010-2014 Cuckoo Foundation. 
  2  # This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org 
  3  # See the file "docs/LICENSE" for copying permission. 
  4   
  5  import os 
  6  import hashlib 
  7   
  8  import lib.maec.maec11 as maec 
  9  from lib.cuckoo.common.abstracts import Report 
 10  from lib.cuckoo.common.exceptions import CuckooReportError 
 11  from lib.cuckoo.common.utils import datetime_to_iso 
 12   
 13   
14 -class MMDef(Report):
15 """Generates a MAEC Malware Metadata Sharing report.""" 16
17 - def run(self, results):
18 """Writes report. 19 @param results: Cuckoo results dict. 20 @raise CuckooReportError: if fails to write report. 21 """ 22 # Save results. 23 self.results = results 24 # Reporting steps. 25 self.addMetadata() 26 self.addObjects() 27 self.addRelations() 28 # Write report. 29 self.output()
30
31 - def addMetadata(self):
32 """Generates header for MAEC xml and root components.""" 33 if self.results["target"]["category"] == "file": 34 id = "cuckoo:%s" % self.results["target"]["file"]["md5"] 35 elif self.results["target"]["category"] == "url": 36 id = "cuckoo:%s" % hashlib.md5(self.results["target"]["url"]).hexdigest() 37 else: 38 raise CuckooReportError("Unknown target type") 39 40 self.m = maec.malwareMetaData( 41 version="1.1", 42 id=id, 43 author="Cuckoo Sandbox %s" % self.results["info"]["version"], 44 comment="Report created with Cuckoo Sandbox %s automated and open source malware sandbox: http://www.cuckoosandbox.org" % self.results["info"]["version"], 45 timestamp=datetime_to_iso(self.results["info"]["started"]) 46 ) 47 # Objects 48 self.objects = maec.objectsType() 49 self.m.set_objects(self.objects) 50 # Object Properties 51 self.properties = maec.objectPropertiesType() 52 self.m.set_objectProperties(self.properties) 53 # Relationships 54 self.relationships = maec.relationshipsType() 55 self.m.set_relationships(self.relationships)
56
57 - def addObjects(self):
58 """Adds objects elements.""" 59 # File objects 60 # Subject 61 if self.results["target"]["category"] == "file": 62 self.objects.add_file(self.createFileObject(self.results["target"]["file"])) 63 elif self.results["target"]["category"] == "url": 64 self.objects.add_uri(maec.uriObject( 65 id=hashlib.md5(self.results["target"]["url"]).hexdigest(), 66 uriString=self.results["target"]["url"]) 67 ) 68 else: 69 raise CuckooReportError("Unknown target type") 70 71 # Dropped files 72 if "dropped" in self.results and isinstance(self.results["dropped"], list): 73 for f in self.results["dropped"]: 74 found = False 75 for exist in self.objects.get_file(): 76 if exist.get_md5() == f["md5"]: 77 found = True 78 if not found: 79 self.objects.add_file(self.createFileObject(f)) 80 # URI objects 81 if "network" in self.results and isinstance(self.results["network"], dict): 82 if "http" in self.results["network"] and isinstance(self.results["network"]["http"], list): 83 for req in self.results["network"]["http"]: 84 found = False 85 for exist in self.objects.get_uri(): 86 if exist.get_id() == req["uri"]: 87 found = True 88 if not found: 89 self.objects.add_uri(self.createUriObject(req))
90
91 - def createFileObject(self, f):
92 """Creates a file object. 93 @param f: file hash representation from cuckoo dict results. 94 @return: file object. 95 """ 96 file = maec.fileObject( 97 id=f["md5"], 98 fileType=[f["type"]], 99 size=f["size"], 100 crc32=f["crc32"], 101 md5=f["md5"], 102 sha1=f["sha1"], 103 sha512=f["sha512"] 104 ) 105 file.add_extraHash(maec.extraHashType("ssdeep", f["ssdeep"])) 106 # Add related filename 107 prop = maec.objectProperty() 108 prop.add_property(maec.property( 109 type_="filename", 110 valueOf_=f["name"] 111 ) 112 ) 113 prop.set_references( 114 maec.reference( 115 valueOf_="file[@id='%s']" % f["md5"] 116 ) 117 ) 118 self.properties.add_objectProperty(prop) 119 return file
120
121 - def getRelId(self):
122 """Generates incremental relation id. 123 @return: generated id 124 """ 125 try: 126 self.relId = self.relId +1 127 except AttributeError: 128 self.relId = 1 129 return self.relId
130
131 - def addRelations(self):
132 """Adds relationships.""" 133 if self.results["target"]["category"] == "file": 134 src = "file[@id='%s']" % self.results["target"]["file"]["md5"] 135 elif self.results["target"]["category"] == "url": 136 src = "url[@id='%s']" % hashlib.md5(self.results["target"]["url"]).hexdigest() 137 138 # Dropped files 139 for file in self.results["dropped"]: 140 self.relationships.add_relationship(self.createRelation( 141 action="installed", 142 src=src, 143 dst="file[@id='%s']" % file["md5"] 144 ) 145 ) 146 # Network 147 if "network" in self.results and isinstance(self.results["network"], dict): 148 # DNS requests 149 for req in self.objects.get_uri(): 150 # Get IP 151 if "domains" in self.results["network"] and isinstance(self.results["network"]["domains"], list): 152 for res in self.results["network"]["domains"]: 153 if res["domain"] == req.get_hostname(): 154 ip = res["ip"] 155 # Check if obj exist 156 found = None 157 for obj in self.objects.get_ip(): 158 if ip == obj.get_startAddress().get_valueOf_(): 159 found = obj 160 # Create obj 161 if found is None: 162 found = self.createIpObject(ip) 163 self.objects.add_ip(found) 164 # Create relation 165 self.relationships.add_relationship(self.createRelation( 166 action="isServerOfService", 167 src="ip[@id='%s']" % found.id, 168 dst="uri[@id='%s']" % req.id 169 ) 170 ) 171 # HTTP requests 172 if "http" in self.results["network"] and isinstance(self.results["network"]["http"], list): 173 for req in self.results["network"]["http"]: 174 self.relationships.add_relationship(self.createRelation( 175 action="contactedBy", 176 src=src, 177 dst="uri[@id='%s']" % req["uri"] 178 ) 179 )
180
181 - def createRelation(self, action, src, dst):
182 """Creates a relation between objects. 183 @param action: relation type 184 @param src: relation source 185 @param dst: relation target 186 @return: relation object 187 """ 188 return maec.relationship( 189 id=self.getRelId(), 190 type_=action, 191 source=maec.reference( 192 valueOf_=src 193 ), 194 target=maec.reference( 195 valueOf_=dst 196 ) 197 )
198
199 - def createIpObject(self, ip):
200 """Creates an single IP object, not an IP range object. 201 @param ip: IP address 202 @return: IP object 203 """ 204 return maec.IPObject( 205 id="%s-%s" % (ip, ip), 206 startAddress=maec.IPAddress( 207 type_="ipv4", 208 valueOf_=ip 209 ), 210 endAddress=maec.IPAddress( 211 type_="ipv4", 212 valueOf_=ip 213 ) 214 )
215
216 - def createUriObject(self, req):
217 """Creates URI object 218 @param req: HTTP request as described in cuckoo dict 219 @return: created URI object 220 """ 221 uri = maec.uriObject( 222 id=req["uri"], 223 uriString=req["uri"], 224 protocol="http", 225 hostname=req["host"], 226 port=req["port"], 227 path=req["path"], 228 ipProtocol="tcp" 229 ) 230 # Add details 231 prop = maec.objectProperty() 232 prop.add_property(maec.property( 233 type_="httpMethod", 234 valueOf_=req["method"] 235 ) 236 ) 237 if req["method"] == "POST": 238 prop.add_property(maec.property( 239 type_="postData", 240 valueOf_="<![CDATA[%s]]>" % req["body"] 241 ) 242 ) 243 if "user-agent" in req: 244 prop.add_property(maec.property( 245 type_="userAgent", 246 valueOf_=req["user-agent"] 247 ) 248 ) 249 prop.set_references( 250 maec.reference( 251 valueOf_="uri[@id='%s']" % req["uri"] 252 ) 253 ) 254 self.properties.add_objectProperty(prop) 255 return uri
256
257 - def output(self):
258 """Writes report to disk.""" 259 try: 260 report = open(os.path.join(self.reports_path, "report.metadata.xml"), "w") 261 report.write("<?xml version='1.0' ?>\n") 262 report.write("<!--\n") 263 report.write("Cuckoo Sandbox malware analysis report\n") 264 report.write("http://www.cuckoosandbox.org\n") 265 report.write("-->\n") 266 self.m.export(report, 0, namespace_="", namespacedef_="xmlns='http://xml/metadataSharing.xsd' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://xml/metadataSharing.xsd'") 267 report.close() 268 except (TypeError, IOError) as e: 269 raise CuckooReportError("Failed to generate MAEC Metadata report: %s" % e)
270