mirror of
https://github.com/mandiant/capa.git
synced 2025-12-22 23:26:21 -08:00
main: learn to save off the path to each rule
This commit is contained in:
29
capa/main.py
29
capa/main.py
@@ -583,18 +583,9 @@ def get_rules(rule_path):
|
|||||||
if not os.path.exists(rule_path):
|
if not os.path.exists(rule_path):
|
||||||
raise IOError('%s does not exist or cannot be accessed' % rule_path)
|
raise IOError('%s does not exist or cannot be accessed' % rule_path)
|
||||||
|
|
||||||
rules = []
|
rule_paths = []
|
||||||
if os.path.isfile(rule_path):
|
if os.path.isfile(rule_path):
|
||||||
logger.info('reading rule file: %s', rule_path)
|
rule_paths.append(rule_path)
|
||||||
with open(rule_path, 'rb') as f:
|
|
||||||
rule = capa.rules.Rule.from_yaml(f.read().decode('utf-8'))
|
|
||||||
|
|
||||||
if is_nursery_rule_path(rule_path):
|
|
||||||
rule.meta['nursery'] = True
|
|
||||||
|
|
||||||
rules.append(rule)
|
|
||||||
logger.debug('rule: %s scope: %s', rule.name, rule.scope)
|
|
||||||
|
|
||||||
elif os.path.isdir(rule_path):
|
elif os.path.isdir(rule_path):
|
||||||
logger.info('reading rules from directory %s', rule_path)
|
logger.info('reading rules from directory %s', rule_path)
|
||||||
for root, dirs, files in os.walk(rule_path):
|
for root, dirs, files in os.walk(rule_path):
|
||||||
@@ -603,18 +594,24 @@ def get_rules(rule_path):
|
|||||||
logger.warning('skipping non-.yml file: %s', file)
|
logger.warning('skipping non-.yml file: %s', file)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
path = os.path.join(root, file)
|
rule_path = os.path.join(root, file)
|
||||||
logger.debug('reading rule file: %s', path)
|
rule_paths.append(rule_path)
|
||||||
|
|
||||||
|
rules = []
|
||||||
|
for rule_path in rule_paths:
|
||||||
|
logger.info('reading rule file: %s', rule_path)
|
||||||
try:
|
try:
|
||||||
rule = capa.rules.Rule.from_yaml_file(path)
|
rule = capa.rules.Rule.from_yaml_file(rule_path)
|
||||||
except capa.rules.InvalidRule:
|
except capa.rules.InvalidRule:
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
if is_nursery_rule_path(root):
|
rule.meta['capa/path'] = rule_path
|
||||||
rule.meta['nursery'] = True
|
if is_nursery_rule_path(rule_path):
|
||||||
|
rule.meta['capa/nursery'] = True
|
||||||
|
|
||||||
rules.append(rule)
|
rules.append(rule)
|
||||||
logger.debug('rule: %s scope: %s', rule.name, rule.scope)
|
logger.debug('rule: %s scope: %s', rule.name, rule.scope)
|
||||||
|
|
||||||
return rules
|
return rules
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -566,8 +566,27 @@ class Rule(object):
|
|||||||
continue
|
continue
|
||||||
move_to_end(meta, key)
|
move_to_end(meta, key)
|
||||||
|
|
||||||
|
# these are meta fields that are internal to capa,
|
||||||
|
# and added during rule reading/construction.
|
||||||
|
# they may help use manipulate or index rules,
|
||||||
|
# but should not be exposed to clients.
|
||||||
|
hidden_meta_keys = ("capa/nursery", "capa/path")
|
||||||
|
hidden_meta = {
|
||||||
|
key: meta.get(key)
|
||||||
|
for key in hidden_meta_keys
|
||||||
|
}
|
||||||
|
|
||||||
|
for key in hidden_meta.keys():
|
||||||
|
del meta[key]
|
||||||
|
|
||||||
ostream = six.BytesIO()
|
ostream = six.BytesIO()
|
||||||
yaml.dump(definition, ostream)
|
yaml.dump(definition, ostream)
|
||||||
|
|
||||||
|
for key, value in hidden_meta.items():
|
||||||
|
if value is None:
|
||||||
|
continue
|
||||||
|
meta[key] = value
|
||||||
|
|
||||||
return ostream.getvalue().decode('utf-8').rstrip("\n") + "\n"
|
return ostream.getvalue().decode('utf-8').rstrip("\n") + "\n"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class MissingNamespace(Lint):
|
|||||||
|
|
||||||
def check_rule(self, ctx, rule):
|
def check_rule(self, ctx, rule):
|
||||||
return ('namespace' not in rule.meta and
|
return ('namespace' not in rule.meta and
|
||||||
'nursery' not in rule.meta and
|
not is_nursery_rule(rule) and
|
||||||
'maec/malware-category' not in rule.meta and
|
'maec/malware-category' not in rule.meta and
|
||||||
'lib' not in rule.meta)
|
'lib' not in rule.meta)
|
||||||
|
|
||||||
@@ -250,7 +250,7 @@ def is_nursery_rule(rule):
|
|||||||
For example, they may not have references to public example of a technique.
|
For example, they may not have references to public example of a technique.
|
||||||
Yet, we still want to capture and report on their matches.
|
Yet, we still want to capture and report on their matches.
|
||||||
'''
|
'''
|
||||||
return rule.meta.get('nursery')
|
return rule.meta.get('capa/nursery')
|
||||||
|
|
||||||
|
|
||||||
def lint_rule(ctx, rule):
|
def lint_rule(ctx, rule):
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ def read_rules(rule_directory):
|
|||||||
rules[rule.name] = rule
|
rules[rule.name] = rule
|
||||||
|
|
||||||
if "nursery" in path:
|
if "nursery" in path:
|
||||||
rule.meta["nursery"] = True
|
rule.meta["capa/nursery"] = True
|
||||||
return rules
|
return rules
|
||||||
|
|
||||||
|
|
||||||
@@ -132,10 +132,8 @@ def main(argv=None):
|
|||||||
filename = filename + ".yml"
|
filename = filename + ".yml"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if rule.meta.get("nursery"):
|
if rule.meta.get("capa/nursery"):
|
||||||
directory = os.path.join(args.destination, "nursery")
|
directory = os.path.join(args.destination, "nursery")
|
||||||
# this isn't meant to be written into the rule
|
|
||||||
del rule.meta["nursery"]
|
|
||||||
elif rule.meta.get("lib"):
|
elif rule.meta.get("lib"):
|
||||||
directory = os.path.join(args.destination, "lib")
|
directory = os.path.join(args.destination, "lib")
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user