diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d4c0c7d..2470af58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - dotnet: emit namespace/class features for ldvirtftn/ldftn instructions #1241 @mike-hunhoff - dotnet: emit namespace/class features for type references #1242 @mike-hunhoff - dotnet: extract dotnet and pe format #1187 @mr-tz +- don't render all library rule matches in vverbose output #1174 @mr-tz ### Breaking Changes - remove SMDA backend #1062 @williballenthin diff --git a/capa/render/utils.py b/capa/render/utils.py index 2cf480c9..96abadcd 100644 --- a/capa/render/utils.py +++ b/capa/render/utils.py @@ -24,6 +24,10 @@ def bold2(s: str) -> str: return termcolor.colored(s, "green") +def warn(s: str) -> str: + return termcolor.colored(s, "yellow") + + def format_parts_id(data: Union[rd.AttackSpec, rd.MBCSpec]): """ format canonical representation of ATT&CK/MBC parts and ID diff --git a/capa/render/vverbose.py b/capa/render/vverbose.py index 5950275a..74be65da 100644 --- a/capa/render/vverbose.py +++ b/capa/render/vverbose.py @@ -285,17 +285,24 @@ def render_rules(ostream, doc: rd.ResultDocument): if rule.meta.is_subscope_rule: continue + lib_info = "" count = len(rule.matches) if count == 1: - capability = rutils.bold(rule.meta.name) + if rule.meta.lib: + lib_info = " (library rule)" + capability = "%s%s" % (rutils.bold(rule.meta.name), lib_info) else: - capability = "%s (%d matches)" % (rutils.bold(rule.meta.name), count) + if rule.meta.lib: + lib_info = ", only showing first match of library rule" + capability = "%s (%d matches%s)" % (rutils.bold(rule.meta.name), count, lib_info) ostream.writeln(capability) had_match = True rows = [] - rows.append(("namespace", rule.meta.namespace)) + if not rule.meta.lib: + # library rules should not have a namespace + rows.append(("namespace", rule.meta.namespace)) if rule.meta.maec.analysis_conclusion or rule.meta.maec.analysis_conclusion_ov: rows.append( @@ -355,6 +362,10 @@ def render_rules(ostream, doc: rd.ResultDocument): ostream.write("\n") render_match(ostream, match, indent=1) + if rule.meta.lib: + # only show first match + break + ostream.write("\n") if not had_match: