-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FEATURE: Implement various analyzers for logical operations
Those new analyzers can be used to perform logical operations on analyzers. They are rather some piece of meta analyzer
- Loading branch information
1 parent
627989a
commit 94fc691
Showing
8 changed files
with
232 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from .andanalyzer import AndAnalyzer | ||
from .logicalbaseanalyzer import LogicalBaseAnalyzer | ||
from .oranalyzer import OrAnalyzer | ||
|
||
__all__ = ('LogicalBaseAnalyzer', 'AndAnalyzer', 'OrAnalyzer') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# -*- coding: utf-8 -*- | ||
from .logicalbaseanalyzer import LogicalBaseAnalyzer | ||
|
||
|
||
class AndAnalyzer(LogicalBaseAnalyzer): | ||
"""Meta analyzer which matches a paste if all of the passed analyzers match that paste""" | ||
name = "AndAnalyzer" | ||
|
||
def match(self, paste): | ||
"""Returns True if all of the passed analyzers matched""" | ||
if len(self.analyzers) == 0: | ||
return False | ||
|
||
for analyzer in self.analyzers: | ||
if not analyzer.match(paste): | ||
return False | ||
|
||
return True |
45 changes: 45 additions & 0 deletions
45
pastepwn/analyzers/logicalanalyzers/logicalbaseanalyzer.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# -*- coding: utf-8 -*- | ||
from pastepwn.analyzers.basicanalyzer import BasicAnalyzer | ||
from pastepwn.util import listify | ||
|
||
|
||
class LogicalBaseAnalyzer(BasicAnalyzer): | ||
"""Meta analyzer used to combine analyzers via a logical operator""" | ||
name = "LogicalBaseAnalyzer" | ||
|
||
def __init__(self, actions, analyzers, merge_actions=False): | ||
""" | ||
Meta analyzer used to combine analyzers via a logical operator | ||
:param actions: A single action or a list of actions to be executed on every paste | ||
:param analyzers: A single analyzer or a list of analyzers used to match pastes | ||
""" | ||
super().__init__(actions) | ||
self.analyzers = listify(analyzers) | ||
|
||
if len(self.analyzers) == 0: | ||
self.logger.warning("You have not specified any analyzers inside '{}'".format(self.name)) | ||
|
||
if merge_actions: | ||
self._merge_actions() | ||
|
||
def _merge_actions(self): | ||
""" | ||
Merges the actions of the passed analyzers into this meta analyzer | ||
If merged, the actions will be executed if this meta analyzer matches | ||
:return: None | ||
""" | ||
for analyzer in self.analyzers: | ||
for action in analyzer.actions: | ||
self.actions.append(action) | ||
|
||
def add_analyzer(self, analyzer): | ||
""" | ||
Add a new analyzer to the list of analyzers | ||
:param analyzer: A single analyzer used to match pastes | ||
:return: | ||
""" | ||
self.analyzers.append(analyzer) | ||
|
||
def match(self, paste): | ||
"""Must be overridden by the subclasses""" | ||
raise NotImplementedError("match() function must be overridden in the subclasses!") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# -*- coding: utf-8 -*- | ||
from .logicalbaseanalyzer import LogicalBaseAnalyzer | ||
|
||
|
||
class OrAnalyzer(LogicalBaseAnalyzer): | ||
"""Meta analyzer which matches a paste if any of the passed analyzers match that paste""" | ||
name = "OrAnalyzer" | ||
|
||
def match(self, paste): | ||
"""Returns True if all of the passed analyzers matched""" | ||
for analyzer in self.analyzers: | ||
if analyzer.match(paste): | ||
return True | ||
|
||
return False |
Empty file.
54 changes: 54 additions & 0 deletions
54
pastepwn/analyzers/logicalanalyzers/tests/andanalyzer_test.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# -*- coding: utf-8 -*- | ||
import unittest | ||
from unittest import mock | ||
|
||
from pastepwn.analyzers import AndAnalyzer | ||
|
||
|
||
class TestAndAnalyzer(unittest.TestCase): | ||
def setUp(self): | ||
self.obj = mock.Mock() | ||
self.gt = mock.Mock() | ||
self.gt.match = mock.Mock(return_value=True) | ||
|
||
self.gf = mock.Mock() | ||
self.gf.match = mock.Mock(return_value=False) | ||
|
||
def test_match_positive(self): | ||
self.obj.body = "Test" | ||
analyzer = AndAnalyzer(None, [self.gt]) | ||
self.assertTrue(analyzer.match(self.obj)) | ||
|
||
analyzer = AndAnalyzer(None, [self.gt, self.gt, self.gt]) | ||
self.assertTrue(analyzer.match(self.obj)) | ||
|
||
# Check if the analyzer returns false if there is at least one false result | ||
analyzer = AndAnalyzer([], [self.gt, self.gf]) | ||
self.assertFalse(analyzer.match(self.obj)) | ||
|
||
analyzer = AndAnalyzer([], [self.gf, self.gf]) | ||
self.assertFalse(analyzer.match(self.obj)) | ||
|
||
analyzer = AndAnalyzer([], [self.gf, self.gf, self.gf, self.gt]) | ||
self.assertFalse(analyzer.match(self.obj)) | ||
|
||
def test_negative(self): | ||
self.obj.body = "" | ||
|
||
analyzer = AndAnalyzer([], None) | ||
self.assertFalse(analyzer.match(self.obj)) | ||
|
||
analyzer = AndAnalyzer([], []) | ||
self.assertFalse(analyzer.match(self.obj)) | ||
|
||
def test_actions_present(self): | ||
analyzer = AndAnalyzer(self.obj, None) | ||
self.assertEqual([self.obj], analyzer.actions) | ||
|
||
def test_analyzers_present(self): | ||
analyzer = AndAnalyzer(None, self.obj) | ||
self.assertEqual([self.obj], analyzer.analyzers) | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
40 changes: 40 additions & 0 deletions
40
pastepwn/analyzers/logicalanalyzers/tests/logicalbaseanalyzer_test.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# -*- coding: utf-8 -*- | ||
import unittest | ||
from unittest import mock | ||
|
||
from pastepwn.analyzers.logicalanalyzers import LogicalBaseAnalyzer | ||
|
||
|
||
class TestLogicalBaseAnalyzer(unittest.TestCase): | ||
def setUp(self): | ||
self.obj = mock.Mock() | ||
|
||
def test_exception(self): | ||
analyzer = LogicalBaseAnalyzer([], []) | ||
self.assertRaises(NotImplementedError, analyzer.match, mock.Mock()) | ||
|
||
def test_actions_present(self): | ||
analyzer = LogicalBaseAnalyzer(self.obj, None) | ||
self.assertEqual([self.obj], analyzer.actions) | ||
|
||
def test_analyzers_present(self): | ||
analyzer = LogicalBaseAnalyzer(None, self.obj) | ||
self.assertEqual([self.obj], analyzer.analyzers) | ||
|
||
def test_merge_actions(self): | ||
action1 = mock.Mock() | ||
action2 = mock.Mock() | ||
action3 = mock.Mock() | ||
|
||
analyzer1 = mock.Mock() | ||
analyzer1.actions = [action1, action2] | ||
analyzer2 = mock.Mock() | ||
analyzer2.actions = [action3] | ||
|
||
analyzer = LogicalBaseAnalyzer(analyzers=[analyzer1, analyzer2], actions=[], merge_actions=True) | ||
self.assertEqual(3, len(analyzer.actions), "Wrong amount of actions in LogicalBaseAnalyzer!") | ||
self.assertEqual([action1, action2, action3], analyzer.actions, "Actions do not match!") | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
53 changes: 53 additions & 0 deletions
53
pastepwn/analyzers/logicalanalyzers/tests/oranalyzer_test.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# -*- coding: utf-8 -*- | ||
import unittest | ||
from unittest import mock | ||
|
||
from pastepwn.analyzers.logicalanalyzers import OrAnalyzer | ||
|
||
|
||
class TestOrAnalyzer(unittest.TestCase): | ||
def setUp(self): | ||
self.obj = mock.Mock() | ||
self.gt = mock.Mock() | ||
self.gt.match = mock.Mock(return_value=True) | ||
|
||
self.gf = mock.Mock() | ||
self.gf.match = mock.Mock(return_value=False) | ||
|
||
def test_match_positive(self): | ||
self.obj.body = "Test" | ||
analyzer = OrAnalyzer(None, [self.gt]) | ||
self.assertTrue(analyzer.match(self.obj)) | ||
|
||
analyzer = OrAnalyzer(None, [self.gt, self.gt, self.gt]) | ||
self.assertTrue(analyzer.match(self.obj)) | ||
|
||
analyzer = OrAnalyzer([], [self.gf, self.gf]) | ||
self.assertFalse(analyzer.match(self.obj)) | ||
|
||
analyzer = OrAnalyzer([], [self.gf, self.gf, self.gf]) | ||
self.assertFalse(analyzer.match(self.obj)) | ||
|
||
analyzer = OrAnalyzer([], [self.gf, self.gf, self.gf, self.gt]) | ||
self.assertTrue(analyzer.match(self.obj)) | ||
|
||
def test_negative(self): | ||
self.obj.body = "" | ||
|
||
analyzer = OrAnalyzer([], None) | ||
self.assertFalse(analyzer.match(self.obj)) | ||
|
||
analyzer = OrAnalyzer([], []) | ||
self.assertFalse(analyzer.match(self.obj)) | ||
|
||
def test_actions_present(self): | ||
analyzer = OrAnalyzer(self.obj, None) | ||
self.assertEqual([self.obj], analyzer.actions) | ||
|
||
def test_analyzers_present(self): | ||
analyzer = OrAnalyzer(None, self.obj) | ||
self.assertEqual([self.obj], analyzer.analyzers) | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |