parse mbc fields

This commit is contained in:
Moritz Raabe
2021-05-21 14:48:51 +02:00
parent ed02088c82
commit f593592ff0
2 changed files with 47 additions and 12 deletions

View File

@@ -179,18 +179,15 @@ def render_mbc(doc, ostream):
if not rule["meta"].get("mbc"):
continue
mbcs = rule["meta"]["mbc"]
if not isinstance(mbcs, list):
raise ValueError("invalid rule: MBC mapping is not a list")
for mbc in rule["meta"]["mbc"]:
id = mbc.get("id")
objective = mbc.get("objective")
behavior = mbc.get("behavior")
method = mbc.get("method")
for mbc in mbcs:
objective, _, rest = mbc.partition("::")
if "::" in rest:
behavior, _, rest = rest.partition("::")
method, _, id = rest.rpartition(" ")
if method:
objectives[objective].add((behavior, method, id))
else:
behavior, _, id = rest.rpartition(" ")
objectives[objective].add((behavior, id))
rows = []
@@ -199,10 +196,10 @@ def render_mbc(doc, ostream):
for spec in sorted(behaviors):
if len(spec) == 2:
behavior, id = spec
inner_rows.append("%s %s" % (rutils.bold(behavior), id))
inner_rows.append("%s [%s]" % (rutils.bold(behavior), id))
elif len(spec) == 3:
behavior, method, id = spec
inner_rows.append("%s::%s %s" % (rutils.bold(behavior), method, id))
inner_rows.append("%s::%s [%s]" % (rutils.bold(behavior), method, id))
else:
raise RuntimeError("unexpected MBC spec format")
rows.append(

View File

@@ -281,6 +281,42 @@ def parse_description(s, value_type, description=None):
return value, description
def parse_meta(meta):
"""
further process meta items such as MBC
"""
mbcs = meta.get("mbc", [])
if not isinstance(mbcs, list):
raise InvalidRule("MBC mapping must be a list")
if mbcs:
meta["mbc"] = [parse_canonical_mbc(mbc) for mbc in mbcs]
# TODO att&ck
return meta
def parse_canonical_mbc(mbc):
"""
parse capa's canonical MBC representation: `OBJECTIVE::Behavior::Method [Identifier]`
"""
objective, _, rest = mbc.partition("::")
if "::" in rest:
behavior, _, rest = rest.partition("::")
method, _, id = rest.rpartition(" ")
else:
behavior, _, id = rest.rpartition(" ")
method = ""
return {
"id": id.lstrip("[").rstrip("]"),
"objective": objective,
"behavior": behavior,
"method": method,
# TODO "micro-behavior": "",
}
def pop_statement_description_entry(d):
"""
extracts the description for statements and removes the description entry from the document
@@ -577,7 +613,9 @@ class Rule(object):
if scope not in SUPPORTED_FEATURES.keys():
raise InvalidRule("{:s} is not a supported scope".format(scope))
return cls(name, scope, build_statements(statements[0], scope), d["rule"]["meta"], definition)
meta = parse_meta(d["rule"]["meta"])
return cls(name, scope, build_statements(statements[0], scope), meta, definition)
@staticmethod
@lru_cache()