diff --git a/capa/features/__init__.py b/capa/features/__init__.py index 2f14a75e..25ad5bb4 100644 --- a/capa/features/__init__.py +++ b/capa/features/__init__.py @@ -49,7 +49,6 @@ class Feature(object): if arch is not None: if arch not in VALID_ARCH: - print(value, arch, description) raise ValueError("arch '%s' must be one of %s" % (arch, VALID_ARCH)) self.name = self.__class__.__name__.lower() + "/" + arch else: diff --git a/capa/features/extractors/ida/insn.py b/capa/features/extractors/ida/insn.py index e72970c7..fa0183ec 100644 --- a/capa/features/extractors/ida/insn.py +++ b/capa/features/extractors/ida/insn.py @@ -19,7 +19,13 @@ _file_imports_cache = None def get_arch(): - # https://reverseengineering.stackexchange.com/a/11398/17194 + """ + fetch the ARCH_* constant for the currently open workspace. + we expect this routine to be pretty lightweight, so we don't cache it. + + via Tamir Bahar/@tmr232 + https://reverseengineering.stackexchange.com/a/11398/17194 + """ info = idaapi.get_inf_structure() if info.is_64bit(): return ARCH_X64 diff --git a/capa/rules.py b/capa/rules.py index 88520527..52b0ba39 100644 --- a/capa/rules.py +++ b/capa/rules.py @@ -10,6 +10,7 @@ import uuid import codecs import logging import binascii +import functools import six import ruamel.yaml @@ -197,12 +198,18 @@ def parse_feature(key): return capa.features.insn.Number elif key.startswith("number/"): arch = key.partition("/")[2] - return lambda *args, **kwargs: capa.features.insn.Number(*args, arch=arch, **kwargs) + # the other handlers here return constructors for features, + # and we want to as well, + # however, we need to preconfigure one of the arguments (`arch`). + # so, instead we return a partially-applied function that + # provides `arch` to the feature constructor. + # it forwards any other arguments provided to the closure along to the constructor. + return functools.partial(capa.features.insn.Number, arch=arch) elif key == "offset": return capa.features.insn.Offset elif key.startswith("offset/"): arch = key.partition("/")[2] - return lambda *args, **kwargs: capa.features.insn.Offset(*args, arch=arch, **kwargs) + return functools.partial(capa.features.insn.Offset, arch=arch) elif key == "mnemonic": return capa.features.insn.Mnemonic elif key == "basic blocks":