Skip to content

Commit

Permalink
Merge branch 'master' into feat/lint-duplicate-features
Browse files Browse the repository at this point in the history
  • Loading branch information
v1bh475u authored Jan 29, 2025
2 parents 1bb930b + 83ec75c commit 0ad6795
Show file tree
Hide file tree
Showing 34 changed files with 1,560 additions and 636 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@

### New Features
- add lint for detecting duplicate features in capa-rules #2250 @v1bh475u
- add span-of-calls scope to match features against a across a sliding window of API calls within a thread @williballenthin #2532
-
### Breaking Changes

### New Rules (2)
- add span-of-calls scope to rule format
- capabilities functions return dataclasses instead of tuples

### New Rules (3)

- data-manipulation/encryption/rsa/encrypt-data-using-rsa-via-embedded-library Ana06
- data-manipulation/encryption/use-bigint-function Ana06
- nursery/dynamic-add-veh [email protected]
-

### Bug Fixes
Expand Down
30 changes: 23 additions & 7 deletions capa/capabilities/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,28 @@
import logging
import itertools
import collections
from typing import Any
from typing import Optional
from dataclasses import dataclass

from capa.rules import Scope, RuleSet
from capa.engine import FeatureSet, MatchResults
from capa.features.address import NO_ADDRESS
from capa.render.result_document import LibraryFunction, StaticFeatureCounts, DynamicFeatureCounts
from capa.features.extractors.base_extractor import FeatureExtractor, StaticFeatureExtractor, DynamicFeatureExtractor

logger = logging.getLogger(__name__)


def find_file_capabilities(ruleset: RuleSet, extractor: FeatureExtractor, function_features: FeatureSet):
@dataclass
class FileCapabilities:
features: FeatureSet
matches: MatchResults
feature_count: int


def find_file_capabilities(
ruleset: RuleSet, extractor: FeatureExtractor, function_features: FeatureSet
) -> FileCapabilities:
file_features: FeatureSet = collections.defaultdict(set)

for feature, va in itertools.chain(extractor.extract_file_features(), extractor.extract_global_features()):
Expand All @@ -43,8 +54,8 @@ def find_file_capabilities(ruleset: RuleSet, extractor: FeatureExtractor, functi

file_features.update(function_features)

_, matches = ruleset.match(Scope.FILE, file_features, NO_ADDRESS)
return matches, len(file_features)
features, matches = ruleset.match(Scope.FILE, file_features, NO_ADDRESS)
return FileCapabilities(features, matches, len(file_features))


def has_file_limitation(rules: RuleSet, capabilities: MatchResults, is_standalone=True) -> bool:
Expand All @@ -69,9 +80,14 @@ def has_file_limitation(rules: RuleSet, capabilities: MatchResults, is_standalon
return False


def find_capabilities(
ruleset: RuleSet, extractor: FeatureExtractor, disable_progress=None, **kwargs
) -> tuple[MatchResults, Any]:
@dataclass
class Capabilities:
matches: MatchResults
feature_counts: StaticFeatureCounts | DynamicFeatureCounts
library_functions: Optional[tuple[LibraryFunction, ...]] = None


def find_capabilities(ruleset: RuleSet, extractor: FeatureExtractor, disable_progress=None, **kwargs) -> Capabilities:
from capa.capabilities.static import find_static_capabilities
from capa.capabilities.dynamic import find_dynamic_capabilities

Expand Down
Loading

0 comments on commit 0ad6795

Please sign in to comment.