mirror of
https://github.com/mandiant/capa.git
synced 2025-12-22 07:10:29 -08:00
render: implement default renderer
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
import capa.engine
|
import capa.engine
|
||||||
|
import capa.render.default
|
||||||
|
|
||||||
|
|
||||||
def convert_statement_to_result_document(statement):
|
def convert_statement_to_result_document(statement):
|
||||||
@@ -247,7 +248,7 @@ def render_verbose(rules, capabilities):
|
|||||||
|
|
||||||
def render_default(rules, capabilities):
|
def render_default(rules, capabilities):
|
||||||
doc = convert_capabilities_to_result_document(rules, capabilities)
|
doc = convert_capabilities_to_result_document(rules, capabilities)
|
||||||
return ''
|
return capa.render.default.render_default(doc)
|
||||||
|
|
||||||
|
|
||||||
class CapaJsonObjectEncoder(json.JSONEncoder):
|
class CapaJsonObjectEncoder(json.JSONEncoder):
|
||||||
|
|||||||
69
capa/render/default.py
Normal file
69
capa/render/default.py
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import collections
|
||||||
|
|
||||||
|
import six
|
||||||
|
import tabulate
|
||||||
|
import termcolor
|
||||||
|
|
||||||
|
|
||||||
|
def bold(s):
|
||||||
|
"""draw attention to the given string"""
|
||||||
|
return termcolor.colored(s, 'blue')
|
||||||
|
|
||||||
|
|
||||||
|
def render_capabilities(doc, ostream):
|
||||||
|
rows = []
|
||||||
|
for (namespace, name, rule) in sorted(map(lambda rule: (rule['meta']['namespace'], rule['meta']['name'], rule), doc.values())):
|
||||||
|
if rule['meta'].get('lib'):
|
||||||
|
continue
|
||||||
|
if rule['meta'].get('capa/subscope'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
rows.append((bold(name), namespace))
|
||||||
|
|
||||||
|
ostream.write(tabulate.tabulate(rows, headers=['CAPABILITY', 'NAMESPACE'], tablefmt="psql"))
|
||||||
|
ostream.write("\n")
|
||||||
|
|
||||||
|
|
||||||
|
def render_attack(doc, ostream):
|
||||||
|
tactics = collections.defaultdict(set)
|
||||||
|
for rule in doc.values():
|
||||||
|
if rule['meta'].get('lib'):
|
||||||
|
continue
|
||||||
|
if rule['meta'].get('capa/subscope'):
|
||||||
|
continue
|
||||||
|
if not rule['meta'].get('att&ck'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
for attack in rule['meta']['att&ck']:
|
||||||
|
tactic, _, rest = attack.partition('::')
|
||||||
|
if '::' in rest:
|
||||||
|
technique, _, rest = rest.partition('::')
|
||||||
|
subtechnique, _, id = rest.rpartition(' ')
|
||||||
|
tactics[tactic].add((technique, subtechnique, id))
|
||||||
|
else:
|
||||||
|
technique, _, id = rest.rpartition(' ')
|
||||||
|
tactics[tactic].add((technique, id))
|
||||||
|
|
||||||
|
for tactic, techniques in sorted(tactics.items()):
|
||||||
|
rows = []
|
||||||
|
for spec in sorted(techniques):
|
||||||
|
if len(spec) == 2:
|
||||||
|
technique, id = spec
|
||||||
|
rows.append(("%s %s" % (bold(technique), id), ))
|
||||||
|
elif len(spec) == 3:
|
||||||
|
technique, subtechnique, id = spec
|
||||||
|
rows.append(("%s::%s %s" % (bold(technique), subtechnique, id), ))
|
||||||
|
else:
|
||||||
|
raise RuntimeError("unexpected ATT&CK spec format")
|
||||||
|
ostream.write(tabulate.tabulate(rows, headers=['ATT&CK tactic: ' + bold(tactic.upper())], tablefmt="psql"))
|
||||||
|
ostream.write("\n")
|
||||||
|
|
||||||
|
|
||||||
|
def render_default(doc):
|
||||||
|
ostream = six.StringIO()
|
||||||
|
|
||||||
|
render_attack(doc, ostream)
|
||||||
|
ostream.write("\n")
|
||||||
|
render_capabilities(doc, ostream)
|
||||||
|
|
||||||
|
return ostream.getvalue()
|
||||||
Reference in New Issue
Block a user