summaryrefslogtreecommitdiff
path: root/tests/analysis
diff options
context:
space:
mode:
Diffstat (limited to 'tests/analysis')
-rw-r--r--tests/analysis/scan/functions.py77
-rw-r--r--tests/analysis/scan/fuzzing.py179
-rw-r--r--tests/analysis/scan/grammar.py227
-rw-r--r--tests/analysis/scan/matches.py41
-rw-r--r--tests/analysis/scan/pyapi.py209
-rw-r--r--tests/analysis/scan/scanning_hex.py89
-rw-r--r--tests/analysis/scan/scanning_str.py20
7 files changed, 786 insertions, 56 deletions
diff --git a/tests/analysis/scan/functions.py b/tests/analysis/scan/functions.py
index 96f029f..6aca957 100644
--- a/tests/analysis/scan/functions.py
+++ b/tests/analysis/scan/functions.py
@@ -9,6 +9,41 @@ class TestRostFunctions(RostTestClass):
# Core
# ====
+ def testSetCounter(self):
+ """Count quantities and set sizes."""
+
+ rule = '''
+rule test {
+
+ condition:
+ count("ABC") == 3
+ and count("AB", "C") == count("ABC")
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+
+ cnt = MemoryContent(b'\x01\x02\x02\x03\x03\x03')
+
+ rule = '''
+rule test {
+
+ bytes:
+ $int_01 = "\x01"
+ $int_02 = "\x02"
+ $int_3 = "\x03"
+
+ condition:
+ count($int_0*, $int_3) == #int_*
+
+}
+'''
+
+ self.check_rule_success(rule, cnt)
+
+
def testDatasize(self):
"""Handle the size of the provided data."""
@@ -33,6 +68,32 @@ rule test {
self.check_rule_success(rule, cnt)
+ def testMaxCommon(self):
+ """Count the largest quantity of same items in a set."""
+
+ cnt = MemoryContent(b'')
+
+ cases = [
+ [ '1', 1 ],
+ [ '1, 2, 3', 1 ],
+ [ '1, 2, 1, 3, 1', 3 ],
+ [ '1, "a", 2, 3, "a"', 2 ],
+ ]
+
+ for c, q in cases:
+
+ rule = '''
+rule test {
+
+ condition:
+ maxcommon(%s) == %u
+
+}
+''' % (c, q)
+
+ self.check_rule_success(rule, cnt)
+
+
# Modules
# =======
@@ -108,6 +169,7 @@ rule test {
self.check_rule_success(rule)
+
rule = '''
rule test {
@@ -119,6 +181,7 @@ rule test {
self.check_rule_success(rule)
+
rule = '''
rule test {
@@ -134,6 +197,19 @@ rule test {
self.check_rule_success(rule)
+ rule = r'''
+rule test {
+
+ condition:
+ "A\x00B\x00C\x00D\x00" endswith string.wide("CD")
+ and "A\x00B\x00C\x00D\x00" contains string.wide("BC")
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+
def testTime(self):
"""Check current time."""
@@ -150,6 +226,7 @@ rule test {
self.check_rule_success(rule)
+
rule = '''
rule test {
diff --git a/tests/analysis/scan/fuzzing.py b/tests/analysis/scan/fuzzing.py
index 53227af..1b9b25b 100644
--- a/tests/analysis/scan/fuzzing.py
+++ b/tests/analysis/scan/fuzzing.py
@@ -108,3 +108,182 @@ rule test {
'''
self.check_rule_failure(rule)
+
+
+ def testSelfReferencingRule(self):
+ """Expect only one argument for the not operator, even in debug mode."""
+
+ rule = '''
+rule test {
+
+ condition:
+ not(0)
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+
+ def testNoCommon(self):
+ """Handle the case where no common item is found from an empty set."""
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = "a"
+
+ condition:
+ maxcommon($a) == 0
+
+}
+'''
+
+ self.check_rule_success(rule)
+
+
+ def testAAsAcharacter(self):
+ """Consider the 'a' character as a valid lowercase character."""
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = "0000a0I0" nocase
+
+ condition:
+ $a
+
+}
+'''
+
+ self.check_rule_failure(rule)
+
+
+ def testAAsAcharacter(self):
+ """Do not expect initialized trackers when there is no real defined search pattern."""
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = {[0]}
+
+ condition:
+ $a
+
+}
+'''
+
+ with self.assertRaisesRegex(ValueError, 'Unable to create content scanner'):
+
+ scanner = ContentScanner(rule)
+
+
+ def testAllocations(self):
+ """Handle big alloctions for strings in conditions with regular expressions."""
+
+ rule = '''
+rule test {
+
+ condition:
+ "%s" == "%s"
+
+}
+''' % ("0" * (256 * 2 + 8), "0" * (256 * 2 + 8))
+
+ self.check_rule_success(rule)
+
+
+ def testFileFinalAccess(self):
+ """Ensure patterns found at the edges of scanned content do not crash the scanner."""
+
+ cnt = MemoryContent(bytes([ 0 for i in range(16) ]))
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { 00 00 00 00 00 00 00 00 }
+
+ condition:
+ $a
+
+}
+'''
+
+ self.check_rule_success(rule, cnt)
+
+
+ def testValidHexRangeMerge(self):
+ """Merge valid hexadecimal ranges."""
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { [0] ?? }
+
+ condition:
+ $a
+
+}
+'''
+
+ with self.assertRaisesRegex(ValueError, 'Unable to create content scanner'):
+
+ scanner = ContentScanner(rule)
+
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { [2] ?? }
+
+ condition:
+ $a
+
+}
+'''
+
+ self.check_rule_failure(rule)
+
+
+ def testSmallBase64(self):
+ """Handle small base64 encodings which may produce few patterns."""
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = "0" base64
+
+ condition:
+ $a
+
+}
+'''
+
+ self.check_rule_failure(rule)
+
+
+ def testCountIndex(self):
+ """Ban pattern count indexes from the grammer."""
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = "1"
+
+ condition:
+ #*[0]
+
+}
+'''
+
+ with self.assertRaisesRegex(ValueError, 'Unable to create content scanner'):
+
+ scanner = ContentScanner(rule)
diff --git a/tests/analysis/scan/grammar.py b/tests/analysis/scan/grammar.py
index 13a255b..14f67fa 100644
--- a/tests/analysis/scan/grammar.py
+++ b/tests/analysis/scan/grammar.py
@@ -2,6 +2,7 @@
import json
from common import RostTestClass
+from pychrysalide.analysis.contents import MemoryContent
class TestRostGrammar(RostTestClass):
@@ -250,6 +251,232 @@ rule test {
self.check_rule_failure(rule)
+ def testMatchCount(self):
+ """Ensure match count provides expected values."""
+
+ cnt = MemoryContent(b'\x01\x02\x02\x03\x03\x03')
+
+ rule = '''
+rule test {
+
+ bytes:
+ $int_01 = "\x01"
+ $int_02 = "\x02"
+ $int_03 = "\x03"
+
+ condition:
+ #int_01 == count($int_01) and #int_01 == 1
+ and #int_02 == count($int_02) and #int_02 == 2
+ and #int_03 == count($int_03) and #int_03 == 3
+ and #int_0* == count($int_0*) and #int_0* == 6
+
+}
+'''
+
+ self.check_rule_success(rule, cnt)
+
+
+ def testBackingUpHandlers(self):
+ """Ensure handlers for backing up removals do not limit the grammar."""
+
+ cnt = MemoryContent(b'AB12')
+
+ # Uncompleted token in rule definition: '?? ?? '
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { ?? ?? }
+
+ condition:
+ #a == 3
+
+}
+'''
+
+ self.check_rule_success(rule, content=cnt)
+
+ # Uncompleted token in rule definition: '?? '
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { ?? 4? }
+
+ condition:
+ #a == 1
+
+}
+'''
+
+ self.check_rule_success(rule, content=cnt)
+
+ # Uncompleted token in rule definition: '?? ?'
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { ?? ?2 }
+
+ condition:
+ #a == 2
+
+}
+'''
+
+ self.check_rule_success(rule, content=cnt)
+
+ # Uncompleted token in rule definition: '?? '
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { ?? 42 }
+
+ condition:
+ #a == 1
+
+}
+'''
+
+ self.check_rule_success(rule, content=cnt)
+
+
+ # Uncompleted token in rule definition: '?1 ?'
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { ?1 ?? }
+
+ condition:
+ #a == 2
+
+}
+'''
+
+ self.check_rule_success(rule, content=cnt)
+
+ # Uncompleted token in rule definition: '?1 4? '
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { ?1 4? }
+
+ condition:
+ #a == 1
+
+}
+'''
+
+ self.check_rule_success(rule, content=cnt)
+
+ # Uncompleted token in rule definition: '?1 ?2 '
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { ?1 ?2 }
+
+ condition:
+ #a == 2
+
+}
+'''
+
+ self.check_rule_success(rule, content=cnt)
+
+ # Uncompleted token in rule definition: '?1 4'
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { ?1 42 }
+
+ condition:
+ #a == 1
+
+}
+'''
+
+ self.check_rule_success(rule, content=cnt)
+
+
+ # Uncompleted token in rule definition: '41 '
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { 41 ?? }
+
+ condition:
+ #a == 1
+
+}
+'''
+
+ self.check_rule_success(rule, content=cnt)
+
+ # Uncompleted token in rule definition: '41 4'
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { 41 4? }
+
+ condition:
+ #a == 1
+
+}
+'''
+
+ self.check_rule_success(rule, content=cnt)
+
+ # Uncompleted token in rule definition: '41 '
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { 41 ?2 }
+
+ condition:
+ #a == 1
+
+}
+'''
+
+ self.check_rule_success(rule, content=cnt)
+
+ # Uncompleted token in rule definition: '41 42 '
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = { 41 42 }
+
+ condition:
+ #a == 1
+
+}
+'''
+
+ self.check_rule_success(rule, content=cnt)
+
+
+
# TODO : test <haystack> matches <regex>
diff --git a/tests/analysis/scan/matches.py b/tests/analysis/scan/matches.py
index 0d7556e..efcae4f 100644
--- a/tests/analysis/scan/matches.py
+++ b/tests/analysis/scan/matches.py
@@ -7,14 +7,14 @@ class TestRostMatchs(RostTestClass):
"""TestCases for the ROST pattern matching engine."""
def testCountMatches(self):
- """Count matches patterns."""
+ """Count matched patterns."""
cnt = MemoryContent(b'aaa aaa bbb aaa')
rule = '''
rule test {
- strings:
+ bytes:
$a = "aaa"
$b = "bbb"
@@ -25,3 +25,40 @@ rule test {
'''
self.check_rule_success(rule, cnt)
+
+
+ def testCountSameMatches(self):
+ """Count matches of similar patterns."""
+
+ cnt = MemoryContent(b'ABCDabcdABCDabcd')
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = "\x61\x62\x63\x64"
+ $b = "\x61\x62\x63\x64"
+
+ condition:
+ #a == 2 and #b == 2
+
+}
+'''
+
+ self.check_rule_success(rule, cnt)
+
+
+ rule = '''
+rule test {
+
+ bytes:
+ $a = "\x61\x62\x63\x64"
+ $b = "\x61\x62\x63"
+
+ condition:
+ #a == 2 and #b == 2
+
+}
+'''
+
+ self.check_rule_success(rule, cnt)
diff --git a/tests/analysis/scan/pyapi.py b/tests/analysis/scan/pyapi.py
index 4b066f3..7a697b3 100644
--- a/tests/analysis/scan/pyapi.py
+++ b/tests/analysis/scan/pyapi.py
@@ -1,5 +1,6 @@
import binascii
+import struct
from chrysacase import ChrysalideTestCase
from gi._constants import TYPE_INVALID
@@ -34,7 +35,7 @@ class TestRostPythonAPI(ChrysalideTestCase):
class StrLenExpr(ScanExpression):
def __init__(self, value):
- super().__init__(ScanExpression.ExprValueType.STRING)
+ super().__init__(ScanExpression.ScanReductionState.REDUCED)
self._value = value
def _cmp_rich(self, other, op):
@@ -73,6 +74,7 @@ class TestRostPythonAPI(ChrysalideTestCase):
self.assertEqual(source, transformed[0])
+
mod = find_token_modifiers_for_name('hex')
self.assertIsNotNone(mod)
@@ -81,6 +83,7 @@ class TestRostPythonAPI(ChrysalideTestCase):
self.assertEqual(binascii.hexlify(source), transformed[0])
+
mod = find_token_modifiers_for_name('rev')
self.assertIsNotNone(mod)
@@ -88,3 +91,207 @@ class TestRostPythonAPI(ChrysalideTestCase):
transformed = mod.transform(source)
self.assertEqual(source[::-1], transformed[0])
+
+
+ mod = find_token_modifiers_for_name('lower')
+ self.assertIsNotNone(mod)
+
+ source = b'AbC'
+ transformed = mod.transform(source)
+
+ self.assertEqual(source.lower(), transformed[0])
+
+
+ mod = find_token_modifiers_for_name('upper')
+ self.assertIsNotNone(mod)
+
+ source = b'AbC'
+ transformed = mod.transform(source)
+
+ self.assertEqual(source.upper(), transformed[0])
+
+
+ mod = find_token_modifiers_for_name('wide')
+ self.assertIsNotNone(mod)
+
+ source = b'ABC'
+ transformed = mod.transform(source)
+
+ self.assertEqual(source.decode('ascii'), transformed[0].decode('utf-16-le'))
+
+
+ mod = find_token_modifiers_for_name('base64')
+ self.assertIsNotNone(mod)
+
+ source = b'ABC'
+ transformed = mod.transform(source)
+
+ self.assertEqual(len(transformed), 3)
+ self.assertEqual(transformed[0], b'QUJD')
+ self.assertEqual(transformed[1], b'FCQ')
+ self.assertEqual(transformed[2], b'BQk')
+
+
+ def testClassicalAPIHashing(self):
+ """Reproduce classical API Hashing results."""
+
+ def b2i(t):
+ return struct.unpack('<I', t)[0]
+
+
+ # Example:
+ # - PlugX (2020) - https://vms.drweb.fr/virus/?i=21512304
+
+ mod = find_token_modifiers_for_name('crc32')
+ self.assertIsNotNone(mod)
+
+ source = b'GetCurrentProcess\x00'
+ transformed = mod.transform(source)
+
+ self.assertEqual(b2i(transformed[0]), 0x3690e66)
+
+
+ # Example:
+ # - GuLoader (2020) - https://www.crowdstrike.com/blog/guloader-malware-analysis/
+
+ mod = find_token_modifiers_for_name('djb2')
+ self.assertIsNotNone(mod)
+
+ source = b'GetProcAddress'
+ transformed = mod.transform(source)
+
+ self.assertEqual(b2i(transformed[0]), 0xcf31bb1f)
+
+
+ def testCustomAPIHashing(self):
+ """Reproduce custom API Hashing results."""
+
+ def b2i(t):
+ return struct.unpack('<I', t)[0]
+
+
+ # Example:
+ # Underminer Exploit Kit (2019) - https://jsac.jpcert.or.jp/archive/2019/pdf/JSAC2019_1_koike-nakajima_jp.pdf
+
+ mod = find_token_modifiers_for_name('add1505-shl5')
+ self.assertIsNotNone(mod)
+
+ source = b'LoadLibraryA'
+ transformed = mod.transform(source)
+
+ self.assertEqual(b2i(transformed[0]), 0x5fbff0fb)
+
+
+ # Example:
+ # Enigma Stealer (2023) https://www.trendmicro.com/es_mx/research/23/b/enigma-stealer-targets-cryptocurrency-industry-with-fake-jobs.html
+
+ mod = find_token_modifiers_for_name('enigma-murmur')
+ self.assertIsNotNone(mod)
+
+ source = b'CreateMutexW'
+ transformed = mod.transform(source)
+
+ self.assertEqual(b2i(transformed[0]), 0xfd43765a)
+
+
+ # Examples:
+ # - ShadowHammer (2019) - https://blog.f-secure.com/analysis-shadowhammer-asus-attack-first-stage-payload/
+ # - ShadowHammer (2019) - https://securelist.com/operation-shadowhammer-a-high-profile-supply-chain-attack/90380/
+
+ mod = find_token_modifiers_for_name('imul21-add')
+ self.assertIsNotNone(mod)
+
+ source = b'VirtualAlloc'
+ transformed = mod.transform(source)
+
+ self.assertEqual(b2i(transformed[0]), 0xdf894b12)
+
+
+ # Examples:
+ # - Bottle Exploit Kit (2019) - https://nao-sec.org/2019/12/say-hello-to-bottle-exploit-kit.html
+ # - ShadowHammer (2019) - https://securelist.com/operation-shadowhammer-a-high-profile-supply-chain-attack/90380/
+
+ mod = find_token_modifiers_for_name('imul83-add')
+ self.assertIsNotNone(mod)
+
+ source = b'GetProcAddress'
+ transformed = mod.transform(source)
+
+ self.assertEqual(b2i(transformed[0]), 0x9ab9b854)
+
+
+ # Examples:
+ # - ?? (2021) - https://www.threatspike.com/blogs/reflective-dll-injection
+ # - Mustang Panda (2022) - https://blog.talosintelligence.com/mustang-panda-targets-europe/
+
+ mod = find_token_modifiers_for_name('ror13')
+ self.assertIsNotNone(mod)
+
+ source = b'GetProcAddress'
+ transformed = mod.transform(source)
+
+ self.assertEqual(b2i(transformed[0]), 0x7c0dfcaa)
+
+ source = b'VirtualAlloc'
+ transformed = mod.transform(source)
+
+ self.assertEqual(b2i(transformed[0]), 0x91afca54)
+
+
+ # Example:
+ # - Energetic Bear (2019) - https://insights.sei.cmu.edu/blog/api-hashing-tool-imagine-that/
+
+ mod = find_token_modifiers_for_name('sll1-add-hash32')
+ self.assertIsNotNone(mod)
+
+ source = b'LoadLibraryA'
+ transformed = mod.transform(source)
+
+ self.assertEqual(b2i(transformed[0]), 0x000d5786)
+
+
+ # Example:
+ # - SideWinder/WarHawk (2022) - https://www.zscaler.com/blogs/security-research/warhawk-new-backdoor-arsenal-sidewinder-apt-group
+
+ mod = find_token_modifiers_for_name('sub42')
+ self.assertIsNotNone(mod)
+
+ source = b'LoadLibraryA'
+ transformed = mod.transform(source)
+
+ self.assertEqual(transformed[0], b'\x8e\xb1\xa3\xa6\x8e\xab\xa4\xb4\xa3\xb4\xbb\x83')
+
+
+ # Example:
+ # - TrickBot (2021) - https://medium.com/walmartglobaltech/trickbot-crews-new-cobaltstrike-loader-32c72b78e81c
+
+ mod = find_token_modifiers_for_name('sub-index1')
+ self.assertIsNotNone(mod)
+
+ source = b'raw.githubusercontent.com'
+ transformed = mod.transform(source)
+
+ self.assertEqual(transformed[0], b'\x73\x63\x7a\x32\x6c\x6f\x7b\x70\x7e\x6c\x80\x7f\x72\x80\x72\x7f\x7f\x86\x78\x82\x89\x44\x7a\x87\x86')
+
+
+ def testBytePatternModifiersAPI(self):
+ """Validate the API for pattern modifiers."""
+
+ mod = find_token_modifiers_for_name('plain')
+ self.assertIsNotNone(mod)
+
+ source = [ b'ABC', b'01234' ]
+ transformed = mod.transform(source)
+
+ self.assertEqual(len(source), len(transformed))
+ self.assertEqual(source[0], transformed[0])
+ self.assertEqual(source[1], transformed[1])
+
+
+ mod = find_token_modifiers_for_name('xor')
+ self.assertIsNotNone(mod)
+
+ source = [ b'ABC' ]
+ transformed = mod.transform(source, 0x20)
+
+ self.assertEqual(transformed[0], b'abc')
diff --git a/tests/analysis/scan/scanning_hex.py b/tests/analysis/scan/scanning_hex.py
index 32979c8..4b0fda4 100644
--- a/tests/analysis/scan/scanning_hex.py
+++ b/tests/analysis/scan/scanning_hex.py
@@ -14,7 +14,7 @@ class TestRostScanningBinary(RostTestClass):
rule = '''
rule test {
- strings:
+ bytes:
$a = { 41 }
condition:
@@ -31,7 +31,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { 62 }
condition:
@@ -48,7 +48,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { 66 }
condition:
@@ -65,7 +65,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ?1 }
condition:
@@ -82,7 +82,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ?2 }
condition:
@@ -99,7 +99,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ?6 }
condition:
@@ -111,7 +111,7 @@ rule test {
self.check_rule_success(rule, content=cnt)
- def testLonelyPatternsNot(self):
+ def ___testLonelyPatternsNot(self):
"""Evaluate the most simple patterns (not version)."""
cnt = MemoryContent(b'Abcdef')
@@ -119,7 +119,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ~41 }
condition:
@@ -136,7 +136,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ~62 }
condition:
@@ -153,7 +153,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ~66 }
condition:
@@ -170,7 +170,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ~?1 }
condition:
@@ -187,7 +187,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ~?2 }
condition:
@@ -204,7 +204,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ~?6 }
condition:
@@ -224,7 +224,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { 41 62 63 }
condition:
@@ -241,7 +241,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { 2d 41 62 63 }
condition:
@@ -261,7 +261,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ?1 6? ?3 }
condition:
@@ -281,7 +281,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { 41 6? ?3 }
condition:
@@ -298,7 +298,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { 4? 62 ?3 }
condition:
@@ -315,7 +315,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { 4? ?2 63 }
condition:
@@ -332,7 +332,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { 4? ?2 ?3 }
condition:
@@ -349,7 +349,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { 2d 4? ?2 63 }
condition:
@@ -366,7 +366,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { 2d 4? 62 ?3 2d }
condition:
@@ -383,7 +383,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { 2? 41 6? 63 ?d }
condition:
@@ -403,7 +403,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { 33 ?? 41 ?? 63 ?? 34 }
condition:
@@ -420,7 +420,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ?? 33 ?? 41 ?? 63 ?? 34 ?? }
condition:
@@ -437,7 +437,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ?? 33 [1-5] 63 ?? 34 ?? }
condition:
@@ -454,7 +454,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { [3-4] 41 ?? 63 ?? 34 ?? }
condition:
@@ -471,7 +471,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ?? 33 ?? 41 ?? 63 [3-] }
condition:
@@ -491,7 +491,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ?3 ?? 4? ?? 6? ?? ?4 }
condition:
@@ -508,7 +508,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ?? ?3 ?? 4? ?? 6? ?? ?4 ?? }
condition:
@@ -525,7 +525,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ?? ?3 [1-5] ?3 ?? ?4 ?? }
condition:
@@ -542,7 +542,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { [3-4] ?1 ?? ?3 ?? ?4 ?? }
condition:
@@ -559,7 +559,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ?? 3? ?? 4? ?? 6? [3-] }
condition:
@@ -579,7 +579,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { 41 62 ( 63 | 64 | 65 ) }
condition:
@@ -596,7 +596,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ( 41 | f2 | f3 ) 62 63 }
condition:
@@ -613,7 +613,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { 41 ( 61 | 62 | 63 ) 63 }
condition:
@@ -630,7 +630,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ( 41 62 63 | 42 62 63 | 43 62 63 ) }
condition:
@@ -643,14 +643,14 @@ rule test {
def testPipedMaskedHexPatterns(self):
- """Look for several patterns at once with piped definition."""
+ """Look for several patterns at once with piped and masked definition."""
cnt = MemoryContent(b'123-Abc-456')
rule = '''
rule test {
- strings:
+ bytes:
$a = { 4? 6? ( ?3 | ?4 | ?5 ) }
condition:
@@ -667,11 +667,11 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { ( ?1 | ?2 | ?3 ) 6? 6? }
condition:
- console.log("COUNTER: ", #a) and #a == 1 and @a[0] == 4 and !a[0] == 3
+ #a == 1 and @a[0] == 4 and !a[0] == 3
}
'''
@@ -684,7 +684,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = { 4? ( ?1 | ?2 | ?3 ) 6? }
condition:
@@ -696,12 +696,15 @@ rule test {
self.check_rule_success(rule, content=cnt)
+ def testDuplicatedResultsFiltering(self):
+ """Filter duplicated results."""
+
cnt = MemoryContent(b'123-Abc-456')
rule = '''
rule test {
- strings:
+ bytes:
$a = { ( 4? ?2 ?3 | 4? 6? 6? | ?3 6? ?3 ) }
condition:
diff --git a/tests/analysis/scan/scanning_str.py b/tests/analysis/scan/scanning_str.py
index ff36ca3..75427a7 100644
--- a/tests/analysis/scan/scanning_str.py
+++ b/tests/analysis/scan/scanning_str.py
@@ -14,7 +14,7 @@ class TestRostScanningStrings(RostTestClass):
rule = '''
rule test {
- strings:
+ bytes:
$a = "Abc"
condition:
@@ -34,7 +34,7 @@ rule test {
rule = r'''
rule test {
- strings:
+ bytes:
$a = "\a\b\t\n\v\f\r\e\"\\\xff"
condition:
@@ -51,7 +51,7 @@ rule test {
rule = r'''
rule test {
- strings:
+ bytes:
$a = "\a\b\t\n--123--\v\f\r\e\"\\\xff"
condition:
@@ -71,7 +71,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = "ABC" hex
condition:
@@ -88,7 +88,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = "ABC" plain
condition:
@@ -105,7 +105,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = "ABC" rev
condition:
@@ -123,7 +123,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = "DEF" fullword
$b = "123" fullword
@@ -141,7 +141,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = "DEF" fullword
$b = "123" fullword
@@ -159,7 +159,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = "DEF" fullword
$b = "123" fullword
@@ -180,7 +180,7 @@ rule test {
rule = '''
rule test {
- strings:
+ bytes:
$a = "Abc" nocase
$b = "ABC123DEF456GHI" nocase
$z = "z0z1z2z3z4z5z6z7z8z9" nocase