From 6575a019c3d12a6a153ff09c6d77c096dcefe8f7 Mon Sep 17 00:00:00 2001 From: William Ballenthin Date: Thu, 2 Jul 2020 15:31:08 -0600 Subject: [PATCH] render: add report header and metadata closes #45 --- capa/main.py | 1 + capa/render/default.py | 21 ++++++++++++++++++++- capa/render/verbose.py | 16 ++++++++++++++++ capa/render/vverbose.py | 17 +++++++++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) 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: