mal-toolbox 0.0.27__py3-none-any.whl → 0.1.12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. {mal_toolbox-0.0.27.dist-info → mal_toolbox-0.1.12.dist-info}/METADATA +60 -28
  2. mal_toolbox-0.1.12.dist-info/RECORD +32 -0
  3. {mal_toolbox-0.0.27.dist-info → mal_toolbox-0.1.12.dist-info}/WHEEL +1 -1
  4. maltoolbox/__init__.py +31 -31
  5. maltoolbox/__main__.py +80 -4
  6. maltoolbox/attackgraph/__init__.py +8 -0
  7. maltoolbox/attackgraph/analyzers/__init__.py +0 -0
  8. maltoolbox/attackgraph/analyzers/apriori.py +173 -27
  9. maltoolbox/attackgraph/attacker.py +99 -21
  10. maltoolbox/attackgraph/attackgraph.py +507 -217
  11. maltoolbox/attackgraph/node.py +143 -21
  12. maltoolbox/attackgraph/query.py +128 -26
  13. maltoolbox/default.conf +8 -7
  14. maltoolbox/exceptions.py +45 -0
  15. maltoolbox/file_utils.py +66 -0
  16. maltoolbox/ingestors/__init__.py +0 -0
  17. maltoolbox/ingestors/neo4j.py +95 -84
  18. maltoolbox/language/__init__.py +4 -0
  19. maltoolbox/language/classes_factory.py +145 -64
  20. maltoolbox/language/{lexer_parser/__main__.py → compiler/__init__.py} +5 -12
  21. maltoolbox/language/{lexer_parser → compiler}/mal_lexer.py +1 -1
  22. maltoolbox/language/{lexer_parser → compiler}/mal_parser.py +1 -1
  23. maltoolbox/language/{lexer_parser → compiler}/mal_visitor.py +4 -5
  24. maltoolbox/language/languagegraph.py +569 -168
  25. maltoolbox/model.py +858 -0
  26. maltoolbox/translators/__init__.py +0 -0
  27. maltoolbox/translators/securicad.py +76 -52
  28. maltoolbox/translators/updater.py +132 -0
  29. maltoolbox/wrappers.py +62 -0
  30. mal_toolbox-0.0.27.dist-info/RECORD +0 -26
  31. maltoolbox/cl_parser.py +0 -89
  32. maltoolbox/language/specification.py +0 -265
  33. maltoolbox/main.py +0 -84
  34. maltoolbox/model/model.py +0 -279
  35. {mal_toolbox-0.0.27.dist-info → mal_toolbox-0.1.12.dist-info}/AUTHORS +0 -0
  36. {mal_toolbox-0.0.27.dist-info → mal_toolbox-0.1.12.dist-info}/LICENSE +0 -0
  37. {mal_toolbox-0.0.27.dist-info → mal_toolbox-0.1.12.dist-info}/top_level.txt +0 -0
@@ -2,33 +2,69 @@
2
2
  MAL-Toolbox Attack Graph Attacker Class
