From 0358b46fcd57263720428728246aa745fecd0803 Mon Sep 17 00:00:00 2001 From: Pratham Chauhan Date: Thu, 23 Mar 2023 18:07:03 +0530 Subject: [PATCH] add FORMAT_RESULT --- capa/features/common.py | 1 + capa/features/extractors/common.py | 9 ++++++++- capa/main.py | 19 ++++++++++++------- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/capa/features/common.py b/capa/features/common.py index d2f1a4ff..b6c89ed9 100644 --- a/capa/features/common.py +++ b/capa/features/common.py @@ -448,6 +448,7 @@ FORMAT_AUTO = "auto" FORMAT_SC32 = "sc32" FORMAT_SC64 = "sc64" FORMAT_FREEZE = "freeze" +FORMAT_RESULT = "result" FORMAT_UNKNOWN = "unknown" diff --git a/capa/features/extractors/common.py b/capa/features/extractors/common.py index d72fcefd..dc5d1c3a 100644 --- a/capa/features/extractors/common.py +++ b/capa/features/extractors/common.py @@ -10,7 +10,7 @@ import capa.features import capa.features.extractors.elf import capa.features.extractors.pefile import capa.features.extractors.strings -from capa.features.common import OS, FORMAT_PE, FORMAT_ELF, OS_WINDOWS, FORMAT_FREEZE, Arch, Format, String, Feature +from capa.features.common import OS, FORMAT_PE, FORMAT_ELF, OS_ANY, OS_WINDOWS, FORMAT_FREEZE, FORMAT_RESULT, ARCH_ANY, Arch, Format, String, Feature from capa.features.freeze import is_freeze from capa.features.address import NO_ADDRESS, Address, FileOffsetAddress @@ -35,6 +35,8 @@ def extract_format(buf) -> Iterator[Tuple[Feature, Address]]: yield Format(FORMAT_ELF), NO_ADDRESS elif is_freeze(buf): yield Format(FORMAT_FREEZE), NO_ADDRESS + elif buf.startswith(b"{\"meta\":"): + yield Format(FORMAT_RESULT), NO_ADDRESS else: # we likely end up here: # 1. handling a file format (e.g. macho) @@ -51,6 +53,9 @@ def extract_arch(buf) -> Iterator[Tuple[Feature, Address]]: elif buf.startswith(b"\x7fELF"): with contextlib.closing(io.BytesIO(buf)) as f: arch = capa.features.extractors.elf.detect_elf_arch(f) + + elif buf.startswith(b"{\"meta\":"): + arch = ARCH_ANY if arch not in capa.features.common.VALID_ARCH: logger.debug("unsupported arch: %s", arch) @@ -79,6 +84,8 @@ def extract_os(buf) -> Iterator[Tuple[Feature, Address]]: elif buf.startswith(b"\x7fELF"): with contextlib.closing(io.BytesIO(buf)) as f: os = capa.features.extractors.elf.detect_elf_os(f) + elif buf.startswith(b"{\"meta\":"): + os = OS_ANY if os not in capa.features.common.VALID_OS: logger.debug("unsupported os: %s", os) diff --git a/capa/main.py b/capa/main.py index 6d024778..338a3f34 100644 --- a/capa/main.py +++ b/capa/main.py @@ -65,6 +65,7 @@ from capa.features.common import ( FORMAT_SC64, FORMAT_DOTNET, FORMAT_FREEZE, + FORMAT_RESULT ) from capa.features.address import NO_ADDRESS, Address from capa.features.extractors.base_extractor import BBHandle, InsnHandle, FunctionHandle, FeatureExtractor @@ -1123,8 +1124,11 @@ def main(argv=None): if not (args.verbose or args.vverbose or args.json): logger.debug("file limitation short circuit, won't analyze fully.") return E_FILE_LIMITATION - - if format_ == FORMAT_FREEZE: + if format_ == FORMAT_RESULT: + with open(args.sample, "rb") as f: + buf = f.read() + print(buf) + elif format_ == FORMAT_FREEZE: with open(args.sample, "rb") as f: extractor = capa.features.freeze.load(f.read()) else: @@ -1153,12 +1157,13 @@ def main(argv=None): except UnsupportedOSError: log_unsupported_os_error() return E_INVALID_FILE_OS + + if not FORMAT_RESULT: + meta = collect_metadata(argv, args.sample, args.rules, extractor) - meta = collect_metadata(argv, args.sample, args.rules, extractor) - - capabilities, counts = find_capabilities(rules, extractor, disable_progress=args.quiet) - meta["analysis"].update(counts) - meta["analysis"]["layout"] = compute_layout(rules, extractor, capabilities) + capabilities, counts = find_capabilities(rules, extractor, disable_progress=args.quiet) + meta["analysis"].update(counts) + meta["analysis"]["layout"] = compute_layout(rules, extractor, capabilities) if has_file_limitation(rules, capabilities): # bail if capa encountered file limitation e.g. a packed binary