From 9da4ff10da8642348de0ad02558a15ce28daf9ff Mon Sep 17 00:00:00 2001 From: Willi Ballenthin Date: Thu, 31 Mar 2022 10:37:06 -0600 Subject: [PATCH] *: rename OperandImmediate to OperandNumber --- CHANGELOG.md | 2 +- capa/features/insn.py | 8 ++++---- capa/rules.py | 10 +++++----- tests/fixtures.py | 6 +++--- tests/test_match.py | 12 ++++++------ 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57ae132b..9047b3fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ ### New Features - add new scope "instruction" for matching mnemonics and operands #767 @williballenthin - - add new feature "operand[{0, 1, 2}].immediate" for matching instruction operand immediate values #767 @williballenthin + - add new feature "operand[{0, 1, 2}].number" for matching instruction operand immediate values #767 @williballenthin - add new feature "operand[{0, 1, 2}].offset" for matching instruction operand offsets #767 @williballenthin ### Breaking Changes diff --git a/capa/features/insn.py b/capa/features/insn.py index cb5b1afc..b5873a72 100644 --- a/capa/features/insn.py +++ b/capa/features/insn.py @@ -60,13 +60,13 @@ class _Operand(Feature): return (self.__class__.__name__, [self.index, self.value]) -class OperandImmediate(_Operand): +class OperandNumber(_Operand): # cached names so we don't do extra string formatting every ctor - NAMES = ["operand[%d].immediate" % i for i in range(MAX_OPERAND_INDEX)] + NAMES = ["operand[%d].number" % i for i in range(MAX_OPERAND_INDEX)] - # operand[i].immediate: 0x12 + # operand[i].number: 0x12 def __init__(self, index: int, value: int, description=None): - super(OperandImmediate, self).__init__(index, value, description=description) + super(OperandNumber, self).__init__(index, value, description=description) self.name = self.NAMES[index] def get_value_str(self) -> str: diff --git a/capa/rules.py b/capa/rules.py index f3b03171..d776df4e 100644 --- a/capa/rules.py +++ b/capa/rules.py @@ -125,7 +125,7 @@ SUPPORTED_FEATURES: Dict[str, Set] = { capa.features.common.Bytes, capa.features.insn.Offset, capa.features.insn.Mnemonic, - capa.features.insn.OperandImmediate, + capa.features.insn.OperandNumber, capa.features.insn.OperandOffset, capa.features.common.Characteristic("nzxor"), capa.features.common.Characteristic("peb access"), @@ -365,7 +365,7 @@ def parse_description(s: Union[str, int, bytes], value_type: str, description=No or value_type.startswith(("number/", "offset/")) or ( value_type.startswith("operand[") - and (value_type.endswith("].immediate") or value_type.endswith("].offset")) + and (value_type.endswith("].number") or value_type.endswith("].offset")) ) ): try: @@ -535,8 +535,8 @@ def build_statements(d, scope: str): elif key == "string" and not isinstance(d[key], str): raise InvalidRule("ambiguous string value %s, must be defined as explicit string" % d[key]) - elif key.startswith("operand[") and key.endswith("].immediate"): - index = key[len("operand[") : -len("].immediate")] + elif key.startswith("operand[") and key.endswith("].number"): + index = key[len("operand[") : -len("].number")] try: index = int(index) except ValueError: @@ -544,7 +544,7 @@ def build_statements(d, scope: str): value, description = parse_description(d[key], key, d.get("description")) try: - feature = capa.features.insn.OperandImmediate(index, value, description=description) + feature = capa.features.insn.OperandNumber(index, value, description=description) except ValueError as e: raise InvalidRule(str(e)) ensure_feature_valid_for_scope(scope, feature) diff --git a/tests/fixtures.py b/tests/fixtures.py index ef1935f0..8630bccf 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -418,9 +418,9 @@ FEATURE_PRESENCE_TESTS = sorted( ("mimikatz", "function=0x40105D", capa.features.insn.Mnemonic("xor"), True), ("mimikatz", "function=0x40105D", capa.features.insn.Mnemonic("in"), False), ("mimikatz", "function=0x40105D", capa.features.insn.Mnemonic("out"), False), - # insn/operand.immediate - ("mimikatz", "function=0x40105D,bb=0x401073", capa.features.insn.OperandImmediate(1, 0xFF), True), - ("mimikatz", "function=0x40105D,bb=0x401073", capa.features.insn.OperandImmediate(0, 0xFF), False), + # insn/operand.number + ("mimikatz", "function=0x40105D,bb=0x401073", capa.features.insn.OperandNumber(1, 0xFF), True), + ("mimikatz", "function=0x40105D,bb=0x401073", capa.features.insn.OperandNumber(0, 0xFF), False), # insn/operand.offset ("mimikatz", "function=0x40105D,bb=0x4010B0", capa.features.insn.OperandOffset(0, 4), True), ("mimikatz", "function=0x40105D,bb=0x4010B0", capa.features.insn.OperandOffset(1, 4), False), diff --git a/tests/test_match.py b/tests/test_match.py index 11551fde..e3ec17e5 100644 --- a/tests/test_match.py +++ b/tests/test_match.py @@ -533,7 +533,7 @@ def test_match_not_not(): assert "test rule" in matches -def test_match_operand_immediate(): +def test_match_operand_number(): rule = textwrap.dedent( """ rule: @@ -541,22 +541,22 @@ def test_match_operand_immediate(): name: test rule features: - and: - - operand[0].immediate: 0x10 + - operand[0].number: 0x10 """ ) r = capa.rules.Rule.from_yaml(rule) - assert capa.features.insn.OperandImmediate(0, 0x10) in {capa.features.insn.OperandImmediate(0, 0x10)} + assert capa.features.insn.OperandNumber(0, 0x10) in {capa.features.insn.OperandNumber(0, 0x10)} - _, matches = match([r], {capa.features.insn.OperandImmediate(0, 0x10): {1, 2}}, 0x0) + _, matches = match([r], {capa.features.insn.OperandNumber(0, 0x10): {1, 2}}, 0x0) assert "test rule" in matches # mismatching index - _, matches = match([r], {capa.features.insn.OperandImmediate(1, 0x10): {1, 2}}, 0x0) + _, matches = match([r], {capa.features.insn.OperandNumber(1, 0x10): {1, 2}}, 0x0) assert "test rule" not in matches # mismatching value - _, matches = match([r], {capa.features.insn.OperandImmediate(0, 0x11): {1, 2}}, 0x0) + _, matches = match([r], {capa.features.insn.OperandNumber(0, 0x11): {1, 2}}, 0x0) assert "test rule" not in matches