diff --git a/capa/features/common.py b/capa/features/common.py index 998345ce..75537c73 100644 --- a/capa/features/common.py +++ b/capa/features/common.py @@ -220,11 +220,11 @@ class _MatchedSubstring(Substring): note: this type should only ever be constructed by `Substring.evaluate()`. it is not part of the public API. """ - def __init__(self, substring: Substring, matches): + def __init__(self, substring: Substring, matches: Dict[str, Set[Address]]): """ args: - substring (Substring): the substring feature that matches. - match (Dict[string, List[int]]|None): mapping from matching string to its locations. + substring: the substring feature that matches. + match: mapping from matching string to its locations. """ super(_MatchedSubstring, self).__init__(str(substring.value), description=substring.description) # we want this to collide with the name of `Substring` above, @@ -317,11 +317,11 @@ class _MatchedRegex(Regex): note: this type should only ever be constructed by `Regex.evaluate()`. it is not part of the public API. """ - def __init__(self, regex: Regex, matches): + def __init__(self, regex: Regex, matches: Dict[str, Set[Address]]): """ args: - regex (Regex): the regex feature that matches. - match (Dict[string, List[int]]|None): mapping from matching string to its locations. + regex: the regex feature that matches. + matches: mapping from matching string to its locations. """ super(_MatchedRegex, self).__init__(str(regex.value), description=regex.description) # we want this to collide with the name of `Regex` above, diff --git a/capa/features/freeze/__init__.py b/capa/features/freeze/__init__.py index 4162e4ee..d818b779 100644 --- a/capa/features/freeze/__init__.py +++ b/capa/features/freeze/__init__.py @@ -12,7 +12,7 @@ See the License for the specific language governing permissions and limitations import zlib import logging from enum import Enum -from typing import Any, Set, Dict, List +from typing import Any, Set, Dict, List, Tuple from devtools import debug from pydantic import Field, BaseModel @@ -158,28 +158,28 @@ class InstructionFeature(HashableModel): class InstructionFeatures(BaseModel): address: Address - features: List[InstructionFeature] + features: Tuple[InstructionFeature, ...] class BasicBlockFeatures(BaseModel): address: Address - features: List[BasicBlockFeature] - instructions: List[InstructionFeatures] + features: Tuple[BasicBlockFeature, ...] + instructions: Tuple[InstructionFeatures, ...] class FunctionFeatures(BaseModel): address: Address - features: List[FunctionFeature] - basic_blocks: List[BasicBlockFeatures] = Field(alias="basic block") + features: Tuple[FunctionFeature, ...] + basic_blocks: Tuple[BasicBlockFeatures, ...] = Field(alias="basic block") class Config: allow_population_by_field_name = True class Features(BaseModel): - global_: List[GlobalFeature] = Field(alias="global") - file: List[FileFeature] - functions: List[FunctionFeatures] + global_: Tuple[GlobalFeature, ...] = Field(alias="global") + file: Tuple[FileFeature, ...] + functions: Tuple[FunctionFeatures, ...] class Config: allow_population_by_field_name = True diff --git a/capa/features/insn.py b/capa/features/insn.py index 40bb1f26..c62d3ddf 100644 --- a/capa/features/insn.py +++ b/capa/features/insn.py @@ -8,10 +8,17 @@ import abc from typing import Union -import capa.render.utils from capa.features.common import Feature +def hex(n: int) -> str: + """render the given number using upper case hex, like: 0x123ABC""" + if n < 0: + return "-0x%X" % (-n) + else: + return "0x%X" % n + + class API(Feature): def __init__(self, name: str, description=None): super(API, self).__init__(name, description=description) @@ -23,7 +30,7 @@ class Number(Feature): def get_value_str(self): if isinstance(self.value, int): - return capa.render.utils.hex(self.value) + return hex(self.value) elif isinstance(self.value, float): return str(self.value) else: @@ -39,7 +46,7 @@ class Offset(Feature): super(Offset, self).__init__(value, description=description) def get_value_str(self): - return capa.render.utils.hex(self.value) + return hex(self.value) class Mnemonic(Feature): @@ -79,7 +86,7 @@ class OperandNumber(_Operand): def get_value_str(self) -> str: assert isinstance(self.value, int) - return capa.render.utils.hex(self.value) + return hex(self.value) class OperandOffset(_Operand): @@ -93,4 +100,4 @@ class OperandOffset(_Operand): def get_value_str(self) -> str: assert isinstance(self.value, int) - return capa.render.utils.hex(self.value) + return hex(self.value) diff --git a/capa/rules.py b/capa/rules.py index e3796131..650cd84c 100644 --- a/capa/rules.py +++ b/capa/rules.py @@ -1249,7 +1249,7 @@ class RuleSet: # at lower scope, e.g. function scope. # so, we find all dependencies of all rules, and later will filter them down. for rule in rules: - if rule.is_subscope_rule(scope): + if rule.is_subscope_rule(): continue scope_rules.update(get_rules_and_dependencies(rules, rule.name))