1
2
3
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
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
23 self.results = results
24
25 self.addMetadata()
26 self.addObjects()
27 self.addRelations()
28
29 self.output()
30
56
58 """Adds objects elements."""
59
60
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
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
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
120
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
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
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
147 if "network" in self.results and isinstance(self.results["network"], dict):
148
149 for req in self.objects.get_uri():
150
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
156 found = None
157 for obj in self.objects.get_ip():
158 if ip == obj.get_startAddress().get_valueOf_():
159 found = obj
160
161 if found is None:
162 found = self.createIpObject(ip)
163 self.objects.add_ip(found)
164
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
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
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
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
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
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
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