From 82b95142301ee6f4144279132a0c1e6e4403051c Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Sat, 25 Jul 2020 17:45:25 -0400 Subject: [PATCH 1/2] initial commit of BinaryNinja import script --- scripts/import-to-bn.py | 111 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 scripts/import-to-bn.py diff --git a/scripts/import-to-bn.py b/scripts/import-to-bn.py new file mode 100644 index 00000000..0f0564ed --- /dev/null +++ b/scripts/import-to-bn.py @@ -0,0 +1,111 @@ +""" +Binary Ninja plugin that imports a capa report, +produced via `capa --json /path/to/sample`, +into the current database. + +It will mark up functions with their capa matches, like: + + ; capa: print debug messages (host-interaction/log/debug/write-event) + ; capa: delete service (host-interaction/service/delete) + ; Attributes: bp-based frame + + public UninstallService + UninstallService proc near + ... + +To use, invoke from the Binary Ninja Tools menu, or from the +command-palette. + +This script will verify that the report matches the workspace. +Check the log window for any errors, and/or the summary of changes. + +Derived from: https://github.com/fireeye/capa/blob/master/scripts/import-to-ida.py +""" +import json +import os + +from binaryninja import * + + +def append_func_cmt(bv, va, cmt): + """ + add the given comment to the given function, + if it doesn't already exist. + """ + func = bv.get_function_at(va) + if not func: + raise ValueError("not a function") + + if cmt in func.comment: + return + + func.comment = func.comment + "\n" + cmt + + +def load_analysis(bv): + #not that I expect many files with multiple periods but why not + shortname = '.'.join(os.path.basename(bv.file.filename).split(".")[0:-1]) + dirname = os.path.dirname(bv.file.filename) + log_info(f'dirname: {dirname}\nshortname: {shortname}\n') + if os.access(os.path.join(dirname, shortname + ".js"), os.R_OK): + path = os.path.join(dirname, shortname + ".js") + elif os.access(os.path.join(dirname, shortname + ".json"), os.R_OK): + path = os.path.join(dirname, shortname + ".json") + else: + path = interaction.get_open_filename_input("capa report:", "JSON (*.js *.json);;All Files (*)") + if not path or not os.access(path, os.R_OK): + log_error("Invalid filename.") + return 0 + log_info("Using capa file %s" % path) + + with open(path, "rb") as f: + doc = json.loads(f.read().decode("utf-8")) + + if "meta" not in doc or "rules" not in doc: + log_error("doesn't appear to be a capa report") + return -1 + + a = doc["meta"]["sample"]["md5"].lower() + md5=Transform['MD5'] + rawhex=Transform['RawHex'] + b = rawhex.encode(md5.encode(bv.parent_view.read(bv.parent_view.start, bv.parent_view.end))).decode("utf-8") + if not a == b: + log_error("sample mismatch") + return -2 + + rows = [] + for rule in doc["rules"].values(): + if rule["meta"].get("lib"): + continue + if rule["meta"].get("capa/subscope"): + continue + if rule["meta"]["scope"] != "function": + continue + + name = rule["meta"]["name"] + ns = rule["meta"].get("namespace", "") + for va in rule["matches"].keys(): + va = int(va) + rows.append((ns, name, va)) + + # order by (namespace, name) so that like things show up together + rows = sorted(rows) + for ns, name, va in rows: + if ns: + cmt = "%s (%s)" % (name, ns) + else: + cmt = "%s" % (name,) + + log_info("0x%x: %s" % (va, cmt)) + try: + # message will look something like: + # + # capa: delete service (host-interaction/service/delete) + append_func_cmt(bv, va, "capa: " + cmt) + except ValueError: + continue + + log_info("ok") + + +PluginCommand.register("Load CAPA file", "Loads an analysis file from capa", load_analysis) From f547ca0faef49e3a98b52ec0b14433f6eb354e93 Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Sat, 25 Jul 2020 22:45:51 -0400 Subject: [PATCH 2/2] updates for pull 205 --- scripts/import-to-bn.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/scripts/import-to-bn.py b/scripts/import-to-bn.py index 0f0564ed..33952aef 100644 --- a/scripts/import-to-bn.py +++ b/scripts/import-to-bn.py @@ -1,4 +1,4 @@ -""" +j""" Binary Ninja plugin that imports a capa report, produced via `capa --json /path/to/sample`, into the current database. @@ -16,13 +16,15 @@ It will mark up functions with their capa matches, like: To use, invoke from the Binary Ninja Tools menu, or from the command-palette. +Adapted for Binary Ninja by @psifertex + This script will verify that the report matches the workspace. Check the log window for any errors, and/or the summary of changes. Derived from: https://github.com/fireeye/capa/blob/master/scripts/import-to-ida.py """ -import json import os +import json from binaryninja import * @@ -43,8 +45,7 @@ def append_func_cmt(bv, va, cmt): def load_analysis(bv): - #not that I expect many files with multiple periods but why not - shortname = '.'.join(os.path.basename(bv.file.filename).split(".")[0:-1]) + shortname = os.path.splitext(os.path.basename(bv.file.filename))[0] dirname = os.path.dirname(bv.file.filename) log_info(f'dirname: {dirname}\nshortname: {shortname}\n') if os.access(os.path.join(dirname, shortname + ".js"), os.R_OK): @@ -108,4 +109,4 @@ def load_analysis(bv): log_info("ok") -PluginCommand.register("Load CAPA file", "Loads an analysis file from capa", load_analysis) +PluginCommand.register("Load capa file", "Loads an analysis file from capa", load_analysis)