From a07ca443f0c04994cebea651c2d583109f6d0ce0 Mon Sep 17 00:00:00 2001 From: Mike Hunhoff Date: Fri, 24 Feb 2023 07:51:40 -0700 Subject: [PATCH] update OS to match OS_ANY for all supported OSes (#1324) --- CHANGELOG.md | 1 + capa/features/common.py | 14 +++++++++++ tests/test_match.py | 51 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 65 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffb42ff6..263b0477 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ ### Bug Fixes - extractor: fix vivisect loop detection corner case #1310 @mr-tz +- match: extend OS characteristic to match OS_ANY to all supported OSes #1324 @mike-hunhoff ### capa explorer IDA Pro plugin diff --git a/capa/features/common.py b/capa/features/common.py index cf2c02f3..c908d7bc 100644 --- a/capa/features/common.py +++ b/capa/features/common.py @@ -428,6 +428,20 @@ class OS(Feature): super().__init__(value, description=description) self.name = "os" + def evaluate(self, ctx, **kwargs): + capa.perf.counters["evaluate.feature"] += 1 + capa.perf.counters["evaluate.feature." + self.name] += 1 + + for feature, locations in ctx.items(): + if not isinstance(feature, (OS,)): + continue + + assert isinstance(feature.value, str) + if OS_ANY in (self.value, feature.value) or self.value == feature.value: + return Result(True, self, [], locations=locations) + + return Result(False, self, []) + FORMAT_PE = "pe" FORMAT_ELF = "elf" diff --git a/tests/test_match.py b/tests/test_match.py index 2d8b9f2a..510db98f 100644 --- a/tests/test_match.py +++ b/tests/test_match.py @@ -13,7 +13,6 @@ import capa.engine import capa.features.insn import capa.features.common from capa.rules import Scope -from capa.features import * from capa.features.insn import * from capa.features.common import * @@ -626,3 +625,53 @@ def test_match_property_access(): 0x0, ) assert "test rule" not in matches + + +def test_match_os_any(): + rule = textwrap.dedent( + """ + rule: + meta: + name: test rule + features: + - or: + - and: + - or: + - os: windows + - os: linux + - os: macos + - string: "Hello world" + - and: + - os: any + - string: "Goodbye world" + """ + ) + r = capa.rules.Rule.from_yaml(rule) + + _, matches = match( + [r], + {OS(OS_ANY): {1}, String("Hello world"): {1}}, + 0x0, + ) + assert "test rule" in matches + + _, matches = match( + [r], + {OS(OS_WINDOWS): {1}, String("Hello world"): {1}}, + 0x0, + ) + assert "test rule" in matches + + _, matches = match( + [r], + {OS(OS_ANY): {1}, String("Goodbye world"): {1}}, + 0x0, + ) + assert "test rule" in matches + + _, matches = match( + [r], + {OS(OS_WINDOWS): {1}, String("Goodbye world"): {1}}, + 0x0, + ) + assert "test rule" in matches