mirror of
https://github.com/mandiant/capa.git
synced 2026-02-04 19:12:01 -08:00
add call-scope tests
This commit is contained in:
@@ -124,7 +124,7 @@ class Scopes:
|
||||
|
||||
def __repr__(self) -> str:
|
||||
if self.static and self.dynamic:
|
||||
return f"static-scope: {self.static}, dyanamic-scope: {self.dynamic}"
|
||||
return f"static-scope: {self.static}, dynamic-scope: {self.dynamic}"
|
||||
elif self.static:
|
||||
return f"static-scope: {self.static}"
|
||||
elif self.dynamic:
|
||||
@@ -1267,6 +1267,7 @@ class RuleSet:
|
||||
self.file_rules = self._get_rules_for_scope(rules, FILE_SCOPE)
|
||||
self.process_rules = self._get_rules_for_scope(rules, PROCESS_SCOPE)
|
||||
self.thread_rules = self._get_rules_for_scope(rules, THREAD_SCOPE)
|
||||
self.call_rules = self._get_rules_for_scope(rules, CALL_SCOPE)
|
||||
self.function_rules = self._get_rules_for_scope(rules, FUNCTION_SCOPE)
|
||||
self.basic_block_rules = self._get_rules_for_scope(rules, BASIC_BLOCK_SCOPE)
|
||||
self.instruction_rules = self._get_rules_for_scope(rules, INSTRUCTION_SCOPE)
|
||||
@@ -1279,6 +1280,7 @@ class RuleSet:
|
||||
self.process_rules
|
||||
)
|
||||
(self._easy_thread_rules_by_feature, self._hard_thread_rules) = self._index_rules_by_feature(self.thread_rules)
|
||||
(self._easy_call_rules_by_feature, self._hard_call_rules) = self._index_rules_by_feature(self.call_rules)
|
||||
(self._easy_function_rules_by_feature, self._hard_function_rules) = self._index_rules_by_feature(
|
||||
self.function_rules
|
||||
)
|
||||
@@ -1533,6 +1535,9 @@ class RuleSet:
|
||||
elif scope == Scope.THREAD:
|
||||
easy_rules_by_feature = self._easy_thread_rules_by_feature
|
||||
hard_rule_names = self._hard_thread_rules
|
||||
elif scope == Scope.CALL:
|
||||
easy_rules_by_feature = self._easy_call_rules_by_feature
|
||||
hard_rule_names = self._hard_call_rules
|
||||
elif scope == Scope.FUNCTION:
|
||||
easy_rules_by_feature = self._easy_function_rules_by_feature
|
||||
hard_rule_names = self._hard_function_rules
|
||||
|
||||
@@ -165,13 +165,55 @@ def test_ruleset():
|
||||
"""
|
||||
)
|
||||
),
|
||||
capa.rules.Rule.from_yaml(
|
||||
textwrap.dedent(
|
||||
"""
|
||||
rule:
|
||||
meta:
|
||||
name: test call subscope
|
||||
scopes:
|
||||
static: basic block
|
||||
dynamic: thread
|
||||
features:
|
||||
- and:
|
||||
- string: "explorer.exe"
|
||||
- call:
|
||||
- api: HttpOpenRequestW
|
||||
"""
|
||||
)
|
||||
),
|
||||
capa.rules.Rule.from_yaml(
|
||||
textwrap.dedent(
|
||||
"""
|
||||
rule:
|
||||
meta:
|
||||
name: test rule
|
||||
scopes:
|
||||
static: instruction
|
||||
dynamic: call
|
||||
features:
|
||||
- and:
|
||||
- or:
|
||||
- api: socket
|
||||
- and:
|
||||
- os: linux
|
||||
- mnemonic: syscall
|
||||
- number: 41 = socket()
|
||||
- number: 6 = IPPROTO_TCP
|
||||
- number: 1 = SOCK_STREAM
|
||||
- number: 2 = AF_INET
|
||||
"""
|
||||
)
|
||||
),
|
||||
]
|
||||
)
|
||||
assert len(rules.file_rules) == 2
|
||||
assert len(rules.function_rules) == 2
|
||||
assert len(rules.basic_block_rules) == 1
|
||||
assert len(rules.basic_block_rules) == 2
|
||||
assert len(rules.instruction_rules) == 1
|
||||
assert len(rules.process_rules) == 4
|
||||
assert len(rules.thread_rules) == 1
|
||||
assert len(rules.thread_rules) == 2
|
||||
assert len(rules.call_rules) == 2
|
||||
|
||||
|
||||
def test_match_across_scopes_file_function(z9324d_extractor):
|
||||
|
||||
@@ -353,6 +353,30 @@ def test_multi_scope_rules_features():
|
||||
)
|
||||
)
|
||||
|
||||
_ = capa.rules.Rule.from_yaml(
|
||||
textwrap.dedent(
|
||||
"""
|
||||
rule:
|
||||
meta:
|
||||
name: test rule
|
||||
scopes:
|
||||
static: instruction
|
||||
dynamic: call
|
||||
features:
|
||||
- and:
|
||||
- or:
|
||||
- api: socket
|
||||
- and:
|
||||
- os: linux
|
||||
- mnemonic: syscall
|
||||
- number: 41 = socket()
|
||||
- number: 6 = IPPROTO_TCP
|
||||
- number: 1 = SOCK_STREAM
|
||||
- number: 2 = AF_INET
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_rules_flavor_filtering():
|
||||
rules = [
|
||||
@@ -489,12 +513,30 @@ def test_subscope_rules():
|
||||
"""
|
||||
)
|
||||
),
|
||||
capa.rules.Rule.from_yaml(
|
||||
textwrap.dedent(
|
||||
"""
|
||||
rule:
|
||||
meta:
|
||||
name: test call subscope
|
||||
scopes:
|
||||
static: basic block
|
||||
dynamic: thread
|
||||
features:
|
||||
- and:
|
||||
- string: "explorer.exe"
|
||||
- call:
|
||||
- api: HttpOpenRequestW
|
||||
"""
|
||||
)
|
||||
),
|
||||
]
|
||||
)
|
||||
# the file rule scope will have two rules:
|
||||
# - `test function subscope` and `test process subscope`
|
||||
# plus the dynamic flavor of all rules
|
||||
# assert len(rules.file_rules) == 4
|
||||
# the file rule scope will have four rules:
|
||||
# - `test function subscope`, `test process subscope` and
|
||||
# `test thread subscope` for the static scope
|
||||
# - and `test process subscope` for both scopes
|
||||
assert len(rules.file_rules) == 3
|
||||
|
||||
# the function rule scope have two rule:
|
||||
# - the rule on which `test function subscope` depends
|
||||
@@ -504,9 +546,14 @@ def test_subscope_rules():
|
||||
# - the rule on which `test process subscope` depends,
|
||||
assert len(rules.process_rules) == 3
|
||||
|
||||
# the thread rule scope has one rule:
|
||||
# the thread rule scope has two rule:
|
||||
# - the rule on which `test thread subscope` depends
|
||||
assert len(rules.thread_rules) == 1
|
||||
# - the `test call subscope` rule
|
||||
assert len(rules.thread_rules) == 2
|
||||
|
||||
# the call rule scope has one rule:
|
||||
# - the rule on which `test call subcsope` depends
|
||||
assert len(rules.call_rules) == 1
|
||||
|
||||
|
||||
def test_duplicate_rules():
|
||||
|
||||
0
tests/unsupported_capa_rules.txt
Normal file
0
tests/unsupported_capa_rules.txt
Normal file
0
tests/unsupported_capa_rules.yml
Normal file
0
tests/unsupported_capa_rules.yml
Normal file
Reference in New Issue
Block a user