From 16e32f8441608d1a447621780aa107777e70b547 Mon Sep 17 00:00:00 2001 From: Yacine Elhamer Date: Thu, 27 Jul 2023 10:31:45 +0100 Subject: [PATCH] add tests --- tests/test_fmt.py | 12 ++--- tests/test_main.py | 32 ++++++------ tests/test_optimizer.py | 2 +- tests/test_render.py | 4 +- tests/test_rule_cache.py | 4 +- tests/test_rules.py | 92 ++++++++++++++++++++++++++++------ tests/test_rules_insn_scope.py | 12 ++--- tests/test_scripts.py | 2 +- tests/test_static_freeze.py | 2 +- 9 files changed, 111 insertions(+), 51 deletions(-) diff --git a/tests/test_fmt.py b/tests/test_fmt.py index fc727c8f..8688db98 100644 --- a/tests/test_fmt.py +++ b/tests/test_fmt.py @@ -19,7 +19,7 @@ EXPECTED = textwrap.dedent( - user@domain.com scopes: static: function - dynamic: dev + dynamic: process examples: - foo1234 - bar5678 @@ -45,7 +45,7 @@ def test_rule_reformat_top_level_elements(): - user@domain.com scopes: static: function - dynamic: dev + dynamic: process examples: - foo1234 - bar5678 @@ -65,7 +65,7 @@ def test_rule_reformat_indentation(): - user@domain.com scopes: static: function - dynamic: dev + dynamic: process examples: - foo1234 - bar5678 @@ -91,7 +91,7 @@ def test_rule_reformat_order(): - bar5678 scopes: static: function - dynamic: dev + dynamic: process name: test rule features: - and: @@ -117,7 +117,7 @@ def test_rule_reformat_meta_update(): - bar5678 scopes: static: function - dynamic: dev + dynamic: process name: AAAA features: - and: @@ -143,7 +143,7 @@ def test_rule_reformat_string_description(): - user@domain.com scopes: static: function - dynamic: dev + dynamic: process features: - and: - string: foo diff --git a/tests/test_main.py b/tests/test_main.py index 94401667..51daa691 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -38,7 +38,7 @@ def test_main_single_rule(z9324d_extractor, tmpdir): name: test rule scopes: static: file - dynamic: dev + dynamic: process authors: - test features: @@ -103,7 +103,7 @@ def test_ruleset(): name: file rule scopes: static: file - dynamic: dev + dynamic: process features: - characteristic: embedded pe """ @@ -117,7 +117,7 @@ def test_ruleset(): name: function rule scopes: static: function - dynamic: dev + dynamic: process features: - characteristic: tight loop """ @@ -131,7 +131,7 @@ def test_ruleset(): name: basic block rule scopes: static: basic block - dynamic: dev + dynamic: process features: - characteristic: nzxor """ @@ -170,7 +170,7 @@ def test_ruleset(): assert len(rules.file_rules) == 2 assert len(rules.function_rules) == 2 assert len(rules.basic_block_rules) == 1 - assert len(rules.process_rules) == 1 + assert len(rules.process_rules) == 4 assert len(rules.thread_rules) == 1 @@ -186,7 +186,7 @@ def test_match_across_scopes_file_function(z9324d_extractor): name: install service scopes: static: function - dynamic: dev + dynamic: process examples: - 9324d1a8ae37a36ae560c37448c9705a:0x4073F0 features: @@ -206,7 +206,7 @@ def test_match_across_scopes_file_function(z9324d_extractor): name: .text section scopes: static: file - dynamic: dev + dynamic: process examples: - 9324d1a8ae37a36ae560c37448c9705a features: @@ -225,7 +225,7 @@ def test_match_across_scopes_file_function(z9324d_extractor): name: .text section and install service scopes: static: file - dynamic: dev + dynamic: process examples: - 9324d1a8ae37a36ae560c37448c9705a features: @@ -255,7 +255,7 @@ def test_match_across_scopes(z9324d_extractor): name: tight loop scopes: static: basic block - dynamic: dev + dynamic: process examples: - 9324d1a8ae37a36ae560c37448c9705a:0x403685 features: @@ -273,7 +273,7 @@ def test_match_across_scopes(z9324d_extractor): name: kill thread loop scopes: static: function - dynamic: dev + dynamic: process examples: - 9324d1a8ae37a36ae560c37448c9705a:0x403660 features: @@ -293,7 +293,7 @@ def test_match_across_scopes(z9324d_extractor): name: kill thread program scopes: static: file - dynamic: dev + dynamic: process examples: - 9324d1a8ae37a36ae560c37448c9705a features: @@ -322,7 +322,7 @@ def test_subscope_bb_rules(z9324d_extractor): name: test rule scopes: static: function - dynamic: dev + dynamic: process features: - and: - basic block: @@ -348,7 +348,7 @@ def test_byte_matching(z9324d_extractor): name: byte match test scopes: static: function - dynamic: dev + dynamic: process features: - and: - bytes: ED 24 9E F4 52 A9 07 47 55 8E E1 AB 30 8E 23 61 @@ -373,7 +373,7 @@ def test_count_bb(z9324d_extractor): namespace: test scopes: static: function - dynamic: dev + dynamic: process features: - and: - count(basic blocks): 1 or more @@ -399,7 +399,7 @@ def test_instruction_scope(z9324d_extractor): namespace: test scopes: static: instruction - dynamic: dev + dynamic: process features: - and: - mnemonic: push @@ -429,7 +429,7 @@ def test_instruction_subscope(z9324d_extractor): namespace: test scopes: static: function - dynamic: dev + dynamic: process features: - and: - arch: i386 diff --git a/tests/test_optimizer.py b/tests/test_optimizer.py index e310f307..68afc52c 100644 --- a/tests/test_optimizer.py +++ b/tests/test_optimizer.py @@ -25,7 +25,7 @@ def test_optimizer_order(): name: test rule scopes: static: function - dynamic: dev + dynamic: process features: - and: - substring: "foo" diff --git a/tests/test_render.py b/tests/test_render.py index 7d85da68..a692a61f 100644 --- a/tests/test_render.py +++ b/tests/test_render.py @@ -52,7 +52,7 @@ def test_render_meta_attack(): name: test rule scopes: static: function - dynamic: dev + dynamic: process authors: - foo att&ck: @@ -90,7 +90,7 @@ def test_render_meta_mbc(): name: test rule scopes: static: function - dynamic: dev + dynamic: process authors: - foo mbc: diff --git a/tests/test_rule_cache.py b/tests/test_rule_cache.py index 395e2fbc..0206e936 100644 --- a/tests/test_rule_cache.py +++ b/tests/test_rule_cache.py @@ -22,7 +22,7 @@ R1 = capa.rules.Rule.from_yaml( - user@domain.com scopes: static: function - dynamic: dev + dynamic: process examples: - foo1234 - bar5678 @@ -44,7 +44,7 @@ R2 = capa.rules.Rule.from_yaml( - user@domain.com scopes: static: function - dynamic: dev + dynamic: process examples: - foo1234 - bar5678 diff --git a/tests/test_rules.py b/tests/test_rules.py index fb6fb154..262be9a5 100644 --- a/tests/test_rules.py +++ b/tests/test_rules.py @@ -56,7 +56,7 @@ def test_rule_yaml(): - user@domain.com scopes: static: function - dynamic: dev + dynamic: process examples: - foo1234 - bar5678 @@ -248,7 +248,7 @@ def test_invalid_rule_feature(): name: test rule scopes: static: file - dynamic: dev + dynamic: process features: - characteristic: nzxor """ @@ -264,7 +264,7 @@ def test_invalid_rule_feature(): name: test rule scopes: static: function - dynamic: dev + dynamic: thread features: - characteristic: embedded pe """ @@ -280,28 +280,90 @@ def test_invalid_rule_feature(): name: test rule scopes: static: basic block - dynamic: dev + dynamic: thread features: - characteristic: embedded pe """ ) ) - with pytest.raises(capa.rules.InvalidRule): + +def test_multi_scope_rules_features(): + _ = capa.rules.Rule.from_yaml( + textwrap.dedent( + """ + rule: + meta: + name: test rule + scopes: + static: function + dynamic: process + features: + - or: + - api: write + - and: + - os: linux + - mnemonic: syscall + - number: 1 = write + """ + ) + ) + + _ = capa.rules.Rule.from_yaml( + textwrap.dedent( + """ + rule: + meta: + name: test rule + features: + - or: + - api: read + - and: + - os: linux + - mnemonic: syscall + - number: 0 = read + """ + ) + ) + + +def test_rules_flavor_filtering(): + rules = [ capa.rules.Rule.from_yaml( textwrap.dedent( """ rule: meta: - name: test rule + name: static rule scopes: static: function - dynamic: process features: - - mnemonic: xor + - api: CreateFileA """ ) - ) + ), + capa.rules.Rule.from_yaml( + textwrap.dedent( + """ + rule: + meta: + name: dynamic rule + scopes: + dynamic: thread + features: + - api: CreateFileA + """ + ) + ), + ] + + static_rules = capa.rules.RuleSet(rules, rules_filter_func=lambda rule: rule.scopes.static) + dynamic_rules = capa.rules.RuleSet(rules, rules_filter_func=lambda rule: rule.scopes.dynamic) + + # only static rule + assert len(static_rules) == 1 + # only dynamic rule + assert len(dynamic_rules) == 1 def test_lib_rules(): @@ -348,7 +410,7 @@ def test_subscope_rules(): name: test function subscope scopes: static: file - dynamic: dev + dynamic: process features: - and: - characteristic: embedded pe @@ -407,7 +469,7 @@ def test_subscope_rules(): # the process rule scope has three rules: # - the rule on which `test process subscope` depends, - assert len(rules.process_rules) == 2 + assert len(rules.process_rules) == 3 # the thread rule scope has one rule: # - the rule on which `test thread subscope` depends @@ -1025,7 +1087,7 @@ def test_function_name_features(): name: test rule scopes: static: file - dynamic: dev + dynamic: process features: - and: - function-name: strcpy @@ -1049,7 +1111,7 @@ def test_os_features(): name: test rule scopes: static: file - dynamic: dev + dynamic: process features: - and: - os: windows @@ -1069,7 +1131,7 @@ def test_format_features(): name: test rule scopes: static: file - dynamic: dev + dynamic: process features: - and: - format: pe @@ -1089,7 +1151,7 @@ def test_arch_features(): name: test rule scopes: static: file - dynamic: dev + dynamic: process features: - and: - arch: amd64 diff --git a/tests/test_rules_insn_scope.py b/tests/test_rules_insn_scope.py index dd0f6dc7..4bc0a14b 100644 --- a/tests/test_rules_insn_scope.py +++ b/tests/test_rules_insn_scope.py @@ -22,9 +22,8 @@ def test_rule_scope_instruction(): name: test rule scopes: static: instruction - dynamic: dev features: - - and: + - and: - mnemonic: mov - arch: i386 - os: windows @@ -41,7 +40,6 @@ def test_rule_scope_instruction(): name: test rule scopes: static: instruction - dynamic: dev features: - characteristic: embedded pe """ @@ -60,7 +58,7 @@ def test_rule_subscope_instruction(): name: test rule scopes: static: function - dynamic: dev + dynamic: process features: - and: - instruction: @@ -91,7 +89,7 @@ def test_scope_instruction_implied_and(): name: test rule scopes: static: function - dynamic: dev + dynamic: process features: - and: - instruction: @@ -112,7 +110,7 @@ def test_scope_instruction_description(): name: test rule scopes: static: function - dynamic: dev + dynamic: process features: - and: - instruction: @@ -132,7 +130,7 @@ def test_scope_instruction_description(): name: test rule scopes: static: function - dynamic: dev + dynamic: process features: - and: - instruction: diff --git a/tests/test_scripts.py b/tests/test_scripts.py index 199b4dbd..7a250d19 100644 --- a/tests/test_scripts.py +++ b/tests/test_scripts.py @@ -109,7 +109,7 @@ def test_detect_duplicate_features(tmpdir): name: Test Rule 0 scopes: static: function - dynamic: dev + dynamic: process features: - and: - number: 1 diff --git a/tests/test_static_freeze.py b/tests/test_static_freeze.py index 16dde31d..6bff6d22 100644 --- a/tests/test_static_freeze.py +++ b/tests/test_static_freeze.py @@ -90,7 +90,7 @@ def test_null_feature_extractor(): name: xor loop scopes: static: basic block - dynamic: dev + dynamic: process features: - and: - characteristic: tight loop