summaryrefslogtreecommitdiff
path: root/tests/analysis/scan/grammar.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/analysis/scan/grammar.py')
-rw-r--r--tests/analysis/scan/grammar.py286
1 files changed, 286 insertions, 0 deletions
diff --git a/tests/analysis/scan/grammar.py b/tests/analysis/scan/grammar.py
new file mode 100644
index 0000000..5a2e1d5
--- /dev/null
+++ b/tests/analysis/scan/grammar.py
@@ -0,0 +1,286 @@
+
+from chrysacase import ChrysalideTestCase
+from pychrysalide.analysis.contents import MemoryContent
+from pychrysalide.analysis.scan import ContentScanner
+from pychrysalide.analysis.scan import ScanOptions
+from pychrysalide.analysis.scan.patterns.backends import AcismBackend
+
+
+class TestRostGrammar(ChrysalideTestCase):
+ """TestCase for analysis.scan.ScanExpression."""
+
+ @classmethod
+ def setUpClass(cls):
+
+ super(TestRostGrammar, cls).setUpClass()
+
+ cls._options = ScanOptions()
+ cls._options.backend_for_data = AcismBackend
+
+
+ def testComments(self):
+ """Ensure comments do not bother rule definitions."""
+
+ cnt = MemoryContent(b'no_real_content')
+
+ rule = '''
+/*
+ Multi-line header...
+*/
+
+rule test { // comment
+
+ /*
+ * Some context
+ */
+
+ condition: /* List of condition(s) */
+ true // Dummy condition
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ def testUintCast(self):
+ """Process nested integer values from binary content."""
+
+ cnt = MemoryContent(b'\x4d\x5a\x00\x00' + b'\x50\x45\x00\x00' + 52 * b'\x00' + b'\x04\x00\x00\x00')
+
+ rule = '''
+rule IsPE {
+
+ condition:
+
+ // MZ signature at offset 0 and ...
+
+ uint16(0) == 0x5a4d and
+
+ // ... PE signature at offset stored in the MZ header at offset 0x3c
+
+ uint32(uint32(0x3c)) == 0x00004550
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('IsPE'))
+
+
+ def testBasicBooleanConditions(self):
+ """Evaluate basic boolean conditions."""
+
+ cnt = MemoryContent(b'0123')
+
+ rule = '''
+rule test {
+
+ condition:
+ true and false
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None))
+ self.assertFalse(ctx.has_match_for_rule('test'))
+
+ rule = '''
+rule test {
+
+ condition:
+ true or false
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ def testArithmeticOpeations(self):
+ """Compute some arithmetic operations."""
+
+ cnt = MemoryContent(b'0123')
+
+ rule = '''
+rule test {
+
+ condition:
+ 1 + 4 * 3 + 2 == 15
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ rule = '''
+rule test {
+
+ condition:
+ (1 + 4) * 3 + 2 == 17
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ rule = '''
+rule test {
+
+ condition:
+ 1 + 4 * (3 + 2) == 21
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ rule = '''
+rule test {
+
+ condition:
+ (1 + 4) * (3 + 2) == 25
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ def testSizeUnits(self):
+ """Evaluate size units."""
+
+ cnt = MemoryContent(b'0123')
+
+
+ rule = '''
+rule test {
+
+ condition:
+ 1KB == 1024
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ rule = '''
+rule test {
+
+ condition:
+ 2MB == 2 * 1024 * 1024
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ rule = '''
+rule test {
+
+ condition:
+ 4Kb == (4 * 1024)
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ rule = '''
+rule test {
+
+ condition:
+ 1KB <= 1024 and 1024 < 1MB
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ def testNamespace(self):
+ """Resolve main functions with the root scan namesapce."""
+
+ cnt = MemoryContent(b'\x01\x02\x03\x04')
+
+ rule = '''
+rule test {
+
+ condition:
+ datasize == 4
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))
+
+
+ rule = '''
+rule test {
+
+ condition:
+ uint16(0) == 0x201 and uint16(datasize - 2) == 0x0403
+
+}
+'''
+
+ scanner = ContentScanner(rule)
+
+ ctx = scanner.analyze(self._options, cnt)
+
+ self.assertTrue(not(ctx is None) and ctx.has_match_for_rule('test'))