diff --git a/capa/features/extractors/viv/__init__.py b/capa/features/extractors/viv/__init__.py index c6511215..47581236 100644 --- a/capa/features/extractors/viv/__init__.py +++ b/capa/features/extractors/viv/__init__.py @@ -8,11 +8,7 @@ import types -import file -import insn -import function import viv_utils -import basicblock import capa.features.extractors import capa.features.extractors.viv.file @@ -42,7 +38,7 @@ def add_va_int_cast(o): this bit of skullduggery lets use cast viv-utils objects as ints. the correct way of doing this is to update viv-utils (or subclass the objects here). """ - setattr(o, "__int__", types.MethodType(get_va, o, type(o))) + setattr(o, "__int__", types.MethodType(get_va, o)) return o diff --git a/capa/features/extractors/viv/basicblock.py b/capa/features/extractors/viv/basicblock.py index 69ae94f6..76ffefe6 100644 --- a/capa/features/extractors/viv/basicblock.py +++ b/capa/features/extractors/viv/basicblock.py @@ -125,11 +125,16 @@ def get_printable_len(oper): def is_printable_ascii(chars): - return all(ord(c) < 127 and c in string.printable for c in chars) + try: + chars_str = chars.decode("ascii") + except UnicodeDecodeError: + return False + else: + return all(c in string.printable for c in chars_str) def is_printable_utf16le(chars): - if all(c == "\x00" for c in chars[1::2]): + if all(c == b"\x00" for c in chars[1::2]): return is_printable_ascii(chars[::2]) diff --git a/capa/main.py b/capa/main.py index 27d5a9c3..2bb14ade 100644 --- a/capa/main.py +++ b/capa/main.py @@ -32,7 +32,7 @@ import capa.features.extractors from capa.helpers import oint, get_file_taste RULES_PATH_DEFAULT_STRING = "(embedded rules)" -SUPPORTED_FILE_MAGIC = set(["MZ"]) +SUPPORTED_FILE_MAGIC = set([b"MZ"]) logger = logging.getLogger("capa") @@ -304,19 +304,33 @@ class UnsupportedRuntimeError(RuntimeError): def get_extractor_py3(path, format, disable_progress=False): - from smda.SmdaConfig import SmdaConfig - from smda.Disassembler import Disassembler + if False: + from smda.SmdaConfig import SmdaConfig + from smda.Disassembler import Disassembler - import capa.features.extractors.smda + import capa.features.extractors.smda - smda_report = None - with halo.Halo(text="analyzing program", spinner="simpleDots", stream=sys.stderr, enabled=not disable_progress): - config = SmdaConfig() - config.STORE_BUFFER = True - smda_disasm = Disassembler(config) - smda_report = smda_disasm.disassembleFile(path) + smda_report = None + with halo.Halo(text="analyzing program", spinner="simpleDots", stream=sys.stderr, enabled=not disable_progress): + config = SmdaConfig() + config.STORE_BUFFER = True + smda_disasm = Disassembler(config) + smda_report = smda_disasm.disassembleFile(path) - return capa.features.extractors.smda.SmdaFeatureExtractor(smda_report, path) + return capa.features.extractors.smda.SmdaFeatureExtractor(smda_report, path) + else: + import capa.features.extractors.viv + + with halo.Halo(text="analyzing program", spinner="simpleDots", stream=sys.stderr, enabled=not disable_progress): + vw = get_workspace(path, format, should_save=False) + + try: + vw.saveWorkspace() + except IOError: + # see #168 for discussion around how to handle non-writable directories + logger.info("source directory is not writable, won't save intermediate workspace") + + return capa.features.extractors.viv.VivisectFeatureExtractor(vw, path) def get_extractor(path, format, disable_progress=False): diff --git a/setup.py b/setup.py index 4caaa749..c739f1b7 100644 --- a/setup.py +++ b/setup.py @@ -27,6 +27,8 @@ if sys.version_info >= (3, 0): # py3 requirements.append("halo") requirements.append("networkx") + requirements.append("vivisect @ git+https://github.com/Ana06/vivisect@py-3#egg=vivisect") + requirements.append("viv-utils==0.3.19") requirements.append("smda==1.5.13") else: # py2