diff --git a/capa/main.py b/capa/main.py index 9d3d96e0..d8584d9d 100644 --- a/capa/main.py +++ b/capa/main.py @@ -336,6 +336,7 @@ def collect_metadata(argv, path, format, extractor): return { "timestamp": datetime.datetime.now().isoformat(), + "version": capa.version.__version__, "argv": argv, "sample": { "md5": md5.hexdigest(), diff --git a/capa/render/default.py b/capa/render/default.py index a93bdda7..55cc8639 100644 --- a/capa/render/default.py +++ b/capa/render/default.py @@ -5,6 +5,7 @@ import tabulate import capa.render.utils as rutils +tabulate.PRESERVE_WHITESPACE = True def width(s, character_count): """pad the given string to at least `character_count`""" @@ -14,6 +15,22 @@ def width(s, character_count): return s +def render_meta(doc, ostream): + rows = [( + rutils.bold("Capa Report for"), + rutils.bold(doc["meta"]["sample"]["md5"]), + )] + + for k in ("timestamp", "version"): + rows.append((width(k, 22), width(doc["meta"][k], 60))) + + for k in ("path", "md5"): + rows.append((k, doc["meta"]["sample"][k])) + + ostream.write(tabulate.tabulate(rows, tablefmt="psql")) + ostream.write("\n") + + def render_capabilities(doc, ostream): """ example:: @@ -90,8 +107,10 @@ def render_attack(doc, ostream): def render_default(doc): - ostream = six.StringIO() + ostream = rutils.StringIO() + render_meta(doc, ostream) + ostream.write("\n") render_attack(doc, ostream) ostream.write("\n") render_capabilities(doc, ostream) diff --git a/capa/render/verbose.py b/capa/render/verbose.py index c89697bb..7aebd70b 100644 --- a/capa/render/verbose.py +++ b/capa/render/verbose.py @@ -23,6 +23,22 @@ import capa.render.utils as rutils def render_verbose(doc): ostream = rutils.StringIO() + rows = [( + rutils.bold("Capa Report for"), + rutils.bold(doc["meta"]["sample"]["md5"]), + )] + for k in ("timestamp", "version"): + rows.append((k,doc["meta"][k])) + + for k in ("path", "md5", "sha1", "sha256"): + rows.append((k, doc["meta"]["sample"][k])) + + for k in ("format", "extractor"): + rows.append((k, doc["meta"]["analysis"][k])) + + ostream.writeln(tabulate.tabulate(rows, tablefmt="plain")) + ostream.write("\n") + for rule in rutils.capability_rules(doc): count = len(rule["matches"]) if count == 1: diff --git a/capa/render/vverbose.py b/capa/render/vverbose.py index d738223b..ddfb7592 100644 --- a/capa/render/vverbose.py +++ b/capa/render/vverbose.py @@ -141,6 +141,23 @@ def render_match(ostream, match, indent=0, mode=MODE_SUCCESS): def render_vverbose(doc): ostream = rutils.StringIO() + rows = [( + rutils.bold("Capa Report for"), + rutils.bold(doc["meta"]["sample"]["md5"]), + )] + for k in ("timestamp", "version"): + rows.append((k,doc["meta"][k])) + + for k in ("path", "md5", "sha1", "sha256"): + rows.append((k, doc["meta"]["sample"][k])) + + for k in ("format", "extractor"): + rows.append((k, doc["meta"]["analysis"][k])) + + ostream.writeln(rutils.bold("Capa Report for " + doc["meta"]["sample"]["md5"])) + ostream.writeln(tabulate.tabulate(rows, tablefmt="plain")) + ostream.write("\n") + for rule in rutils.capability_rules(doc): count = len(rule["matches"]) if count == 1: