capabilities: use dataclasses to represent complicated return types

foo
This commit is contained in:
Willi Ballenthin
2024-12-10 15:58:32 +00:00
committed by Willi Ballenthin
parent 4896ff01d8
commit 8d17319128
21 changed files with 256 additions and 199 deletions

View File

@@ -146,12 +146,12 @@ def get_capa_results(args):
"error": f"unexpected error: {e}",
}
capabilities, counts = capa.capabilities.common.find_capabilities(rules, extractor, disable_progress=True)
capabilities = capa.capabilities.common.find_capabilities(rules, extractor, disable_progress=True)
meta = capa.loader.collect_metadata(argv, args.input_file, format_, os_, [], extractor, counts)
meta.analysis.layout = capa.loader.compute_layout(rules, extractor, capabilities)
meta = capa.loader.collect_metadata(argv, args.input_file, format_, os_, [], extractor, capabilities)
meta.analysis.layout = capa.loader.compute_layout(rules, extractor, capabilities.matches)
doc = rd.ResultDocument.from_capa(meta, rules, capabilities)
doc = rd.ResultDocument.from_capa(meta, rules, capabilities.matches)
return {"path": input_file, "status": "ok", "ok": doc.model_dump()}

View File

@@ -184,25 +184,25 @@ def capa_details(rules_path: Path, input_file: Path, output_format="dictionary")
extractor = capa.loader.get_extractor(
input_file, FORMAT_AUTO, OS_AUTO, capa.main.BACKEND_VIV, [], should_save_workspace=False, disable_progress=True
)
capabilities, counts = capa.capabilities.common.find_capabilities(rules, extractor, disable_progress=True)
capabilities = capa.capabilities.common.find_capabilities(rules, extractor, disable_progress=True)
# collect metadata (used only to make rendering more complete)
meta = capa.loader.collect_metadata([], input_file, FORMAT_AUTO, OS_AUTO, [rules_path], extractor, counts)
meta.analysis.layout = capa.loader.compute_layout(rules, extractor, capabilities)
meta = capa.loader.collect_metadata([], input_file, FORMAT_AUTO, OS_AUTO, [rules_path], extractor, capabilities)
meta.analysis.layout = capa.loader.compute_layout(rules, extractor, capabilities.matches)
capa_output: Any = False
if output_format == "dictionary":
# ...as python dictionary, simplified as textable but in dictionary
doc = rd.ResultDocument.from_capa(meta, rules, capabilities)
doc = rd.ResultDocument.from_capa(meta, rules, capabilities.matches)
capa_output = render_dictionary(doc)
elif output_format == "json":
# render results
# ...as json
capa_output = json.loads(capa.render.json.render(meta, rules, capabilities))
capa_output = json.loads(capa.render.json.render(meta, rules, capabilities.matches))
elif output_format == "texttable":
# ...as human readable text table
capa_output = capa.render.default.render(meta, rules, capabilities)
capa_output = capa.render.default.render(meta, rules, capabilities.matches)
return capa_output

View File

@@ -100,12 +100,12 @@ def main(argv=None):
except capa.main.ShouldExitError as e:
return e.status_code
capabilities, counts = capa.capabilities.common.find_capabilities(rules, extractor)
capabilities = capa.capabilities.common.find_capabilities(rules, extractor)
meta = capa.loader.collect_metadata(argv, args.input_file, input_format, os_, args.rules, extractor, counts)
meta.analysis.layout = capa.loader.compute_layout(rules, extractor, capabilities)
meta = capa.loader.collect_metadata(argv, args.input_file, input_format, os_, args.rules, extractor, capabilities)
meta.analysis.layout = capa.loader.compute_layout(rules, extractor, capabilities.matches)
doc = rd.ResultDocument.from_capa(meta, rules, capabilities)
doc = rd.ResultDocument.from_capa(meta, rules, capabilities.matches)
pb = capa.render.proto.doc_to_pb2(doc)
sys.stdout.buffer.write(pb.SerializeToString(deterministic=True))

View File

@@ -91,7 +91,7 @@ def main():
return -2
rows = []
for name in capabilities.keys():
for name in capabilities.matches.keys():
rule = result_doc.rules[name]
if rule.meta.lib:
continue

View File

@@ -357,10 +357,10 @@ def get_sample_capabilities(ctx: Context, path: Path) -> set[str]:
disable_progress=True,
)
capabilities, _ = capa.capabilities.common.find_capabilities(ctx.rules, extractor, disable_progress=True)
capabilities = capa.capabilities.common.find_capabilities(ctx.rules, extractor, disable_progress=True)
# mypy doesn't seem to be happy with the MatchResults type alias & set(...keys())?
# so we ignore a few types here.
capabilities = set(capabilities.keys()) # type: ignore
capabilities = set(capabilities.matches.keys()) # type: ignore
assert isinstance(capabilities, set)
logger.debug("computed results: %s: %d capabilities", nice_path, len(capabilities))

View File

@@ -155,18 +155,18 @@ def main(argv=None):
except capa.main.ShouldExitError as e:
return e.status_code
capabilities, counts = capa.capabilities.common.find_capabilities(rules, extractor)
capabilities = capa.capabilities.common.find_capabilities(rules, extractor)
meta = capa.loader.collect_metadata(argv, args.input_file, input_format, os_, args.rules, extractor, counts)
meta.analysis.layout = capa.loader.compute_layout(rules, extractor, capabilities)
meta = capa.loader.collect_metadata(argv, args.input_file, input_format, os_, args.rules, extractor, capabilities)
meta.analysis.layout = capa.loader.compute_layout(rules, extractor, capabilities.matches)
if capa.capabilities.common.has_file_limitation(rules, capabilities):
if capa.capabilities.common.has_file_limitation(rules, capabilities.matches):
# bail if capa encountered file limitation e.g. a packed binary
# do show the output in verbose mode, though.
if not (args.verbose or args.vverbose or args.json):
return capa.main.E_FILE_LIMITATION
doc = rd.ResultDocument.from_capa(meta, rules, capabilities)
doc = rd.ResultDocument.from_capa(meta, rules, capabilities.matches)
print(render_matches_by_function(doc))
colorama.deinit()