diff options
Diffstat (limited to 'tests/analysis/scan/grammar.py')
-rw-r--r-- | tests/analysis/scan/grammar.py | 286 |
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')) |