From ef2cd1df11478a5b9c08c6cec3dbf8dc69f29e09 Mon Sep 17 00:00:00 2001 From: Capa Bot Date: Tue, 10 Mar 2026 11:48:04 +0000 Subject: [PATCH] style: auto-format with black and isort --- .../extractors/binexport2/__init__.py | 1 + .../extractors/binexport2/arch/arm/insn.py | 18 +- .../extractors/binexport2/arch/intel/insn.py | 36 +- .../features/extractors/viv/indirect_calls.py | 2 +- capa/features/extractors/viv/insn.py | 2 +- capa/main.py | 6 +- capa/render/proto/__init__.py | 1 + scripts/bulk-process.py | 1 + scripts/capa2sarif.py | 1 + scripts/detect-binexport2-capabilities.py | 1 + scripts/detect-elf-os.py | 1 + scripts/import-to-bn.py | 1 + scripts/match-function-id.py | 1 + scripts/minimize_vmray_results.py | 1 + scripts/profile-time.py | 1 + scripts/proto-from-results.py | 1 + scripts/proto-to-results.py | 1 + scripts/setup-linter-dependencies.py | 1 + scripts/show-capabilities-by-function.py | 1 + scripts/show-features.py | 1 + tests/test_binexport_accessors.py | 39 +- tests/test_capabilities.py | 132 +--- tests/test_cape_model.py | 6 +- tests/test_drakvuf_models.py | 6 +- tests/test_dynamic_span_of_calls_scope.py | 80 +-- tests/test_fmt.py | 36 +- tests/test_freeze_dynamic.py | 8 +- tests/test_freeze_static.py | 8 +- tests/test_main.py | 70 +-- tests/test_match.py | 200 ++---- tests/test_optimizer.py | 6 +- tests/test_render.py | 30 +- tests/test_rule_cache.py | 16 +- tests/test_rules.py | 592 +++++------------- tests/test_rules_insn_scope.py | 52 +- tests/test_scripts.py | 24 +- tests/test_vmray_model.py | 36 +- 37 files changed, 399 insertions(+), 1021 deletions(-) diff --git a/capa/features/extractors/binexport2/__init__.py b/capa/features/extractors/binexport2/__init__.py index aaa1d911..f27ff79e 100644 --- a/capa/features/extractors/binexport2/__init__.py +++ b/capa/features/extractors/binexport2/__init__.py @@ -20,6 +20,7 @@ Proto files generated via protobuf v24.4: from BinExport2 at 6916731d5f6693c4a4f0a052501fd3bd92cfd08b https://github.com/google/binexport/blob/6916731/binexport2.proto """ + import io import hashlib import logging diff --git a/capa/features/extractors/binexport2/arch/arm/insn.py b/capa/features/extractors/binexport2/arch/arm/insn.py index 8b481040..2cce6831 100644 --- a/capa/features/extractors/binexport2/arch/arm/insn.py +++ b/capa/features/extractors/binexport2/arch/arm/insn.py @@ -84,16 +84,14 @@ def extract_insn_number_features( yield OperandOffset(i, value), ih.address -OFFSET_PATTERNS = BinExport2InstructionPatternMatcher.from_str( - """ +OFFSET_PATTERNS = BinExport2InstructionPatternMatcher.from_str(""" ldr|ldrb|ldrh|ldrsb|ldrsh|ldrex|ldrd|str|strb|strh|strex|strd reg, [reg(not-stack), #int] ; capture #int ldr|ldrb|ldrh|ldrsb|ldrsh|ldrex|ldrd|str|strb|strh|strex|strd reg, [reg(not-stack), #int]! ; capture #int ldr|ldrb|ldrh|ldrsb|ldrsh|ldrex|ldrd|str|strb|strh|strex|strd reg, [reg(not-stack)], #int ; capture #int ldp|ldpd|stp|stpd reg, reg, [reg(not-stack), #int] ; capture #int ldp|ldpd|stp|stpd reg, reg, [reg(not-stack), #int]! ; capture #int ldp|ldpd|stp|stpd reg, reg, [reg(not-stack)], #int ; capture #int - """ -) + """) def extract_insn_offset_features( @@ -117,12 +115,10 @@ def extract_insn_offset_features( yield OperandOffset(match.operand_index, value), ih.address -NZXOR_PATTERNS = BinExport2InstructionPatternMatcher.from_str( - """ +NZXOR_PATTERNS = BinExport2InstructionPatternMatcher.from_str(""" eor reg, reg, reg eor reg, reg, #int - """ -) + """) def extract_insn_nzxor_characteristic_features( @@ -144,11 +140,9 @@ def extract_insn_nzxor_characteristic_features( yield Characteristic("nzxor"), ih.address -INDIRECT_CALL_PATTERNS = BinExport2InstructionPatternMatcher.from_str( - """ +INDIRECT_CALL_PATTERNS = BinExport2InstructionPatternMatcher.from_str(""" blx|bx|blr reg - """ -) + """) def extract_function_indirect_call_characteristic_features( diff --git a/capa/features/extractors/binexport2/arch/intel/insn.py b/capa/features/extractors/binexport2/arch/intel/insn.py index 02e51a6d..ed0f1863 100644 --- a/capa/features/extractors/binexport2/arch/intel/insn.py +++ b/capa/features/extractors/binexport2/arch/intel/insn.py @@ -34,17 +34,14 @@ from capa.features.extractors.binexport2.arch.intel.helpers import SECURITY_COOK logger = logging.getLogger(__name__) -IGNORE_NUMBER_PATTERNS = BinExport2InstructionPatternMatcher.from_str( - """ +IGNORE_NUMBER_PATTERNS = BinExport2InstructionPatternMatcher.from_str(""" ret #int retn #int add reg(stack), #int sub reg(stack), #int - """ -) + """) -NUMBER_PATTERNS = BinExport2InstructionPatternMatcher.from_str( - """ +NUMBER_PATTERNS = BinExport2InstructionPatternMatcher.from_str(""" push #int0 ; capture #int0 # its a little tedious to enumerate all the address forms @@ -64,8 +61,7 @@ NUMBER_PATTERNS = BinExport2InstructionPatternMatcher.from_str( # imagine reg is zero'd out, then this is like `mov reg, #int` # which is not uncommon. lea reg, [reg + #int] ; capture #int - """ -) + """) def extract_insn_number_features( @@ -100,8 +96,7 @@ def extract_insn_number_features( yield OperandOffset(match.operand_index, value), ih.address -OFFSET_PATTERNS = BinExport2InstructionPatternMatcher.from_str( - """ +OFFSET_PATTERNS = BinExport2InstructionPatternMatcher.from_str(""" mov|movzx|movsb|cmp [reg + reg * #int + #int0], #int ; capture #int0 mov|movzx|movsb|cmp [reg * #int + #int0], #int ; capture #int0 mov|movzx|movsb|cmp [reg + reg + #int0], #int ; capture #int0 @@ -114,18 +109,15 @@ OFFSET_PATTERNS = BinExport2InstructionPatternMatcher.from_str( mov|movzx|movsb|cmp|lea reg, [reg * #int + #int0] ; capture #int0 mov|movzx|movsb|cmp|lea reg, [reg + reg + #int0] ; capture #int0 mov|movzx|movsb|cmp|lea reg, [reg(not-stack) + #int0] ; capture #int0 - """ -) + """) # these are patterns that access offset 0 from some pointer # (pointer is not the stack pointer). -OFFSET_ZERO_PATTERNS = BinExport2InstructionPatternMatcher.from_str( - """ +OFFSET_ZERO_PATTERNS = BinExport2InstructionPatternMatcher.from_str(""" mov|movzx|movsb [reg(not-stack)], reg mov|movzx|movsb [reg(not-stack)], #int lea reg, [reg(not-stack)] - """ -) + """) def extract_insn_offset_features( @@ -189,12 +181,10 @@ def is_security_cookie( return False -NZXOR_PATTERNS = BinExport2InstructionPatternMatcher.from_str( - """ +NZXOR_PATTERNS = BinExport2InstructionPatternMatcher.from_str(""" xor|xorpd|xorps|pxor reg, reg xor|xorpd|xorps|pxor reg, #int - """ -) + """) def extract_insn_nzxor_characteristic_features( @@ -228,8 +218,7 @@ def extract_insn_nzxor_characteristic_features( yield Characteristic("nzxor"), ih.address -INDIRECT_CALL_PATTERNS = BinExport2InstructionPatternMatcher.from_str( - """ +INDIRECT_CALL_PATTERNS = BinExport2InstructionPatternMatcher.from_str(""" call|jmp reg0 call|jmp [reg + reg * #int + #int] call|jmp [reg + reg * #int] @@ -237,8 +226,7 @@ INDIRECT_CALL_PATTERNS = BinExport2InstructionPatternMatcher.from_str( call|jmp [reg + reg + #int] call|jmp [reg + #int] call|jmp [reg] - """ -) + """) def extract_function_indirect_call_characteristic_features( diff --git a/capa/features/extractors/viv/indirect_calls.py b/capa/features/extractors/viv/indirect_calls.py index 0f04fccc..d7bbc65c 100644 --- a/capa/features/extractors/viv/indirect_calls.py +++ b/capa/features/extractors/viv/indirect_calls.py @@ -56,7 +56,7 @@ def get_previous_instructions(vw: VivWorkspace, va: int) -> list[int]: if ploc is not None: # from vivisect.const: # location: (L_VA, L_SIZE, L_LTYPE, L_TINFO) - (pva, _, ptype, pinfo) = ploc + pva, _, ptype, pinfo = ploc if ptype == LOC_OP and not (pinfo & IF_NOFALL): ret.append(pva) diff --git a/capa/features/extractors/viv/insn.py b/capa/features/extractors/viv/insn.py index 0b3e79f9..552edfe4 100644 --- a/capa/features/extractors/viv/insn.py +++ b/capa/features/extractors/viv/insn.py @@ -176,7 +176,7 @@ def extract_insn_api_features(fh: FunctionHandle, bb, ih: InsnHandle) -> Iterato elif isinstance(insn.opers[0], envi.archs.i386.disasm.i386RegOper): try: - (_, target) = resolve_indirect_call(f.vw, insn.va, insn=insn) + _, target = resolve_indirect_call(f.vw, insn.va, insn=insn) except NotFoundError: # not able to resolve the indirect call, sorry return diff --git a/capa/main.py b/capa/main.py index ce0191d3..368d3ecd 100644 --- a/capa/main.py +++ b/capa/main.py @@ -945,8 +945,7 @@ def main(argv: Optional[list[str]] = None): argv = sys.argv[1:] desc = "The FLARE team's open-source tool to identify capabilities in executable files." - epilog = textwrap.dedent( - """ + epilog = textwrap.dedent(""" By default, capa uses a default set of embedded rules. You can see the rule set here: https://github.com/mandiant/capa-rules @@ -973,8 +972,7 @@ def main(argv: Optional[list[str]] = None): filter rules by meta fields, e.g. rule name or namespace capa -t "create TCP socket" suspicious.exe - """ - ) + """) parser = argparse.ArgumentParser( description=desc, epilog=epilog, formatter_class=argparse.RawDescriptionHelpFormatter diff --git a/capa/render/proto/__init__.py b/capa/render/proto/__init__.py index 31b272e5..53f942c5 100644 --- a/capa/render/proto/__init__.py +++ b/capa/render/proto/__init__.py @@ -31,6 +31,7 @@ $ protoc.exe --python_out=. --mypy_out=. (e.g. capa/render/proto Alternatively, --pyi_out=. can be used to generate a Python Interface file that supports development """ + import datetime from typing import Any, Union diff --git a/scripts/bulk-process.py b/scripts/bulk-process.py index 768a551b..12d64fed 100644 --- a/scripts/bulk-process.py +++ b/scripts/bulk-process.py @@ -61,6 +61,7 @@ usage: parallelism factor --no-mp disable subprocesses """ + import sys import json import logging diff --git a/scripts/capa2sarif.py b/scripts/capa2sarif.py index 4d4f3f9a..b16d9f08 100644 --- a/scripts/capa2sarif.py +++ b/scripts/capa2sarif.py @@ -28,6 +28,7 @@ Requires: - sarif_om 1.0.4 - jschema_to_python 1.2.3 """ + import sys import json import logging diff --git a/scripts/detect-binexport2-capabilities.py b/scripts/detect-binexport2-capabilities.py index 0a170d29..22615786 100644 --- a/scripts/detect-binexport2-capabilities.py +++ b/scripts/detect-binexport2-capabilities.py @@ -32,6 +32,7 @@ Example: │00000070│ 39 31 37 36 61 64 36 38 ┊ 32 66 66 64 64 36 35 66 │9176ad68┊2ffdd65f│ │00000080│ 30 61 36 36 39 12 28 61 ┊ 34 62 33 35 64 65 37 31 │0a669•(a┊4b35de71│ """ + import sys import logging import argparse diff --git a/scripts/detect-elf-os.py b/scripts/detect-elf-os.py index 33a4640c..65802ea8 100644 --- a/scripts/detect-elf-os.py +++ b/scripts/detect-elf-os.py @@ -18,6 +18,7 @@ detect-elf-os Attempt to detect the underlying OS that the given ELF file targets. """ + import sys import logging import argparse diff --git a/scripts/import-to-bn.py b/scripts/import-to-bn.py index e01b6f87..5496f895 100644 --- a/scripts/import-to-bn.py +++ b/scripts/import-to-bn.py @@ -36,6 +36,7 @@ Check the log window for any errors, and/or the summary of changes. Derived from: https://github.com/mandiant/capa/blob/master/scripts/import-to-ida.py """ + import os import json from pathlib import Path diff --git a/scripts/match-function-id.py b/scripts/match-function-id.py index fd92bf3c..dfcfb72a 100644 --- a/scripts/match-function-id.py +++ b/scripts/match-function-id.py @@ -54,6 +54,7 @@ Example:: 0x44cb60: ? 0x44cba0: __guard_icall_checks_enforced """ + import sys import logging import argparse diff --git a/scripts/minimize_vmray_results.py b/scripts/minimize_vmray_results.py index 9ffb9139..e90c1a17 100644 --- a/scripts/minimize_vmray_results.py +++ b/scripts/minimize_vmray_results.py @@ -16,6 +16,7 @@ """ Extract files relevant to capa analysis from VMRay Analysis Archive and create a new ZIP file. """ + import sys import logging import zipfile diff --git a/scripts/profile-time.py b/scripts/profile-time.py index 8b5ae889..09560450 100644 --- a/scripts/profile-time.py +++ b/scripts/profile-time.py @@ -43,6 +43,7 @@ example: ^^^ --label or git hash """ + import sys import timeit import logging diff --git a/scripts/proto-from-results.py b/scripts/proto-from-results.py index f920b060..7db79af0 100644 --- a/scripts/proto-from-results.py +++ b/scripts/proto-from-results.py @@ -34,6 +34,7 @@ Example: │00000080│ 30 61 36 36 39 12 28 61 ┊ 34 62 33 35 64 65 37 31 │0a669•(a┊4b35de71│ """ + import sys import logging import argparse diff --git a/scripts/proto-to-results.py b/scripts/proto-to-results.py index 3d1590eb..4888fdb3 100644 --- a/scripts/proto-to-results.py +++ b/scripts/proto-to-results.py @@ -37,6 +37,7 @@ Example: ────┴──────────────────────────────────────────────────── """ + import sys import logging import argparse diff --git a/scripts/setup-linter-dependencies.py b/scripts/setup-linter-dependencies.py index 285ed7a1..01e15acc 100644 --- a/scripts/setup-linter-dependencies.py +++ b/scripts/setup-linter-dependencies.py @@ -46,6 +46,7 @@ Example: 2022-01-24 22:35:39,839 [INFO] Starting extraction... 2022-01-24 22:35:42,632 [INFO] Writing results to linter-data.json """ + import json import logging import argparse diff --git a/scripts/show-capabilities-by-function.py b/scripts/show-capabilities-by-function.py index d2c73683..1c69302e 100644 --- a/scripts/show-capabilities-by-function.py +++ b/scripts/show-capabilities-by-function.py @@ -54,6 +54,7 @@ Example:: - connect TCP socket ... """ + import sys import logging import argparse diff --git a/scripts/show-features.py b/scripts/show-features.py index 62da59e1..0004f6c7 100644 --- a/scripts/show-features.py +++ b/scripts/show-features.py @@ -70,6 +70,7 @@ Example:: insn: 0x10001027: mnemonic(shl) ... """ + import sys import logging import argparse diff --git a/tests/test_binexport_accessors.py b/tests/test_binexport_accessors.py index fc5c352b..4c5362c4 100644 --- a/tests/test_binexport_accessors.py +++ b/tests/test_binexport_accessors.py @@ -458,9 +458,7 @@ def test_pattern_parsing(): capture="#int", ) - assert ( - BinExport2InstructionPatternMatcher.from_str( - """ + assert BinExport2InstructionPatternMatcher.from_str(""" # comment br reg br reg(not-stack) @@ -481,10 +479,7 @@ def test_pattern_parsing(): call [reg * #int + #int] call [reg + reg + #int] call [reg + #int] - """ - ).queries - is not None - ) + """).queries is not None def match_address(extractor: BinExport2FeatureExtractor, queries: BinExport2InstructionPatternMatcher, address: int): @@ -507,8 +502,7 @@ def match_address_with_be2( def test_pattern_matching(): - queries = BinExport2InstructionPatternMatcher.from_str( - """ + queries = BinExport2InstructionPatternMatcher.from_str(""" br reg(stack) ; capture reg br reg(not-stack) ; capture reg mov reg0, reg1 ; capture reg0 @@ -522,8 +516,7 @@ def test_pattern_matching(): ldp|stp reg, reg, [reg, #int]! ; capture #int ldp|stp reg, reg, [reg], #int ; capture #int ldrb reg0, [reg1(not-stack), reg2] ; capture reg2 - """ - ) + """) # 0x210184: ldrb w2, [x0, x1] # query: ldrb reg0, [reg1(not-stack), reg2] ; capture reg2" @@ -550,11 +543,9 @@ BE2_EXTRACTOR_687 = fixtures.get_binexport_extractor( def test_pattern_matching_exclamation(): - queries = BinExport2InstructionPatternMatcher.from_str( - """ + queries = BinExport2InstructionPatternMatcher.from_str(""" stp reg, reg, [reg, #int]! ; capture #int - """ - ) + """) # note this captures the sp # 0x107918: stp x20, x19, [sp,0xFFFFFFFFFFFFFFE0]! @@ -564,11 +555,9 @@ def test_pattern_matching_exclamation(): def test_pattern_matching_stack(): - queries = BinExport2InstructionPatternMatcher.from_str( - """ + queries = BinExport2InstructionPatternMatcher.from_str(""" stp reg, reg, [reg(stack), #int]! ; capture #int - """ - ) + """) # note this does capture the sp # compare this with the test above (exclamation) @@ -579,11 +568,9 @@ def test_pattern_matching_stack(): def test_pattern_matching_not_stack(): - queries = BinExport2InstructionPatternMatcher.from_str( - """ + queries = BinExport2InstructionPatternMatcher.from_str(""" stp reg, reg, [reg(not-stack), #int]! ; capture #int - """ - ) + """) # note this does not capture the sp # compare this with the test above (exclamation) @@ -597,11 +584,9 @@ BE2_EXTRACTOR_MIMI = fixtures.get_binexport_extractor(CD / "data" / "binexport2" def test_pattern_matching_x86(): - queries = BinExport2InstructionPatternMatcher.from_str( - """ + queries = BinExport2InstructionPatternMatcher.from_str(""" cmp|lea reg, [reg(not-stack) + #int0] ; capture #int0 - """ - ) + """) # 0x4018c0: LEA ECX, [EBX+0x2] # query: cmp|lea reg, [reg(not-stack) + #int0] ; capture #int0 diff --git a/tests/test_capabilities.py b/tests/test_capabilities.py index 809173da..9a689568 100644 --- a/tests/test_capabilities.py +++ b/tests/test_capabilities.py @@ -23,9 +23,7 @@ def test_match_across_scopes_file_function(z9324d_extractor): rules = capa.rules.RuleSet( [ # this rule should match on a function (0x4073F0) - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: install service @@ -39,13 +37,9 @@ def test_match_across_scopes_file_function(z9324d_extractor): - api: advapi32.OpenSCManagerA - api: advapi32.CreateServiceA - api: advapi32.StartServiceA - """ - ) - ), + """)), # this rule should match on a file feature - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: .text section @@ -56,15 +50,11 @@ def test_match_across_scopes_file_function(z9324d_extractor): - 9324d1a8ae37a36ae560c37448c9705a features: - section: .text - """ - ) - ), + """)), # this rule should match on earlier rule matches: # - install service, with function scope # - .text section, with file scope - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: .text section and install service @@ -77,9 +67,7 @@ def test_match_across_scopes_file_function(z9324d_extractor): - and: - match: install service - match: .text section - """ - ) - ), + """)), ] ) capabilities = capa.capabilities.common.find_capabilities(rules, z9324d_extractor) @@ -92,9 +80,7 @@ def test_match_across_scopes(z9324d_extractor): rules = capa.rules.RuleSet( [ # this rule should match on a basic block (including at least 0x403685) - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: tight loop @@ -105,14 +91,10 @@ def test_match_across_scopes(z9324d_extractor): - 9324d1a8ae37a36ae560c37448c9705a:0x403685 features: - characteristic: tight loop - """ - ) - ), + """)), # this rule should match on a function (0x403660) # based on API, as well as prior basic block rule match - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: kill thread loop @@ -126,13 +108,9 @@ def test_match_across_scopes(z9324d_extractor): - api: kernel32.TerminateThread - api: kernel32.CloseHandle - match: tight loop - """ - ) - ), + """)), # this rule should match on a file feature and a prior function rule match - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: kill thread program @@ -145,9 +123,7 @@ def test_match_across_scopes(z9324d_extractor): - and: - section: .text - match: kill thread loop - """ - ) - ), + """)), ] ) capabilities = capa.capabilities.common.find_capabilities(rules, z9324d_extractor) @@ -157,11 +133,7 @@ def test_match_across_scopes(z9324d_extractor): def test_subscope_bb_rules(z9324d_extractor): - rules = capa.rules.RuleSet( - [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + rules = capa.rules.RuleSet([capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -172,22 +144,14 @@ def test_subscope_bb_rules(z9324d_extractor): - and: - basic block: - characteristic: tight loop - """ - ) - ) - ] - ) + """))]) # tight loop at 0x403685 capabilities = capa.capabilities.common.find_capabilities(rules, z9324d_extractor) assert "test rule" in capabilities.matches def test_match_specific_functions(z9324d_extractor): - rules = capa.rules.RuleSet( - [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + rules = capa.rules.RuleSet([capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: receive data @@ -199,11 +163,7 @@ def test_match_specific_functions(z9324d_extractor): features: - or: - api: recv - """ - ) - ) - ] - ) + """))]) extractor = FunctionFilter(z9324d_extractor, {0x4019C0}) capabilities = capa.capabilities.common.find_capabilities(rules, extractor) matches = capabilities.matches["receive data"] @@ -214,11 +174,7 @@ def test_match_specific_functions(z9324d_extractor): def test_byte_matching(z9324d_extractor): - rules = capa.rules.RuleSet( - [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + rules = capa.rules.RuleSet([capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: byte match test @@ -228,21 +184,13 @@ def test_byte_matching(z9324d_extractor): features: - and: - bytes: ED 24 9E F4 52 A9 07 47 55 8E E1 AB 30 8E 23 61 - """ - ) - ) - ] - ) + """))]) capabilities = capa.capabilities.common.find_capabilities(rules, z9324d_extractor) assert "byte match test" in capabilities.matches def test_com_feature_matching(z395eb_extractor): - rules = capa.rules.RuleSet( - [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + rules = capa.rules.RuleSet([capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: initialize IWebBrowser2 @@ -254,21 +202,13 @@ def test_com_feature_matching(z395eb_extractor): - api: ole32.CoCreateInstance - com/class: InternetExplorer #bytes: 01 DF 02 00 00 00 00 00 C0 00 00 00 00 00 00 46 = CLSID_InternetExplorer - com/interface: IWebBrowser2 #bytes: 61 16 0C D3 AF CD D0 11 8A 3E 00 C0 4F C9 E2 6E = IID_IWebBrowser2 - """ - ) - ) - ] - ) + """))]) capabilities = capa.main.find_capabilities(rules, z395eb_extractor) assert "initialize IWebBrowser2" in capabilities.matches def test_count_bb(z9324d_extractor): - rules = capa.rules.RuleSet( - [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + rules = capa.rules.RuleSet([capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: count bb @@ -279,22 +219,14 @@ def test_count_bb(z9324d_extractor): features: - and: - count(basic blocks): 1 or more - """ - ) - ) - ] - ) + """))]) capabilities = capa.capabilities.common.find_capabilities(rules, z9324d_extractor) assert "count bb" in capabilities.matches def test_instruction_scope(z9324d_extractor): # .text:004071A4 68 E8 03 00 00 push 3E8h - rules = capa.rules.RuleSet( - [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + rules = capa.rules.RuleSet([capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: push 1000 @@ -306,11 +238,7 @@ def test_instruction_scope(z9324d_extractor): - and: - mnemonic: push - number: 1000 - """ - ) - ) - ] - ) + """))]) capabilities = capa.capabilities.common.find_capabilities(rules, z9324d_extractor) assert "push 1000" in capabilities.matches assert 0x4071A4 in {result[0] for result in capabilities.matches["push 1000"]} @@ -320,11 +248,7 @@ def test_instruction_subscope(z9324d_extractor): # .text:00406F60 sub_406F60 proc near # [...] # .text:004071A4 68 E8 03 00 00 push 3E8h - rules = capa.rules.RuleSet( - [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + rules = capa.rules.RuleSet([capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: push 1000 on i386 @@ -338,11 +262,7 @@ def test_instruction_subscope(z9324d_extractor): - instruction: - mnemonic: push - number: 1000 - """ - ) - ) - ] - ) + """))]) capabilities = capa.capabilities.common.find_capabilities(rules, z9324d_extractor) assert "push 1000 on i386" in capabilities.matches assert 0x406F60 in {result[0] for result in capabilities.matches["push 1000 on i386"]} diff --git a/tests/test_cape_model.py b/tests/test_cape_model.py index 3e46c665..d6ad7a95 100644 --- a/tests/test_cape_model.py +++ b/tests/test_cape_model.py @@ -81,8 +81,7 @@ def test_cape_extractor(version: str, filename: str, exception: Type[BaseExcepti def test_cape_model_argument(): - call = Call.model_validate_json( - """ + call = Call.model_validate_json(""" { "timestamp": "2023-10-20 12:30:14,015", "thread_id": "2380", @@ -105,7 +104,6 @@ def test_cape_model_argument(): "repeated": 19, "id": 0 } - """ - ) + """) assert call.arguments[0].value == 30 assert call.arguments[1].value == 0x30 diff --git a/tests/test_drakvuf_models.py b/tests/test_drakvuf_models.py index 07833197..c2fbb8fe 100644 --- a/tests/test_drakvuf_models.py +++ b/tests/test_drakvuf_models.py @@ -18,8 +18,7 @@ from capa.features.extractors.drakvuf.models import SystemCall def test_syscall_argument_construction(): - call_dictionary = json.loads( - r""" + call_dictionary = json.loads(r""" { "Plugin": "syscall", "TimeStamp": "1716999134.581449", @@ -43,8 +42,7 @@ def test_syscall_argument_construction(): "Timeout": "0xfffff506a02846d8", "Alertable": "0x0" } - """ - ) + """) call = SystemCall(**call_dictionary) assert len(call.arguments) == call.nargs assert call.arguments["IoCompletionHandle"] == "0xffffffff80001ac0" diff --git a/tests/test_dynamic_span_of_calls_scope.py b/tests/test_dynamic_span_of_calls_scope.py index 5f1a19a7..d024e5ba 100644 --- a/tests/test_dynamic_span_of_calls_scope.py +++ b/tests/test_dynamic_span_of_calls_scope.py @@ -83,8 +83,7 @@ def get_call_ids(matches) -> Iterator[int]: def test_dynamic_call_scope(): extractor = get_0000a657_thread3064() - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -93,8 +92,7 @@ def test_dynamic_call_scope(): dynamic: call features: - api: GetSystemTimeAsFileTime - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) ruleset = capa.rules.RuleSet([r]) @@ -116,8 +114,7 @@ def test_dynamic_call_scope(): def test_dynamic_span_scope(): extractor = get_0000a657_thread3064() - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -131,8 +128,7 @@ def test_dynamic_span_scope(): - api: LdrGetDllHandle - api: LdrGetProcedureAddress - count(api(LdrGetDllHandle)): 2 - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) ruleset = capa.rules.RuleSet([r]) @@ -158,8 +154,7 @@ def test_dynamic_span_scope(): def test_dynamic_span_scope_length(): extractor = get_0000a657_thread3064() - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -170,8 +165,7 @@ def test_dynamic_span_scope_length(): - and: - api: GetSystemTimeAsFileTime - api: RtlAddVectoredExceptionHandler - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) ruleset = capa.rules.RuleSet([r]) @@ -196,8 +190,7 @@ def test_dynamic_span_scope_length(): def test_dynamic_span_call_subscope(): extractor = get_0000a657_thread3064() - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -210,8 +203,7 @@ def test_dynamic_span_call_subscope(): - and: - api: LdrGetProcedureAddress - string: AddVectoredExceptionHandler - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) ruleset = capa.rules.RuleSet([r]) @@ -234,8 +226,7 @@ def test_dynamic_span_call_subscope(): def test_dynamic_span_scope_span_subscope(): extractor = get_0000a657_thread3064() - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -256,8 +247,7 @@ def test_dynamic_span_scope_span_subscope(): - api: LdrGetDllHandle - api: LdrGetProcedureAddress - string: RemoveVectoredExceptionHandler - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) ruleset = capa.rules.RuleSet([r]) @@ -269,8 +259,7 @@ def test_dynamic_span_scope_span_subscope(): # show that you can't use thread subscope in span rules. def test_dynamic_span_scope_thread_subscope(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -281,8 +270,7 @@ def test_dynamic_span_scope_thread_subscope(): - and: - thread: - string: "foo" - """ - ) + """) with pytest.raises(capa.rules.InvalidRule): capa.rules.Rule.from_yaml(rule) @@ -300,8 +288,7 @@ def test_dynamic_span_scope_thread_subscope(): def test_dynamic_span_example(): extractor = get_0000a657_thread3064() - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -319,8 +306,7 @@ def test_dynamic_span_example(): - api: LdrGetProcedureAddress - string: "AddVectoredExceptionHandler" - api: RtlAddVectoredExceptionHandler - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) ruleset = capa.rules.RuleSet([r]) @@ -345,8 +331,7 @@ def test_dynamic_span_example(): def test_dynamic_span_multiple_spans_overlapping_single_event(): extractor = get_0000a657_thread3064() - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -359,8 +344,7 @@ def test_dynamic_span_multiple_spans_overlapping_single_event(): - and: - api: LdrGetProcedureAddress - string: "AddVectoredExceptionHandler" - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) ruleset = capa.rules.RuleSet([r]) @@ -386,9 +370,7 @@ def test_dynamic_span_scope_match_statements(): ruleset = capa.rules.RuleSet( [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: resolve add VEH @@ -401,12 +383,8 @@ def test_dynamic_span_scope_match_statements(): - api: LdrGetDllHandle - api: LdrGetProcedureAddress - string: AddVectoredExceptionHandler - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: resolve remove VEH @@ -419,12 +397,8 @@ def test_dynamic_span_scope_match_statements(): - api: LdrGetDllHandle - api: LdrGetProcedureAddress - string: RemoveVectoredExceptionHandler - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: resolve add and remove VEH @@ -435,12 +409,8 @@ def test_dynamic_span_scope_match_statements(): - and: - match: resolve add VEH - match: resolve remove VEH - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: has VEH runtime linking @@ -450,9 +420,7 @@ def test_dynamic_span_scope_match_statements(): features: - and: - match: linking/runtime-linking/veh - """ - ) - ), + """)), ] ) diff --git a/tests/test_fmt.py b/tests/test_fmt.py index 20a75129..05b1fafc 100644 --- a/tests/test_fmt.py +++ b/tests/test_fmt.py @@ -17,8 +17,7 @@ import textwrap import capa.rules -EXPECTED = textwrap.dedent( - """\ +EXPECTED = textwrap.dedent("""\ rule: meta: name: test rule @@ -34,13 +33,11 @@ EXPECTED = textwrap.dedent( - and: - number: 1 - number: 2 - """ -) + """) def test_rule_reformat_top_level_elements(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: features: - and: @@ -56,15 +53,13 @@ def test_rule_reformat_top_level_elements(): examples: - foo1234 - bar5678 - """ - ) + """) assert capa.rules.Rule.from_yaml(rule).to_yaml() == EXPECTED def test_rule_reformat_indentation(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -80,15 +75,13 @@ def test_rule_reformat_indentation(): - and: - number: 1 - number: 2 - """ - ) + """) assert capa.rules.Rule.from_yaml(rule).to_yaml() == EXPECTED def test_rule_reformat_order(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: authors: @@ -104,8 +97,7 @@ def test_rule_reformat_order(): - and: - number: 1 - number: 2 - """ - ) + """) assert capa.rules.Rule.from_yaml(rule).to_yaml() == EXPECTED @@ -113,8 +105,7 @@ def test_rule_reformat_order(): def test_rule_reformat_meta_update(): # test updating the rule content after parsing - src = textwrap.dedent( - """ + src = textwrap.dedent(""" rule: meta: authors: @@ -130,8 +121,7 @@ def test_rule_reformat_meta_update(): - and: - number: 1 - number: 2 - """ - ) + """) rule = capa.rules.Rule.from_yaml(src) rule.name = "test rule" @@ -141,8 +131,7 @@ def test_rule_reformat_meta_update(): def test_rule_reformat_string_description(): # the `description` should be aligned with the preceding feature name. # see #263 - src = textwrap.dedent( - """ + src = textwrap.dedent(""" rule: meta: name: test rule @@ -155,8 +144,7 @@ def test_rule_reformat_string_description(): - and: - string: foo description: bar - """ - ).lstrip() + """).lstrip() rule = capa.rules.Rule.from_yaml(src) assert rule.to_yaml() == src diff --git a/tests/test_freeze_dynamic.py b/tests/test_freeze_dynamic.py index 9ed84fa4..74129f4f 100644 --- a/tests/test_freeze_dynamic.py +++ b/tests/test_freeze_dynamic.py @@ -108,9 +108,7 @@ def test_null_feature_extractor(): rules = capa.rules.RuleSet( [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: create file @@ -120,9 +118,7 @@ def test_null_feature_extractor(): features: - and: - api: CreateFile - """ - ) - ), + """)), ] ) capabilities = capa.main.find_capabilities(rules, EXTRACTOR) diff --git a/tests/test_freeze_static.py b/tests/test_freeze_static.py index e9f58bc4..9c171f2e 100644 --- a/tests/test_freeze_static.py +++ b/tests/test_freeze_static.py @@ -88,9 +88,7 @@ def test_null_feature_extractor(): rules = capa.rules.RuleSet( [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: xor loop @@ -102,9 +100,7 @@ def test_null_feature_extractor(): - characteristic: tight loop - mnemonic: xor - characteristic: nzxor - """ - ) - ), + """)), ] ) capabilities = capa.main.find_capabilities(rules, EXTRACTOR) diff --git a/tests/test_main.py b/tests/test_main.py index 1b0af399..72ebd762 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -38,8 +38,7 @@ def test_main(z9324d_extractor): def test_main_single_rule(z9324d_extractor, tmpdir): # tests a single rule can be loaded successfully - RULE_CONTENT = textwrap.dedent( - """ + RULE_CONTENT = textwrap.dedent(""" rule: meta: name: test rule @@ -50,8 +49,7 @@ def test_main_single_rule(z9324d_extractor, tmpdir): - test features: - string: test - """ - ) + """) path = z9324d_extractor.path rule_file = tmpdir.mkdir("capa").join("rule.yml") rule_file.write(RULE_CONTENT) @@ -100,9 +98,7 @@ def test_main_shellcode(z499c2_extractor): def test_ruleset(): rules = capa.rules.RuleSet( [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: file rule @@ -111,12 +107,8 @@ def test_ruleset(): dynamic: process features: - characteristic: embedded pe - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: function rule @@ -125,12 +117,8 @@ def test_ruleset(): dynamic: process features: - characteristic: tight loop - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: basic block rule @@ -139,12 +127,8 @@ def test_ruleset(): dynamic: process features: - characteristic: nzxor - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: process rule @@ -153,12 +137,8 @@ def test_ruleset(): dynamic: process features: - string: "explorer.exe" - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: thread rule @@ -167,12 +147,8 @@ def test_ruleset(): dynamic: thread features: - api: RegDeleteKey - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test call subscope @@ -184,12 +160,8 @@ def test_ruleset(): - string: "explorer.exe" - call: - api: HttpOpenRequestW - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -207,9 +179,7 @@ def test_ruleset(): - number: 6 = IPPROTO_TCP - number: 1 = SOCK_STREAM - number: 2 = AF_INET - """ - ) - ), + """)), ] ) assert len(rules.file_rules) == 2 @@ -322,9 +292,7 @@ def test_main_cape1(tmp_path): # https://github.com/mandiant/capa/pull/1696 rules = tmp_path / "rules" rules.mkdir() - (rules / "create-or-open-registry-key.yml").write_text( - textwrap.dedent( - """ + (rules / "create-or-open-registry-key.yml").write_text(textwrap.dedent(""" rule: meta: name: create or open registry key @@ -354,9 +322,7 @@ def test_main_cape1(tmp_path): - api: SHRegOpenUSKey - api: SHRegCreateUSKey - api: RtlCreateRegistryKey - """ - ) - ) + """)) assert capa.main.main([str(path), "-r", str(rules)]) == 0 assert capa.main.main([str(path), "-q", "-r", str(rules)]) == 0 diff --git a/tests/test_match.py b/tests/test_match.py index 8fdd146d..cfeeb7e9 100644 --- a/tests/test_match.py +++ b/tests/test_match.py @@ -46,8 +46,7 @@ def match(rules, features, va, scope=Scope.FUNCTION): def test_match_simple(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -57,8 +56,7 @@ def test_match_simple(): namespace: testns1/testns2 features: - number: 100 - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) features, matches = match([r], {capa.features.insn.Number(100): {1, 2}}, 0x0) @@ -69,8 +67,7 @@ def test_match_simple(): def test_match_range_exact(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -79,8 +76,7 @@ def test_match_range_exact(): dynamic: process features: - count(number(100)): 2 - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) # just enough matches @@ -97,8 +93,7 @@ def test_match_range_exact(): def test_match_range_range(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -107,8 +102,7 @@ def test_match_range_range(): dynamic: process features: - count(number(100)): (2, 3) - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) # just enough matches @@ -129,8 +123,7 @@ def test_match_range_range(): def test_match_range_exact_zero(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -146,8 +139,7 @@ def test_match_range_exact_zero(): # so we have this additional trivial feature. - mnemonic: mov - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) # feature isn't indexed - good. @@ -165,8 +157,7 @@ def test_match_range_exact_zero(): def test_match_range_with_zero(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -181,8 +172,7 @@ def test_match_range_with_zero(): # since we don't support top level NOT statements. # so we have this additional trivial feature. - mnemonic: mov - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) # ok @@ -200,8 +190,7 @@ def test_match_range_with_zero(): def test_match_adds_matched_rule_feature(): """show that using `match` adds a feature for matched rules.""" - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -210,8 +199,7 @@ def test_match_adds_matched_rule_feature(): dynamic: process features: - number: 100 - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) features, _ = match([r], {capa.features.insn.Number(100): {1}}, 0x0) assert capa.features.common.MatchedRule("test rule") in features @@ -220,9 +208,7 @@ def test_match_adds_matched_rule_feature(): def test_match_matched_rules(): """show that using `match` adds a feature for matched rules.""" rules = [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule1 @@ -231,12 +217,8 @@ def test_match_matched_rules(): dynamic: process features: - number: 100 - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule2 @@ -245,9 +227,7 @@ def test_match_matched_rules(): dynamic: process features: - match: test rule1 - """ - ) - ), + """)), ] features, _ = match( @@ -271,9 +251,7 @@ def test_match_matched_rules(): def test_match_namespace(): rules = [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: CreateFile API @@ -283,12 +261,8 @@ def test_match_namespace(): namespace: file/create/CreateFile features: - api: CreateFile - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: WriteFile API @@ -298,12 +272,8 @@ def test_match_namespace(): namespace: file/write features: - api: WriteFile - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: file-create @@ -312,12 +282,8 @@ def test_match_namespace(): dynamic: process features: - match: file/create - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: filesystem-any @@ -326,9 +292,7 @@ def test_match_namespace(): dynamic: process features: - match: file - """ - ) - ), + """)), ] features, matches = match( @@ -355,9 +319,7 @@ def test_match_namespace(): def test_match_substring(): rules = [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -367,9 +329,7 @@ def test_match_substring(): features: - and: - substring: abc - """ - ) - ), + """)), ] features, _ = match( capa.rules.topologically_order_rules(rules), @@ -409,9 +369,7 @@ def test_match_substring(): def test_match_regex(): rules = [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -421,12 +379,8 @@ def test_match_regex(): features: - and: - string: /.*bbbb.*/ - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: rule with implied wildcards @@ -436,12 +390,8 @@ def test_match_regex(): features: - and: - string: /bbbb/ - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: rule with anchor @@ -451,9 +401,7 @@ def test_match_regex(): features: - and: - string: /^bbbb/ - """ - ) - ), + """)), ] features, _ = match( capa.rules.topologically_order_rules(rules), @@ -488,9 +436,7 @@ def test_match_regex(): def test_match_regex_ignorecase(): rules = [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -500,9 +446,7 @@ def test_match_regex_ignorecase(): features: - and: - string: /.*bbbb.*/i - """ - ) - ), + """)), ] features, _ = match( capa.rules.topologically_order_rules(rules), @@ -514,9 +458,7 @@ def test_match_regex_ignorecase(): def test_match_regex_complex(): rules = [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - r""" + capa.rules.Rule.from_yaml(textwrap.dedent(r""" rule: meta: name: test rule @@ -526,9 +468,7 @@ def test_match_regex_complex(): features: - or: - string: /.*HARDWARE\\Key\\key with spaces\\.*/i - """ - ) - ), + """)), ] features, _ = match( capa.rules.topologically_order_rules(rules), @@ -540,9 +480,7 @@ def test_match_regex_complex(): def test_match_regex_values_always_string(): rules = [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -553,9 +491,7 @@ def test_match_regex_values_always_string(): - or: - string: /123/ - string: /0x123/ - """ - ) - ), + """)), ] features, _ = match( capa.rules.topologically_order_rules(rules), @@ -587,8 +523,7 @@ def test_regex_get_value_str(pattern): @pytest.mark.xfail(reason="can't have top level NOT") def test_match_only_not(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -599,8 +534,7 @@ def test_match_only_not(): features: - not: - number: 99 - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) _, matches = match([r], {capa.features.insn.Number(100): {1, 2}}, 0x0) @@ -608,8 +542,7 @@ def test_match_only_not(): def test_match_not(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -622,8 +555,7 @@ def test_match_not(): - mnemonic: mov - not: - number: 99 - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) _, matches = match([r], {capa.features.insn.Number(100): {1, 2}, capa.features.insn.Mnemonic("mov"): {1, 2}}, 0x0) @@ -632,8 +564,7 @@ def test_match_not(): @pytest.mark.xfail(reason="can't have nested NOT") def test_match_not_not(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -645,8 +576,7 @@ def test_match_not_not(): - not: - not: - number: 100 - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) _, matches = match([r], {capa.features.insn.Number(100): {1, 2}}, 0x0) @@ -654,8 +584,7 @@ def test_match_not_not(): def test_match_operand_number(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -665,8 +594,7 @@ def test_match_operand_number(): features: - and: - operand[0].number: 0x10 - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) assert capa.features.insn.OperandNumber(0, 0x10) in {capa.features.insn.OperandNumber(0, 0x10)} @@ -684,8 +612,7 @@ def test_match_operand_number(): def test_match_operand_offset(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -695,8 +622,7 @@ def test_match_operand_offset(): features: - and: - operand[0].offset: 0x10 - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) assert capa.features.insn.OperandOffset(0, 0x10) in {capa.features.insn.OperandOffset(0, 0x10)} @@ -714,8 +640,7 @@ def test_match_operand_offset(): def test_match_property_access(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -725,8 +650,7 @@ def test_match_property_access(): features: - and: - property/read: System.IO.FileInfo::Length - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) assert capa.features.insn.Property("System.IO.FileInfo::Length", capa.features.common.FeatureAccess.READ) in { @@ -758,8 +682,7 @@ def test_match_property_access(): def test_match_os_any(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -777,8 +700,7 @@ def test_match_os_any(): - and: - os: any - string: "Goodbye world" - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) _, matches = match( @@ -812,8 +734,7 @@ def test_match_os_any(): # this test demonstrates the behavior of unstable features that may change before the next major release. def test_index_features_and_unstable(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -824,8 +745,7 @@ def test_index_features_and_unstable(): - and: - mnemonic: mov - api: CreateFileW - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) rr = capa.rules.RuleSet([r]) index: capa.rules.RuleSet._RuleFeatureIndex = rr._feature_indexes_by_scopes[capa.rules.Scope.FUNCTION] @@ -841,8 +761,7 @@ def test_index_features_and_unstable(): # this test demonstrates the behavior of unstable features that may change before the next major release. def test_index_features_or_unstable(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -853,8 +772,7 @@ def test_index_features_or_unstable(): - or: - mnemonic: mov - api: CreateFileW - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) rr = capa.rules.RuleSet([r]) index: capa.rules.RuleSet._RuleFeatureIndex = rr._feature_indexes_by_scopes[capa.rules.Scope.FUNCTION] @@ -871,8 +789,7 @@ def test_index_features_or_unstable(): # this test demonstrates the behavior of unstable features that may change before the next major release. def test_index_features_nested_unstable(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -885,8 +802,7 @@ def test_index_features_nested_unstable(): - or: - api: CreateFileW - string: foo - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) rr = capa.rules.RuleSet([r]) index: capa.rules.RuleSet._RuleFeatureIndex = rr._feature_indexes_by_scopes[capa.rules.Scope.FUNCTION] diff --git a/tests/test_optimizer.py b/tests/test_optimizer.py index 16b2a5a1..1c3d5598 100644 --- a/tests/test_optimizer.py +++ b/tests/test_optimizer.py @@ -25,8 +25,7 @@ from capa.features.common import Arch, Substring def test_optimizer_order(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -44,8 +43,7 @@ def test_optimizer_order(): - or: - number: 1 - offset: 4 - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) # before optimization diff --git a/tests/test_render.py b/tests/test_render.py index 5389823c..3c8bfc00 100644 --- a/tests/test_render.py +++ b/tests/test_render.py @@ -56,8 +56,7 @@ def test_render_meta_attack(): subtechnique = "Windows Service" canonical = "{:s}::{:s}::{:s} [{:s}]".format(tactic, technique, subtechnique, id) - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -70,10 +69,7 @@ def test_render_meta_attack(): - {:s} features: - number: 1 - """.format( - canonical - ) - ) + """.format(canonical)) r = capa.rules.Rule.from_yaml(rule) rule_meta = capa.render.result_document.RuleMetadata.from_capa(r) attack = rule_meta.attack[0] @@ -94,8 +90,7 @@ def test_render_meta_mbc(): method = "Heavens Gate" canonical = "{:s}::{:s}::{:s} [{:s}]".format(objective, behavior, method, id) - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -108,10 +103,7 @@ def test_render_meta_mbc(): - {:s} features: - number: 1 - """.format( - canonical - ) - ) + """.format(canonical)) r = capa.rules.Rule.from_yaml(rule) rule_meta = capa.render.result_document.RuleMetadata.from_capa(r) mbc = rule_meta.mbc[0] @@ -129,8 +121,7 @@ def test_render_meta_maec(): malware_category = "downloader" analysis_conclusion = "malicious" - rule_yaml = textwrap.dedent( - """ + rule_yaml = textwrap.dedent(""" rule: meta: name: test rule @@ -144,10 +135,7 @@ def test_render_meta_maec(): maec/analysis-conclusion: {:s} features: - number: 1 - """.format( - malware_family, malware_category, analysis_conclusion - ) - ) + """.format(malware_family, malware_category, analysis_conclusion)) rule = capa.rules.Rule.from_yaml(rule_yaml) rm = capa.render.result_document.RuleMatches( meta=capa.render.result_document.RuleMetadata.from_capa(rule), @@ -220,8 +208,7 @@ def test_render_vverbose_feature(feature, expected): layout = capa.render.result_document.StaticLayout(functions=()) - src = textwrap.dedent( - """ + src = textwrap.dedent(""" rule: meta: name: test rule @@ -237,8 +224,7 @@ def test_render_vverbose_feature(feature, expected): - and: - number: 1 - number: 2 - """ - ) + """) rule = capa.rules.Rule.from_yaml(src) rm = capa.render.result_document.RuleMatches( diff --git a/tests/test_rule_cache.py b/tests/test_rule_cache.py index 0ba9ff99..59f6ff7d 100644 --- a/tests/test_rule_cache.py +++ b/tests/test_rule_cache.py @@ -22,9 +22,7 @@ import capa.rules import capa.helpers import capa.rules.cache -R1 = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ +R1 = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -40,13 +38,9 @@ R1 = capa.rules.Rule.from_yaml( - and: - number: 1 - number: 2 - """ - ) -) + """)) -R2 = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ +R2 = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule 2 @@ -62,9 +56,7 @@ R2 = capa.rules.Rule.from_yaml( - and: - number: 3 - number: 4 - """ - ) -) + """)) def test_ruleset_cache_ids(): diff --git a/tests/test_rules.py b/tests/test_rules.py index 9a8b6874..4df8fcb4 100644 --- a/tests/test_rules.py +++ b/tests/test_rules.py @@ -55,8 +55,7 @@ def test_rule_ctor(): def test_rule_yaml(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -72,8 +71,7 @@ def test_rule_yaml(): - and: - number: 1 - number: 2 - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) assert bool(r.evaluate({Number(0): {ADDR1}})) is False assert bool(r.evaluate({Number(0): {ADDR1}, Number(1): {ADDR1}})) is False @@ -82,8 +80,7 @@ def test_rule_yaml(): def test_rule_yaml_complex(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -101,16 +98,14 @@ def test_rule_yaml_complex(): - number: 4 - number: 5 - number: 6 - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) assert bool(r.evaluate({Number(5): {ADDR1}, Number(6): {ADDR1}, Number(7): {ADDR1}, Number(8): {ADDR1}})) is True assert bool(r.evaluate({Number(6): {ADDR1}, Number(7): {ADDR1}, Number(8): {ADDR1}})) is False def test_rule_descriptions(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -135,8 +130,7 @@ def test_rule_descriptions(): - description: and description - and: - description: and description - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) def rec(statement): @@ -155,9 +149,7 @@ def test_rule_descriptions(): def test_invalid_rule_statement_descriptions(): # statements can only have one description with pytest.raises(capa.rules.InvalidRule): - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -169,9 +161,7 @@ def test_invalid_rule_statement_descriptions(): - number: 1 = This is the number 1 - description: description - description: another description (invalid) - """ - ) - ) + """)) def test_empty_yaml_raises_invalid_rule(): @@ -206,8 +196,7 @@ def test_get_rules_skips_empty_yaml(tmp_path): def test_rule_yaml_not(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -219,16 +208,14 @@ def test_rule_yaml_not(): - number: 1 - not: - number: 2 - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) assert bool(r.evaluate({Number(1): {ADDR1}})) is True assert bool(r.evaluate({Number(1): {ADDR1}, Number(2): {ADDR1}})) is False def test_rule_yaml_count(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -237,8 +224,7 @@ def test_rule_yaml_count(): dynamic: process features: - count(number(100)): 1 - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) assert bool(r.evaluate({Number(100): set()})) is False assert bool(r.evaluate({Number(100): {ADDR1}})) is True @@ -246,8 +232,7 @@ def test_rule_yaml_count(): def test_rule_yaml_count_range(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -256,8 +241,7 @@ def test_rule_yaml_count_range(): dynamic: process features: - count(number(100)): (1, 2) - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) assert bool(r.evaluate({Number(100): set()})) is False assert bool(r.evaluate({Number(100): {ADDR1}})) is True @@ -266,8 +250,7 @@ def test_rule_yaml_count_range(): def test_rule_yaml_count_string(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -276,8 +259,7 @@ def test_rule_yaml_count_string(): dynamic: process features: - count(string(foo)): 2 - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) assert bool(r.evaluate({String("foo"): set()})) is False assert bool(r.evaluate({String("foo"): {ADDR1}})) is False @@ -287,9 +269,7 @@ def test_rule_yaml_count_string(): def test_invalid_rule_feature(): with pytest.raises(capa.rules.InvalidRule): - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -298,14 +278,10 @@ def test_invalid_rule_feature(): dynamic: process features: - foo: true - """ - ) - ) + """)) with pytest.raises(capa.rules.InvalidRule): - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -314,14 +290,10 @@ def test_invalid_rule_feature(): dynamic: process features: - characteristic: nzxor - """ - ) - ) + """)) with pytest.raises(capa.rules.InvalidRule): - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -330,14 +302,10 @@ def test_invalid_rule_feature(): dynamic: thread features: - characteristic: embedded pe - """ - ) - ) + """)) with pytest.raises(capa.rules.InvalidRule): - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -346,15 +314,11 @@ def test_invalid_rule_feature(): dynamic: thread features: - characteristic: embedded pe - """ - ) - ) + """)) def test_multi_scope_rules_features(): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -368,13 +332,9 @@ def test_multi_scope_rules_features(): - os: linux - mnemonic: syscall - number: 1 = write - """ - ) - ) + """)) - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -388,13 +348,9 @@ def test_multi_scope_rules_features(): - os: linux - mnemonic: syscall - number: 0 = read - """ - ) - ) + """)) - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -412,16 +368,12 @@ def test_multi_scope_rules_features(): - number: 6 = IPPROTO_TCP - number: 1 = SOCK_STREAM - number: 2 = AF_INET - """ - ) - ) + """)) def test_rules_flavor_filtering(): rules = [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: static rule @@ -430,12 +382,8 @@ def test_rules_flavor_filtering(): dynamic: unsupported features: - api: CreateFileA - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: dynamic rule @@ -444,9 +392,7 @@ def test_rules_flavor_filtering(): dynamic: thread features: - api: CreateFileA - """ - ) - ), + """)), ] static_rules = capa.rules.RuleSet([r for r in rules if r.scopes.static is not None]) @@ -464,9 +410,7 @@ def test_meta_scope_keywords(): for static_scope in static_scopes: for dynamic_scope in dynamic_scopes: - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - f""" + _ = capa.rules.Rule.from_yaml(textwrap.dedent(f""" rule: meta: name: test rule @@ -476,15 +420,11 @@ def test_meta_scope_keywords(): features: - or: - format: pe - """ - ) - ) + """)) # its also ok to specify "unsupported" for static_scope in static_scopes: - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - f""" + _ = capa.rules.Rule.from_yaml(textwrap.dedent(f""" rule: meta: name: test rule @@ -494,13 +434,9 @@ def test_meta_scope_keywords(): features: - or: - format: pe - """ - ) - ) + """)) for dynamic_scope in dynamic_scopes: - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - f""" + _ = capa.rules.Rule.from_yaml(textwrap.dedent(f""" rule: meta: name: test rule @@ -510,15 +446,11 @@ def test_meta_scope_keywords(): features: - or: - format: pe - """ - ) - ) + """)) # but at least one scope must be specified with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -526,13 +458,9 @@ def test_meta_scope_keywords(): features: - or: - format: pe - """ - ) - ) + """)) with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -542,9 +470,7 @@ def test_meta_scope_keywords(): features: - or: - format: pe - """ - ) - ) + """)) def test_subscope_same_as_scope(): @@ -557,9 +483,7 @@ def test_subscope_same_as_scope(): for static_scope in static_scopes: for dynamic_scope in dynamic_scopes: - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - f""" + _ = capa.rules.Rule.from_yaml(textwrap.dedent(f""" rule: meta: name: test rule @@ -572,17 +496,13 @@ def test_subscope_same_as_scope(): - format: pe - {dynamic_scope}: - format: pe - """ - ) - ) + """)) def test_lib_rules(): rules = capa.rules.RuleSet( [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: a lib rule @@ -592,12 +512,8 @@ def test_lib_rules(): lib: true features: - api: CreateFileA - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: a standard rule @@ -607,9 +523,7 @@ def test_lib_rules(): lib: false features: - api: CreateFileW - """ - ) - ), + """)), ] ) # lib rules are added to the rule set @@ -619,9 +533,7 @@ def test_lib_rules(): def test_subscope_rules(): rules = capa.rules.RuleSet( [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test function subscope @@ -635,12 +547,8 @@ def test_subscope_rules(): - and: - characteristic: nzxor - characteristic: loop - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test process subscope @@ -653,12 +561,8 @@ def test_subscope_rules(): - process: - and: - substring: "http://" - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test thread subscope @@ -670,12 +574,8 @@ def test_subscope_rules(): - string: "explorer.exe" - thread: - api: HttpOpenRequestW - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test call subscope @@ -687,9 +587,7 @@ def test_subscope_rules(): - string: "explorer.exe" - call: - api: HttpOpenRequestW - """ - ) - ), + """)), ] ) # the file rule scope will have four rules: @@ -720,9 +618,7 @@ def test_duplicate_rules(): with pytest.raises(capa.rules.InvalidRule): _ = capa.rules.RuleSet( [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: rule-name @@ -731,12 +627,8 @@ def test_duplicate_rules(): dynamic: process features: - api: CreateFileA - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: rule-name @@ -745,9 +637,7 @@ def test_duplicate_rules(): dynamic: process features: - api: CreateFileW - """ - ) - ), + """)), ] ) @@ -756,9 +646,7 @@ def test_missing_dependency(): with pytest.raises(capa.rules.InvalidRule): _ = capa.rules.RuleSet( [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: dependent rule @@ -767,18 +655,14 @@ def test_missing_dependency(): dynamic: process features: - match: missing rule - """ - ) - ), + """)), ] ) def test_invalid_rules(): with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -787,14 +671,10 @@ def test_invalid_rules(): dynamic: process features: - characteristic: number(1) - """ - ) - ) + """)) with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -803,15 +683,11 @@ def test_invalid_rules(): dynamic: process features: - characteristic: count(number(100)) - """ - ) - ) + """)) # att&ck and mbc must be lists with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -821,13 +697,9 @@ def test_invalid_rules(): att&ck: Tactic::Technique::Subtechnique [Identifier] features: - number: 1 - """ - ) - ) + """)) with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -837,13 +709,9 @@ def test_invalid_rules(): mbc: Objective::Behavior::Method [Identifier] features: - number: 1 - """ - ) - ) + """)) with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -852,13 +720,9 @@ def test_invalid_rules(): behavior: process features: - number: 1 - """ - ) - ) + """)) with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -867,13 +731,9 @@ def test_invalid_rules(): dynamic: process features: - number: 1 - """ - ) - ) + """)) with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -882,13 +742,9 @@ def test_invalid_rules(): dynamic: process features: - number: 1 - """ - ) - ) + """)) with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -897,14 +753,11 @@ def test_invalid_rules(): dynamic: function features: - number: 1 - """ - ) - ) + """)) def test_number_symbol(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -920,8 +773,7 @@ def test_number_symbol(): - number: 4 = symbol name = another name - number: 0x100 = symbol name - number: 0x11 = (FLAG_A | FLAG_B) - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) children = list(r.statement.get_children()) assert (Number(1) in children) is True @@ -933,8 +785,7 @@ def test_number_symbol(): def test_count_number_symbol(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -946,8 +797,7 @@ def test_count_number_symbol(): - count(number(2 = symbol name)): 1 - count(number(0x100 = symbol name)): 2 or more - count(number(0x11 = (FLAG_A | FLAG_B))): 2 or more - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) assert bool(r.evaluate({Number(2): set()})) is False assert bool(r.evaluate({Number(2): {ADDR1}})) is True @@ -957,8 +807,7 @@ def test_count_number_symbol(): def test_count_api(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -969,8 +818,7 @@ def test_count_api(): - or: - count(api(kernel32.CreateFileA)): 1 - count(api(System.Convert::FromBase64String)): 1 - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) # apis including their DLL names are not extracted anymore assert bool(r.evaluate({API("kernel32.CreateFileA"): set()})) is False @@ -982,9 +830,7 @@ def test_count_api(): def test_invalid_number(): with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -993,14 +839,10 @@ def test_invalid_number(): dynamic: process features: - number: "this is a string" - """ - ) - ) + """)) with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -1009,14 +851,10 @@ def test_invalid_number(): dynamic: process features: - number: 2= - """ - ) - ) + """)) with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -1025,14 +863,11 @@ def test_invalid_number(): dynamic: process features: - number: symbol name = 2 - """ - ) - ) + """)) def test_offset_symbol(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -1046,8 +881,7 @@ def test_offset_symbol(): - offset: 3 = symbol name - offset: 4 = symbol name = another name - offset: 0x100 = symbol name - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) children = list(r.statement.get_children()) assert (Offset(1) in children) is True @@ -1058,8 +892,7 @@ def test_offset_symbol(): def test_count_offset_symbol(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -1071,8 +904,7 @@ def test_count_offset_symbol(): - count(offset(2 = symbol name)): 1 - count(offset(0x100 = symbol name)): 2 or more - count(offset(0x11 = (FLAG_A | FLAG_B))): 2 or more - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) assert bool(r.evaluate({Offset(2): set()})) is False assert bool(r.evaluate({Offset(2): {ADDR1}})) is True @@ -1083,9 +915,7 @@ def test_count_offset_symbol(): def test_invalid_offset(): with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -1094,14 +924,10 @@ def test_invalid_offset(): dynamic: process features: - offset: "this is a string" - """ - ) - ) + """)) with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -1110,14 +936,10 @@ def test_invalid_offset(): dynamic: process features: - offset: 2= - """ - ) - ) + """)) with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -1126,16 +948,12 @@ def test_invalid_offset(): dynamic: process features: - offset: symbol name = 2 - """ - ) - ) + """)) def test_invalid_string_values_int(): with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -1144,14 +962,10 @@ def test_invalid_string_values_int(): dynamic: process features: - string: 123 - """ - ) - ) + """)) with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -1160,14 +974,11 @@ def test_invalid_string_values_int(): dynamic: process features: - string: 0x123 - """ - ) - ) + """)) def test_explicit_string_values_int(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -1178,8 +989,7 @@ def test_explicit_string_values_int(): - or: - string: "123" - string: "0x123" - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) children = list(r.statement.get_children()) assert (String("123") in children) is True @@ -1187,8 +997,7 @@ def test_explicit_string_values_int(): def test_string_values_special_characters(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -1200,8 +1009,7 @@ def test_string_values_special_characters(): - string: "hello\\r\\nworld" - string: "bye\\nbye" description: "test description" - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) children = list(r.statement.get_children()) assert (String("hello\r\nworld") in children) is True @@ -1209,8 +1017,7 @@ def test_string_values_special_characters(): def test_substring_feature(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -1222,8 +1029,7 @@ def test_substring_feature(): - substring: abc - substring: "def" - substring: "gh\\ni" - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) children = list(r.statement.get_children()) assert (Substring("abc") in children) is True @@ -1232,8 +1038,7 @@ def test_substring_feature(): def test_substring_description(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -1244,8 +1049,7 @@ def test_substring_description(): - or: - substring: abc description: the start of the alphabet - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) children = list(r.statement.get_children()) assert (Substring("abc") in children) is True @@ -1254,9 +1058,7 @@ def test_substring_description(): def test_filter_rules(): rules = capa.rules.RuleSet( [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: rule 1 @@ -1267,12 +1069,8 @@ def test_filter_rules(): - joe features: - api: CreateFile - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: rule 2 @@ -1281,9 +1079,7 @@ def test_filter_rules(): dynamic: process features: - string: joe - """ - ) - ), + """)), ] ) rules = rules.filter_rules_by_meta("joe") @@ -1294,9 +1090,7 @@ def test_filter_rules(): def test_filter_rules_dependencies(): rules = capa.rules.RuleSet( [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: rule 1 @@ -1305,12 +1099,8 @@ def test_filter_rules_dependencies(): dynamic: process features: - match: rule 2 - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: rule 2 @@ -1319,12 +1109,8 @@ def test_filter_rules_dependencies(): dynamic: process features: - match: rule 3 - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: rule 3 @@ -1333,9 +1119,7 @@ def test_filter_rules_dependencies(): dynamic: process features: - api: CreateFile - """ - ) - ), + """)), ] ) rules = rules.filter_rules_by_meta("rule 1") @@ -1349,9 +1133,7 @@ def test_filter_rules_missing_dependency(): with pytest.raises(capa.rules.InvalidRule): capa.rules.RuleSet( [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: rule 1 @@ -1362,18 +1144,14 @@ def test_filter_rules_missing_dependency(): - joe features: - match: rule 2 - """ - ) - ), + """)), ] ) def test_rules_namespace_dependencies(): rules = [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: rule 1 @@ -1383,12 +1161,8 @@ def test_rules_namespace_dependencies(): namespace: ns1/nsA features: - api: CreateFile - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: rule 2 @@ -1398,12 +1172,8 @@ def test_rules_namespace_dependencies(): namespace: ns1/nsB features: - api: CreateFile - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: rule 3 @@ -1412,12 +1182,8 @@ def test_rules_namespace_dependencies(): dynamic: process features: - match: ns1/nsA - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: rule 4 @@ -1426,9 +1192,7 @@ def test_rules_namespace_dependencies(): dynamic: process features: - match: ns1 - """ - ) - ), + """)), ] r3 = {r.name for r in capa.rules.get_rules_and_dependencies(rules, "rule 3")} @@ -1443,8 +1207,7 @@ def test_rules_namespace_dependencies(): def test_function_name_features(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -1457,8 +1220,7 @@ def test_function_name_features(): - function-name: strcmp = copy from here to there - function-name: strdup description: duplicate a string - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) children = list(r.statement.get_children()) assert (FunctionName("strcpy") in children) is True @@ -1467,8 +1229,7 @@ def test_function_name_features(): def test_os_features(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -1478,8 +1239,7 @@ def test_os_features(): features: - and: - os: windows - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) children = list(r.statement.get_children()) assert (OS(OS_WINDOWS) in children) is True @@ -1487,8 +1247,7 @@ def test_os_features(): def test_format_features(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -1498,8 +1257,7 @@ def test_format_features(): features: - and: - format: pe - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) children = list(r.statement.get_children()) assert (Format(FORMAT_PE) in children) is True @@ -1507,8 +1265,7 @@ def test_format_features(): def test_arch_features(): - rule = textwrap.dedent( - """ + rule = textwrap.dedent(""" rule: meta: name: test rule @@ -1518,8 +1275,7 @@ def test_arch_features(): features: - and: - arch: amd64 - """ - ) + """) r = capa.rules.Rule.from_yaml(rule) children = list(r.statement.get_children()) assert (Arch(ARCH_AMD64) in children) is True @@ -1527,9 +1283,7 @@ def test_arch_features(): def test_property_access(): - r = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + r = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -1538,9 +1292,7 @@ def test_property_access(): dynamic: process features: - property/read: System.IO.FileInfo::Length - """ - ) - ) + """)) assert bool(r.evaluate({Property("System.IO.FileInfo::Length", access=FeatureAccess.READ): {ADDR1}})) is True assert bool(r.evaluate({Property("System.IO.FileInfo::Length"): {ADDR1}})) is False @@ -1548,9 +1300,7 @@ def test_property_access(): def test_property_access_symbol(): - r = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + r = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -1559,9 +1309,7 @@ def test_property_access_symbol(): dynamic: process features: - property/read: System.IO.FileInfo::Length = some property - """ - ) - ) + """)) assert ( bool( r.evaluate( @@ -1577,9 +1325,7 @@ def test_property_access_symbol(): def test_translate_com_features(): - r = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + r = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -1590,9 +1336,7 @@ def test_translate_com_features(): - com/class: WICPngDecoder # 389ea17b-5078-4cde-b6ef-25c15175c751 WICPngDecoder # e018945b-aa86-4008-9bd4-6777a1e40c11 WICPngDecoder - """ - ) - ) + """)) com_name = "WICPngDecoder" com_features = [ capa.features.common.Bytes(b"{\xa1\x9e8xP\xdeL\xb6\xef%\xc1Qu\xc7Q", f"CLSID_{com_name} as bytes"), @@ -1606,53 +1350,39 @@ def test_translate_com_features(): def test_invalid_com_features(): # test for unknown COM class with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule features: - com/class: invalid_com - """ - ) - ) + """)) # test for unknown COM interface with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule features: - com/interface: invalid_com - """ - ) - ) + """)) # test for invalid COM type # valid_com_types = "class", "interface" with pytest.raises(capa.rules.InvalidRule): - _ = capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + _ = capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule features: - com/invalid_COM_type: WICPngDecoder - """ - ) - ) + """)) def test_circular_dependency(): rules = [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule 1 @@ -1664,12 +1394,8 @@ def test_circular_dependency(): - or: - match: test rule 2 - api: kernel32.VirtualAlloc - """ - ) - ), - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + """)), + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule 2 @@ -1679,9 +1405,7 @@ def test_circular_dependency(): lib: true features: - match: test rule 1 - """ - ) - ), + """)), ] with pytest.raises(capa.rules.InvalidRule): list(capa.rules.get_rules_and_dependencies(rules, rules[0].name)) diff --git a/tests/test_rules_insn_scope.py b/tests/test_rules_insn_scope.py index 86ebcd35..1b393dc5 100644 --- a/tests/test_rules_insn_scope.py +++ b/tests/test_rules_insn_scope.py @@ -21,9 +21,7 @@ import capa.rules def test_rule_scope_instruction(): - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -35,14 +33,10 @@ def test_rule_scope_instruction(): - mnemonic: mov - arch: i386 - os: windows - """ - ) - ) + """)) with pytest.raises(capa.rules.InvalidRule): - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -51,17 +45,11 @@ def test_rule_scope_instruction(): dynamic: unsupported features: - characteristic: embedded pe - """ - ) - ) + """)) def test_rule_subscope_instruction(): - rules = capa.rules.RuleSet( - [ - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + rules = capa.rules.RuleSet([capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -75,11 +63,7 @@ def test_rule_subscope_instruction(): - mnemonic: mov - arch: i386 - os: windows - """ - ) - ) - ] - ) + """))]) # the function rule scope will have one rules: # - `test rule` assert len(rules.function_rules) == 1 @@ -90,9 +74,7 @@ def test_rule_subscope_instruction(): def test_scope_instruction_implied_and(): - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -105,15 +87,11 @@ def test_scope_instruction_implied_and(): - mnemonic: mov - arch: i386 - os: windows - """ - ) - ) + """)) def test_scope_instruction_description(): - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -127,13 +105,9 @@ def test_scope_instruction_description(): - mnemonic: mov - arch: i386 - os: windows - """ - ) - ) + """)) - capa.rules.Rule.from_yaml( - textwrap.dedent( - """ + capa.rules.Rule.from_yaml(textwrap.dedent(""" rule: meta: name: test rule @@ -147,6 +121,4 @@ def test_scope_instruction_description(): - mnemonic: mov - arch: i386 - os: windows - """ - ) - ) + """)) diff --git a/tests/test_scripts.py b/tests/test_scripts.py index 37eb6a18..20b36f0b 100644 --- a/tests/test_scripts.py +++ b/tests/test_scripts.py @@ -142,8 +142,7 @@ def test_proto_conversion(tmp_path): def test_detect_duplicate_features(tmpdir): - TEST_RULE_0 = textwrap.dedent( - """ + TEST_RULE_0 = textwrap.dedent(""" rule: meta: name: Test Rule 0 @@ -155,12 +154,10 @@ def test_detect_duplicate_features(tmpdir): - number: 1 - not: - string: process - """ - ) + """) TEST_RULESET = { - "rule_1": textwrap.dedent( - """ + "rule_1": textwrap.dedent(""" rule: meta: name: Test Rule 1 @@ -179,10 +176,8 @@ def test_detect_duplicate_features(tmpdir): - count(mnemonic(xor)): 5 - not: - os: linux - """ - ), - "rule_2": textwrap.dedent( - """ + """), + "rule_2": textwrap.dedent(""" rule: meta: name: Test Rule 2 @@ -196,10 +191,8 @@ def test_detect_duplicate_features(tmpdir): - and: - api: CreateFile - mnemonic: xor - """ - ), - "rule_3": textwrap.dedent( - """ + """), + "rule_3": textwrap.dedent(""" rule: meta: name: Test Rule 3 @@ -214,8 +207,7 @@ def test_detect_duplicate_features(tmpdir): - and: - api: bind - number: 2 - """ - ), + """), } """ diff --git a/tests/test_vmray_model.py b/tests/test_vmray_model.py index 55277907..f1bf1025 100644 --- a/tests/test_vmray_model.py +++ b/tests/test_vmray_model.py @@ -26,11 +26,9 @@ from capa.features.extractors.vmray.models import ( def test_vmray_model_param(): - param_str = textwrap.dedent( - """ + param_str = textwrap.dedent(""" - """ - ) + """) param: Param = Param.model_validate(xml_to_dict(param_str)["param"]) assert param.value is not None @@ -38,13 +36,11 @@ def test_vmray_model_param(): def test_vmray_model_param_deref(): - param_str = textwrap.dedent( - """ + param_str = textwrap.dedent(""" - """ - ) + """) param: Param = Param.model_validate(xml_to_dict(param_str)["param"]) assert param.deref is not None @@ -52,8 +48,7 @@ def test_vmray_model_param_deref(): def test_vmray_model_function_call(): - function_call_str = textwrap.dedent( - """ + function_call_str = textwrap.dedent(""" @@ -62,8 +57,7 @@ def test_vmray_model_function_call(): - """ - ) + """) function_call: FunctionCall = FunctionCall.model_validate(xml_to_dict(function_call_str)["fncall"]) assert function_call.fncall_id == 18 @@ -81,22 +75,19 @@ def test_vmray_model_function_call(): def test_vmray_model_analysis_metadata(): - analysis_metadata: AnalysisMetadata = AnalysisMetadata.model_validate_json( - """ + analysis_metadata: AnalysisMetadata = AnalysisMetadata.model_validate_json(""" { "sample_type": "Linux ELF Executable (x86-64)", "submission_filename": "abcd1234" } - """ - ) + """) assert analysis_metadata.sample_type == "Linux ELF Executable (x86-64)" assert analysis_metadata.submission_filename == "abcd1234" def test_vmray_model_elffile(): - elffile: ElfFile = ElfFile.model_validate_json( - """ + elffile: ElfFile = ElfFile.model_validate_json(""" { "sections": [ { @@ -107,16 +98,14 @@ def test_vmray_model_elffile(): } ] } - """ - ) + """) assert elffile.sections[0].header.sh_name == "abcd1234" assert elffile.sections[0].header.sh_addr == 2863311530 def test_vmray_model_pefile(): - pefile: PEFile = PEFile.model_validate_json( - """ + pefile: PEFile = PEFile.model_validate_json(""" { "basic_info": { "image_base": 2863311530 @@ -150,8 +139,7 @@ def test_vmray_model_pefile(): } ] } - """ - ) + """) assert pefile.basic_info.image_base == 2863311530