3
3
  """
4
4
 
5
+ from __future__ import annotations
6
+ from dataclasses import dataclass, field
7
+ import copy
5
8
  import logging
6
9
 
7
- from dataclasses import dataclass
8
- from typing import List, ForwardRef
10
+ from typing import Optional
11
+ from typing import TYPE_CHECKING
12
+ if TYPE_CHECKING:
13
+ from .attackgraph import AttackGraphNode
9
14
 
10
15
  logger = logging.getLogger(__name__)
11
16
 
12
17
  @dataclass
13
18
  class Attacker:
14
- id: str
15
- entry_points: List[ForwardRef("node.AttackGraphNode")]
16
- reached_attack_steps: List[ForwardRef("node.AttackGraphNode")]
17
- node: ForwardRef("node.AttackGraphNode")
18
-
19
- def to_dict(self):
20
- attacker_dict = {
21
- "id": self.id,
22
- "entry_points": [entry_point.id for entry_point in
23
- self.entry_points],
24
- "reached_attack_steps": [attack_step.id for attack_step in
25
- self.reached_attack_steps],
26
- "node": self.node.id
19
+ name: str
20
+ entry_points: list[AttackGraphNode] = field(default_factory=list)
21
+ reached_attack_steps: list[AttackGraphNode] = \
22
+ field(default_factory=list)
23
+ id: Optional[int] = None
24
+
25
+ def to_dict(self) -> dict:
26
+ attacker_dict: dict = {
27
+ 'id': self.id,
28
+ 'name': self.name,
29
+ 'entry_points': {},
30
+ 'reached_attack_steps': {}
27
31
  }
28
32
 
33
+ for entry_point in self.entry_points:
34
+ attacker_dict['entry_points'][entry_point.id] = \
35
+ entry_point.full_name
36
+ for attack_step in self.reached_attack_steps:
37
+ attacker_dict['reached_attack_steps'][attack_step.id] = \
38
+ attack_step.full_name
39
+
29
40
  return attacker_dict
30
41
 
31
- def compromise(self, node):
42
+ def __repr__(self) -> str:
43
+ return str(self.to_dict())
44
+
45
+ def __deepcopy__(self, memo) -> Attacker:
46
+ """Deep copy an Attacker"""
47
+
48
+ # Check if the object is already in the memo dictionary
49
+ if id(self) in memo:
50
+ return memo[id(self)]
51
+
52
+ copied_attacker = Attacker(
53
+ id = self.id,
54
+ name = self.name,
55
+ )
56
+
57
+ # Remember that self was already copied
58
+ memo[id(self)] = copied_attacker
59
+
60
+ copied_attacker.entry_points = copy.deepcopy(
61
+ self.entry_points, memo = memo)
62
+ copied_attacker.reached_attack_steps = copy.deepcopy(
63
+ self.reached_attack_steps, memo = memo)
64
+
65
+ return copied_attacker
66
+
67
+ def compromise(self, node: AttackGraphNode) -> None:
32
68
  """
33
69
  Have the attacke compromise the node given as a parameter.
34
70
 
@@ -36,12 +72,54 @@ class Attacker:
36
72
  node - the node that the attacker will compromise
37
73
  """
38
74
 
39
- logger.debug(f'Attacker \"{self.id}\" is compromising node '
40
- f'\"{node.id}\".')
41
- if self in node.compromised_by:
42
- logger.info(f'Attacker \"{self.id}\" had already compromised '
43
- f'node \"{node.id}\". Do nothing.')
75
+ logger.debug(
76
+ 'Attacker "%s"(%d) is compromising node "%s"(%d).',
77
+ self.name,
78
+ self.id,
79
+ node.full_name,
80
+ node.id
81
+ )
82
+ if node.is_compromised_by(self):
83
+ logger.info(
84
+ 'Attacker "%s"(%d) already compromised node "%s"(%d). '
85
+ 'Do nothing.',
86
+ self.name,
87
+ self.id,
88
+ node.full_name,
89
+ node.id
90
+ )
44
91
  return
45
92
 
46
93
  node.compromised_by.append(self)
47
94
  self.reached_attack_steps.append(node)
95
+
96
+ def undo_compromise(self, node: AttackGraphNode) -> None:
97
+ """
98
+ Remove the attacker from the list of attackers that have compromised
99
+ the node given as a parameter.
100
+
101
+ Arguments:
102
+ node - the node that we wish to remove this attacker from.
103
+ """
104
+
105
+ logger.debug(
106
+ 'Removing attacker "%s"(%d) from compromised_by '
107
+ 'list of node "%s"(%d).',
108
+ self.name,
109
+ self.id,
110
+ node.full_name,
111
+ node.id
112
+ )
113
+ if not node.is_compromised_by(self):
114
+ logger.info(
115
+ 'Attacker "%s"(%d) had not compromised node "%s"(%d).'
116
+ ' Do nothing.',
117
+ self.name,
118
+ self.id,
119
+ node.full_name,
120
+ node.id
121
+ )
122
+ return
123
+
124
+ node.compromised_by.remove(self)
125
+ self.reached_attack_steps.remove(node)