mirror of
https://github.com/mandiant/capa.git
synced 2025-12-21 23:00:29 -08:00
*: rename OperandImmediate to OperandNumber
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user