mirror of
https://github.com/mandiant/capa.git
synced 2026-01-05 09:17:47 -08:00
Merge branch 'master' of github.com:fireeye/capa
This commit is contained in:
@@ -298,7 +298,7 @@ def extract_insn_peb_access_characteristic_features(f, bb, insn):
|
||||
'''
|
||||
parse peb access from the given function. fs:[0x30] on x86, gs:[0x60] on x64
|
||||
'''
|
||||
# TODO extract x64
|
||||
# TODO handle where fs/gs are loaded into a register or onto the stack and used later
|
||||
|
||||
if insn.mnem not in ['push', 'mov']:
|
||||
return
|
||||
|
||||
@@ -324,14 +324,9 @@ class CapaExplorerDataModel(QtCore.QAbstractItemModel):
|
||||
parent2 = CapaExplorerDefaultItem(parent, '%d or more' % result.statement.count)
|
||||
elif not isinstance(result.statement, (capa.features.Feature, capa.engine.Range, capa.engine.Regex)):
|
||||
# when rending a structural node (and/or/not) then we only care about the node name.
|
||||
'''
|
||||
succs = list(filter(lambda c: bool(c), result.children))
|
||||
if len(succs) == 1:
|
||||
# skip structural node with single succeeding child
|
||||
parent2 = parent
|
||||
else:
|
||||
parent2 = CapaExplorerDefaultItem(parent, result.statement.name.lower())
|
||||
'''
|
||||
if not list(filter(lambda c: bool(c), result.children)):
|
||||
# ignore structural expressions that do not have any successful children (e.g. not)
|
||||
return
|
||||
parent2 = CapaExplorerDefaultItem(parent, result.statement.name.lower())
|
||||
else:
|
||||
# but when rendering a Feature, want to see any arguments to it
|
||||
@@ -383,6 +378,8 @@ class CapaExplorerDataModel(QtCore.QAbstractItemModel):
|
||||
if isinstance(feature, string_view):
|
||||
# TODO: move string collection to item constructor
|
||||
if isinstance(feature, capa.engine.Regex):
|
||||
# rstrip "matched="<string>")" because data already displayed in interface
|
||||
name = name.split(',')[0] + ')'
|
||||
return CapaExplorerStringViewItem(parent, name, ea, feature.match)
|
||||
|
||||
if isinstance(feature, capa.features.Characteristic):
|
||||
|
||||
@@ -351,6 +351,8 @@ class CapaExplorerForm(idaapi.PluginForm):
|
||||
self._model_data.render_capa_results(rules, capabilities)
|
||||
self._render_capa_summary(rules, capabilities)
|
||||
|
||||
self._view_tree.sortByColumn(CapaExplorerDataModel.COLUMN_INDEX_RULE_INFORMATION, Qt.AscendingOrder)
|
||||
|
||||
logger.info('render views completed.')
|
||||
|
||||
def _render_capa_summary(self, ruleset, results):
|
||||
|
||||
33
capa/main.py
33
capa/main.py
@@ -305,7 +305,7 @@ def render_capabilities_concise(results):
|
||||
print(rule)
|
||||
|
||||
|
||||
def render_capabilities_verbose(results):
|
||||
def render_capabilities_verbose(ruleset, results):
|
||||
'''
|
||||
print the matching rules, and the functions in which they matched.
|
||||
|
||||
@@ -321,6 +321,15 @@ def render_capabilities_verbose(results):
|
||||
- 0x40105d
|
||||
'''
|
||||
for rule, ress in results.items():
|
||||
if ruleset.rules[rule].meta.get('capa/subscope-rule', False):
|
||||
# don't display subscope rules
|
||||
continue
|
||||
|
||||
rule_scope = ruleset.rules[rule].scope
|
||||
if rule_scope == capa.rules.FILE_SCOPE:
|
||||
# only display rule name at file scope
|
||||
print('%s' % rule)
|
||||
continue
|
||||
print('%s:' % (rule))
|
||||
seen = set([])
|
||||
for (fva, _) in sorted(ress, key=lambda p: p[0]):
|
||||
@@ -374,7 +383,7 @@ def render_result(res, indent=''):
|
||||
render_result(children, indent=indent + ' ')
|
||||
|
||||
|
||||
def render_capabilities_vverbose(results):
|
||||
def render_capabilities_vverbose(ruleset, results):
|
||||
'''
|
||||
print the matching rules, the functions in which they matched,
|
||||
and the logic tree with annotated matching features.
|
||||
@@ -391,9 +400,18 @@ def render_capabilities_vverbose(results):
|
||||
- virtual address: 0x4010c8
|
||||
'''
|
||||
for rule, ress in results.items():
|
||||
if ruleset.rules[rule].meta.get('capa/subscope-rule', False):
|
||||
# don't display subscope rules
|
||||
continue
|
||||
|
||||
print('rule %s:' % (rule))
|
||||
for (fva, res) in sorted(ress, key=lambda p: p[0]):
|
||||
print(' - function 0x%x:' % (fva))
|
||||
for (va, res) in sorted(ress, key=lambda p: p[0]):
|
||||
rule_scope = ruleset.rules[rule].scope
|
||||
if rule_scope == capa.rules.FILE_SCOPE:
|
||||
# does not make sense to display va at file scope
|
||||
print(' - %s:' % rule_scope)
|
||||
else:
|
||||
print(' - %s 0x%x:' % (rule_scope, va))
|
||||
render_result(res, indent=' ')
|
||||
|
||||
|
||||
@@ -676,6 +694,9 @@ def main(argv=None):
|
||||
if args.tag:
|
||||
rules = rules.filter_rules_by_meta(args.tag)
|
||||
logger.info('selected %s rules', len(rules))
|
||||
for i, r in enumerate(rules.rules, 1):
|
||||
# TODO don't display subscope rules?
|
||||
logger.debug(' %d. %s', i, r)
|
||||
except (IOError, capa.rules.InvalidRule, capa.rules.InvalidRuleSet) as e:
|
||||
logger.error('%s', str(e))
|
||||
return -1
|
||||
@@ -718,9 +739,9 @@ def main(argv=None):
|
||||
return -1
|
||||
|
||||
if args.vverbose:
|
||||
render_capabilities_vverbose(capabilities)
|
||||
render_capabilities_vverbose(rules, capabilities)
|
||||
elif args.verbose:
|
||||
render_capabilities_verbose(capabilities)
|
||||
render_capabilities_verbose(rules, capabilities)
|
||||
else:
|
||||
render_capabilities_default(rules, capabilities)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user