atomicshop 2.12.17__py3-none-any.whl → 2.12.19__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.
Potentially problematic release.
This version of atomicshop might be problematic. Click here for more details.
- atomicshop/__init__.py +1 -1
- atomicshop/diff_check.py +3 -6
- atomicshop/file_io/file_io.py +4 -2
- atomicshop/monitor/change_monitor.py +17 -24
- atomicshop/monitor/checks/dns.py +125 -114
- atomicshop/monitor/checks/file.py +77 -0
- atomicshop/monitor/checks/hash.py +6 -7
- atomicshop/monitor/checks/network.py +81 -81
- atomicshop/monitor/checks/process_running.py +33 -34
- atomicshop/monitor/checks/url.py +94 -0
- {atomicshop-2.12.17.dist-info → atomicshop-2.12.19.dist-info}/METADATA +1 -1
- {atomicshop-2.12.17.dist-info → atomicshop-2.12.19.dist-info}/RECORD +15 -16
- atomicshop/monitor/checks/hash_checks/__init__.py +0 -0
- atomicshop/monitor/checks/hash_checks/file.py +0 -54
- atomicshop/monitor/checks/hash_checks/url.py +0 -64
- {atomicshop-2.12.17.dist-info → atomicshop-2.12.19.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.12.17.dist-info → atomicshop-2.12.19.dist-info}/WHEEL +0 -0
- {atomicshop-2.12.17.dist-info → atomicshop-2.12.19.dist-info}/top_level.txt +0 -0
atomicshop/__init__.py
CHANGED
atomicshop/diff_check.py
CHANGED
|
@@ -207,7 +207,7 @@ class DiffChecker:
|
|
|
207
207
|
self.new_objects_seconds_then_difference: Union[float, None] = None
|
|
208
208
|
self.timer = None
|
|
209
209
|
|
|
210
|
-
def
|
|
210
|
+
def initiate_before_action(self):
|
|
211
211
|
"""
|
|
212
212
|
This function will be called before the actual checking of the object.
|
|
213
213
|
If you change any attribute of the class, you will need to call this function again.
|
|
@@ -254,7 +254,8 @@ class DiffChecker:
|
|
|
254
254
|
self.previous_day = None
|
|
255
255
|
|
|
256
256
|
if self.new_objects_hours_then_difference and self.operation_type != 'new_objects':
|
|
257
|
-
raise ValueError(
|
|
257
|
+
raise ValueError(
|
|
258
|
+
"The 'new_objects_hours_then_difference' variable must be set for 'new_objects' operation type.")
|
|
258
259
|
|
|
259
260
|
if self.new_objects_hours_then_difference:
|
|
260
261
|
self.new_objects_seconds_then_difference = self.new_objects_hours_then_difference * 60 * 60
|
|
@@ -266,8 +267,6 @@ class DiffChecker:
|
|
|
266
267
|
The function will check file content for change by hashing it and comparing the hash.
|
|
267
268
|
"""
|
|
268
269
|
|
|
269
|
-
self._static_pre_process()
|
|
270
|
-
|
|
271
270
|
if not isinstance(self.check_object, str):
|
|
272
271
|
raise TypeError(f"[check_object] must be string, not {type(self.check_object)}.")
|
|
273
272
|
|
|
@@ -287,8 +286,6 @@ class DiffChecker:
|
|
|
287
286
|
:param print_kwargs: dict, of kwargs to pass to 'print_api' function.
|
|
288
287
|
"""
|
|
289
288
|
|
|
290
|
-
self._static_pre_process()
|
|
291
|
-
|
|
292
289
|
if not isinstance(self.check_object, list):
|
|
293
290
|
raise TypeError(f'[check_object] must be list, not {type(self.check_object)}.')
|
|
294
291
|
|
atomicshop/file_io/file_io.py
CHANGED
|
@@ -102,8 +102,10 @@ def write_file(
|
|
|
102
102
|
content = '\n'.join(content)
|
|
103
103
|
else:
|
|
104
104
|
file_object.writelines(content)
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
elif isinstance(content, str):
|
|
106
|
+
file_object.write(content)
|
|
107
|
+
# THis will happen if the content is bytes and the file mode is 'wb'.
|
|
108
|
+
elif isinstance(content, bytes) and 'b' in file_mode:
|
|
107
109
|
file_object.write(content)
|
|
108
110
|
else:
|
|
109
111
|
raise TypeError(f"Content type is not supported: {type(content)}")
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
from typing import Literal, Union
|
|
2
|
-
from pathlib import Path
|
|
3
2
|
|
|
4
|
-
from .checks import dns, network,
|
|
5
|
-
from .. import filesystem, scheduling
|
|
3
|
+
from .checks import dns, network, file, url, process_running
|
|
6
4
|
|
|
7
5
|
|
|
8
6
|
DNS__DEFAULT_SETTINGS = {
|
|
@@ -122,36 +120,31 @@ class ChangeMonitor:
|
|
|
122
120
|
|
|
123
121
|
# === Additional variables ========================================
|
|
124
122
|
|
|
125
|
-
# self.original_object_directory = None
|
|
126
|
-
# self.original_object_file_path = None
|
|
127
|
-
|
|
128
|
-
# # If 'store_original_object' is True, create directory for original object.
|
|
129
|
-
# if self.store_original_object:
|
|
130
|
-
# # Make path for original object.
|
|
131
|
-
# self.original_object_directory = filesystem.add_object_to_path(
|
|
132
|
-
# self.input_directory, 'Original')
|
|
133
|
-
# # Create directory if it doesn't exist.
|
|
134
|
-
# filesystem.create_directory(self.original_object_directory)
|
|
135
|
-
#
|
|
136
|
-
# Initialize objects for DNS and Network monitoring.
|
|
137
|
-
|
|
138
123
|
self.checks_instance = None
|
|
139
124
|
self._setup_object()
|
|
140
125
|
|
|
141
126
|
def _setup_object(self):
|
|
142
|
-
if self.object_type == 'file'
|
|
143
|
-
self.
|
|
144
|
-
|
|
145
|
-
self.checks_instance = dns
|
|
127
|
+
if self.object_type == 'file':
|
|
128
|
+
if not self.object_type_settings:
|
|
129
|
+
self.object_type_settings = FILE__URL__DEFAULT_SETTINGS
|
|
146
130
|
|
|
131
|
+
self.checks_instance = file.FileCheck(self)
|
|
132
|
+
elif self.object_type.startswith('url_'):
|
|
133
|
+
if not self.object_type_settings:
|
|
134
|
+
self.object_type_settings = FILE__URL__DEFAULT_SETTINGS
|
|
135
|
+
|
|
136
|
+
self.checks_instance = url.UrlCheck(self)
|
|
137
|
+
elif self.object_type == 'dns':
|
|
147
138
|
if not self.object_type_settings:
|
|
148
139
|
self.object_type_settings = DNS__DEFAULT_SETTINGS
|
|
140
|
+
|
|
141
|
+
self.checks_instance = dns.DnsCheck(self)
|
|
149
142
|
elif self.object_type == 'network':
|
|
150
|
-
self.checks_instance = network
|
|
143
|
+
self.checks_instance = network.NetworkCheck(self)
|
|
151
144
|
elif self.object_type == 'process_running':
|
|
152
|
-
self.checks_instance = process_running
|
|
153
|
-
|
|
154
|
-
|
|
145
|
+
self.checks_instance = process_running.ProcessRunningCheck(self)
|
|
146
|
+
else:
|
|
147
|
+
raise ValueError(f"ERROR: Unknown object type: {self.object_type}")
|
|
155
148
|
|
|
156
149
|
def check_cycle(self, print_kwargs: dict = None):
|
|
157
150
|
"""
|
atomicshop/monitor/checks/dns.py
CHANGED
|
@@ -1,126 +1,137 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
+
from typing import Union
|
|
2
3
|
|
|
3
4
|
from ...etw.dns_trace import DnsTrace
|
|
4
5
|
from ...print_api import print_api
|
|
5
|
-
from ...
|
|
6
|
+
from ...import diff_check
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
INPUT_FILE_DEFAULT_NAME: str = 'known_domains.json'
|
|
9
10
|
INPUT_STATISTICS_FILE_DEFAULT_NAME: str = 'dns_statistics.json'
|
|
10
|
-
FETCH_ENGINE: DnsTrace = DnsTrace(enable_process_poller=True, attrs=['name', 'cmdline', 'domain', 'query_type'])
|
|
11
|
-
SETTINGS = {}
|
|
12
|
-
DIFF_CHECKER_AGGREGATION = DiffChecker(
|
|
13
|
-
check_object=list(), # DNS events will be appended to this list.
|
|
14
|
-
return_first_cycle=True,
|
|
15
|
-
operation_type='new_objects'
|
|
16
|
-
)
|
|
17
|
-
DIFF_CHECKER_STATISTICS = DiffChecker(
|
|
18
|
-
check_object=list(), # DNS events will be appended to this list.
|
|
19
|
-
return_first_cycle=True,
|
|
20
|
-
operation_type='hit_statistics',
|
|
21
|
-
hit_statistics_enable_queue=True
|
|
22
|
-
)
|
|
23
11
|
|
|
24
12
|
|
|
25
|
-
|
|
26
|
-
global SETTINGS
|
|
27
|
-
SETTINGS = change_monitor_instance.object_type_settings
|
|
28
|
-
|
|
29
|
-
if SETTINGS['alert_always'] and SETTINGS['alert_about_missing_entries_after_learning']:
|
|
30
|
-
raise ValueError(
|
|
31
|
-
"ERROR: [alert_always] and [alert_about_missing_entries_after_learning] cannot be True at the same time.")
|
|
32
|
-
|
|
33
|
-
if not change_monitor_instance.input_file_name:
|
|
34
|
-
change_monitor_instance.input_file_name = INPUT_FILE_DEFAULT_NAME
|
|
35
|
-
input_file_path = (
|
|
36
|
-
str(Path(change_monitor_instance.input_directory, change_monitor_instance.input_file_name)))
|
|
37
|
-
|
|
38
|
-
if not change_monitor_instance.input_statistics_file_name:
|
|
39
|
-
change_monitor_instance.input_statistics_file_name = INPUT_STATISTICS_FILE_DEFAULT_NAME
|
|
40
|
-
input_statistic_file_path = (
|
|
41
|
-
str(Path(change_monitor_instance.input_directory, change_monitor_instance.input_statistics_file_name)))
|
|
42
|
-
|
|
43
|
-
if SETTINGS['learning_mode_create_unique_entries_list']:
|
|
44
|
-
DIFF_CHECKER_AGGREGATION.input_file_write_only = change_monitor_instance.input_file_write_only
|
|
45
|
-
DIFF_CHECKER_AGGREGATION.check_object_display_name = \
|
|
46
|
-
f'{change_monitor_instance.input_file_name}|{change_monitor_instance.object_type}'
|
|
47
|
-
DIFF_CHECKER_AGGREGATION.input_file_path = input_file_path
|
|
48
|
-
DIFF_CHECKER_AGGREGATION.new_objects_hours_then_difference = SETTINGS['learning_hours']
|
|
49
|
-
|
|
50
|
-
if SETTINGS['create_alert_statistics']:
|
|
51
|
-
DIFF_CHECKER_STATISTICS.input_file_write_only = change_monitor_instance.input_file_write_only
|
|
52
|
-
DIFF_CHECKER_STATISTICS.check_object_display_name = \
|
|
53
|
-
f'{change_monitor_instance.input_statistics_file_name}|{change_monitor_instance.object_type}'
|
|
54
|
-
DIFF_CHECKER_STATISTICS.input_file_path = input_statistic_file_path
|
|
55
|
-
DIFF_CHECKER_STATISTICS.hit_statistics_input_file_rotation_cycle_hours = SETTINGS['statistics_rotation_hours']
|
|
56
|
-
|
|
57
|
-
# Start DNS monitoring.
|
|
58
|
-
FETCH_ENGINE.start()
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def execute_cycle(print_kwargs: dict = None) -> list:
|
|
13
|
+
class DnsCheck:
|
|
62
14
|
"""
|
|
63
|
-
|
|
64
|
-
The function is blocking so while using it, the script will wait for the next DNS event.
|
|
65
|
-
No need to use 'time.sleep()'.
|
|
66
|
-
|
|
67
|
-
:param print_kwargs: print_api kwargs.
|
|
68
|
-
:return: List of dictionaries with the results of the cycle.
|
|
15
|
+
Class for DNS monitoring.
|
|
69
16
|
"""
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if '
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
17
|
+
|
|
18
|
+
def __init__(self, change_monitor_instance):
|
|
19
|
+
self.change_monitor_instance = change_monitor_instance
|
|
20
|
+
self.diff_checker_aggregation: Union[diff_check.DiffChecker, None] = None
|
|
21
|
+
self.diff_checker_statistics: Union[diff_check.DiffChecker, None] = None
|
|
22
|
+
self.settings: dict = change_monitor_instance.object_type_settings
|
|
23
|
+
self.fetch_engine: DnsTrace = (
|
|
24
|
+
DnsTrace(enable_process_poller=True, attrs=['name', 'cmdline', 'domain', 'query_type']))
|
|
25
|
+
|
|
26
|
+
if self.settings['alert_always'] and self.settings['alert_about_missing_entries_after_learning']:
|
|
27
|
+
raise ValueError(
|
|
28
|
+
"ERROR: [alert_always] and [alert_about_missing_entries_after_learning] "
|
|
29
|
+
"cannot be True at the same time.")
|
|
30
|
+
|
|
31
|
+
if not change_monitor_instance.input_file_name:
|
|
32
|
+
change_monitor_instance.input_file_name = INPUT_FILE_DEFAULT_NAME
|
|
33
|
+
input_file_path = (
|
|
34
|
+
str(Path(change_monitor_instance.input_directory, change_monitor_instance.input_file_name)))
|
|
35
|
+
|
|
36
|
+
if not change_monitor_instance.input_statistics_file_name:
|
|
37
|
+
change_monitor_instance.input_statistics_file_name = INPUT_STATISTICS_FILE_DEFAULT_NAME
|
|
38
|
+
input_statistic_file_path = (
|
|
39
|
+
str(Path(change_monitor_instance.input_directory, change_monitor_instance.input_statistics_file_name)))
|
|
40
|
+
|
|
41
|
+
if self.settings['learning_mode_create_unique_entries_list']:
|
|
42
|
+
aggregation_display_name = \
|
|
43
|
+
f'{change_monitor_instance.input_file_name}|{change_monitor_instance.object_type}'
|
|
44
|
+
self.diff_checker_aggregation = diff_check.DiffChecker(
|
|
45
|
+
check_object=list(), # DNS events will be appended to this list.
|
|
46
|
+
return_first_cycle=True,
|
|
47
|
+
operation_type='new_objects',
|
|
48
|
+
input_file_write_only=change_monitor_instance.input_file_write_only,
|
|
49
|
+
check_object_display_name=aggregation_display_name,
|
|
50
|
+
input_file_path=input_file_path,
|
|
51
|
+
new_objects_hours_then_difference=self.settings['learning_hours']
|
|
52
|
+
)
|
|
53
|
+
self.diff_checker_aggregation.initiate_before_action()
|
|
54
|
+
|
|
55
|
+
if self.settings['create_alert_statistics']:
|
|
56
|
+
statistics_display_name = \
|
|
57
|
+
f'{change_monitor_instance.input_statistics_file_name}|{change_monitor_instance.object_type}'
|
|
58
|
+
|
|
59
|
+
self.diff_checker_statistics = diff_check.DiffChecker(
|
|
60
|
+
check_object=list(), # DNS events will be appended to this list.
|
|
61
|
+
return_first_cycle=True,
|
|
62
|
+
operation_type='hit_statistics',
|
|
63
|
+
hit_statistics_enable_queue=True,
|
|
64
|
+
input_file_write_only=change_monitor_instance.input_file_write_only,
|
|
65
|
+
check_object_display_name=statistics_display_name,
|
|
66
|
+
input_file_path=input_statistic_file_path,
|
|
67
|
+
hit_statistics_input_file_rotation_cycle_hours=self.settings['statistics_rotation_hours']
|
|
68
|
+
)
|
|
69
|
+
self.diff_checker_statistics.initiate_before_action()
|
|
70
|
+
|
|
71
|
+
# Start DNS monitoring.
|
|
72
|
+
self.fetch_engine.start()
|
|
73
|
+
|
|
74
|
+
def execute_cycle(self, print_kwargs: dict = None) -> list:
|
|
75
|
+
"""
|
|
76
|
+
This function executes the cycle of the change monitor: dns.
|
|
77
|
+
The function is blocking so while using it, the script will wait for the next DNS event.
|
|
78
|
+
No need to use 'time.sleep()'.
|
|
79
|
+
|
|
80
|
+
:param print_kwargs: print_api kwargs.
|
|
81
|
+
:return: List of dictionaries with the results of the cycle.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
# 'emit()' method is blocking (it uses 'get' of queue instance)
|
|
85
|
+
# will return a dict with current DNS trace event.
|
|
86
|
+
event_dict = self.fetch_engine.emit()
|
|
87
|
+
|
|
88
|
+
return_list = list()
|
|
89
|
+
if self.settings['learning_mode_create_unique_entries_list']:
|
|
90
|
+
self._aggregation_process(event_dict, return_list, print_kwargs)
|
|
91
|
+
|
|
92
|
+
if self.settings['create_alert_statistics'] and self.settings['alert_always']:
|
|
93
|
+
self._statistics_process(event_dict, return_list, print_kwargs)
|
|
94
|
+
|
|
95
|
+
return return_list
|
|
96
|
+
|
|
97
|
+
def _aggregation_process(self, event_dict: dict, return_list: list, print_kwargs: dict = None):
|
|
98
|
+
self.diff_checker_aggregation.check_object = [event_dict]
|
|
99
|
+
|
|
100
|
+
# Check if 'known_domains' list was updated from previous cycle.
|
|
101
|
+
result, message = self.diff_checker_aggregation.check_list_of_dicts(
|
|
102
|
+
sort_by_keys=['cmdline', 'name'], print_kwargs=print_kwargs)
|
|
103
|
+
|
|
104
|
+
if result:
|
|
105
|
+
# Check if 'updated' key is in the result. This means that this is a regular cycle.
|
|
106
|
+
if 'updated' in result:
|
|
107
|
+
if not result['time_passed']:
|
|
108
|
+
# Get list of new connections only.
|
|
109
|
+
# new_connections_only: list = list_of_dicts.get_difference(result['old'], result['updated'])
|
|
110
|
+
|
|
111
|
+
for connection in result['updated']:
|
|
112
|
+
message = \
|
|
113
|
+
f"[Learning] New Domain Added: {connection['name']} | " \
|
|
114
|
+
f"{connection['domain']} | {connection['query_type']} | " \
|
|
115
|
+
f"{connection['cmdline']}"
|
|
116
|
+
print_api(message, color='yellow', **(print_kwargs or {}))
|
|
117
|
+
|
|
118
|
+
return_list.append(message)
|
|
119
|
+
|
|
120
|
+
# Check if learning time passed, so we can alert the new entries.
|
|
121
|
+
if 'time_passed' in result:
|
|
122
|
+
if result['time_passed']:
|
|
123
|
+
self._statistics_process(result['updated'], return_list, print_kwargs)
|
|
124
|
+
|
|
125
|
+
def _statistics_process(self, event_dict: dict, return_list: list, print_kwargs: dict = None):
|
|
126
|
+
self.diff_checker_statistics.check_object = [event_dict]
|
|
127
|
+
|
|
128
|
+
# Check if 'known_domains' list was updated from previous cycle.
|
|
129
|
+
result, message = self.diff_checker_statistics.check_list_of_dicts(
|
|
130
|
+
sort_by_keys=['cmdline', 'name'], print_kwargs=print_kwargs)
|
|
131
|
+
|
|
132
|
+
if result:
|
|
133
|
+
if 'count' in result:
|
|
134
|
+
message = f"[Alert] DNS Request: {result['entry']} | Times hit: {result['count']}"
|
|
135
|
+
print_api(message, color='yellow', **(print_kwargs or {}))
|
|
136
|
+
|
|
137
|
+
return_list.append(message)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from ... import filesystem, hashing
|
|
4
|
+
from ... import diff_check
|
|
5
|
+
from ...print_api import print_api
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class FileCheck:
|
|
9
|
+
"""
|
|
10
|
+
Class for file monitoring.
|
|
11
|
+
"""
|
|
12
|
+
def __init__(self, change_monitor_instance):
|
|
13
|
+
self.diff_checker = None
|
|
14
|
+
self.change_monitor_instance = None
|
|
15
|
+
self.store_original_file_path = None
|
|
16
|
+
|
|
17
|
+
if not change_monitor_instance.input_file_name:
|
|
18
|
+
change_monitor_instance.input_file_name = Path(change_monitor_instance.check_object).name
|
|
19
|
+
change_monitor_instance.input_file_name = change_monitor_instance.input_file_name.lower()
|
|
20
|
+
change_monitor_instance.input_file_name = (
|
|
21
|
+
change_monitor_instance.input_file_name.replace(' ', '_').replace('.', '_'))
|
|
22
|
+
change_monitor_instance.input_file_name = f'{change_monitor_instance.input_file_name}.txt'
|
|
23
|
+
|
|
24
|
+
input_file_path = (
|
|
25
|
+
str(Path(change_monitor_instance.input_directory, change_monitor_instance.input_file_name)))
|
|
26
|
+
|
|
27
|
+
# If 'store_original_object' is True, create filename for the store original object.
|
|
28
|
+
if change_monitor_instance.object_type_settings['store_original_object']:
|
|
29
|
+
store_original_file_name: str = f'ORIGINAL_{Path(change_monitor_instance.check_object).name}'
|
|
30
|
+
self.store_original_file_path = str(Path(change_monitor_instance.input_directory, store_original_file_name))
|
|
31
|
+
|
|
32
|
+
self.diff_checker = diff_check.DiffChecker(
|
|
33
|
+
return_first_cycle=False,
|
|
34
|
+
operation_type='single_object',
|
|
35
|
+
input_file_path=input_file_path,
|
|
36
|
+
check_object_display_name=f'{change_monitor_instance.input_file_name}|{change_monitor_instance.object_type}'
|
|
37
|
+
)
|
|
38
|
+
self.diff_checker.initiate_before_action()
|
|
39
|
+
self.change_monitor_instance = change_monitor_instance
|
|
40
|
+
|
|
41
|
+
def execute_cycle(self, print_kwargs: dict = None):
|
|
42
|
+
"""
|
|
43
|
+
This function executes the cycle of the change monitor: hash.
|
|
44
|
+
|
|
45
|
+
:param print_kwargs: print_api kwargs.
|
|
46
|
+
:return: List of dictionaries with the results of the cycle.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
return_list = list()
|
|
50
|
+
|
|
51
|
+
self._get_hash()
|
|
52
|
+
|
|
53
|
+
# Check if the object was updated.
|
|
54
|
+
result, message = self.diff_checker.check_string(
|
|
55
|
+
print_kwargs=print_kwargs)
|
|
56
|
+
|
|
57
|
+
# If the object was updated, print the message in yellow color, otherwise print in green color.
|
|
58
|
+
if result:
|
|
59
|
+
print_api(message, color='yellow', **print_kwargs)
|
|
60
|
+
# create_message_file(message, self.__class__.__name__, logger=self.logger)
|
|
61
|
+
|
|
62
|
+
return_list.append(message)
|
|
63
|
+
else:
|
|
64
|
+
print_api(message, color='green', **print_kwargs)
|
|
65
|
+
|
|
66
|
+
return return_list
|
|
67
|
+
|
|
68
|
+
def _get_hash(self):
|
|
69
|
+
# Copy the file to the original object directory.
|
|
70
|
+
if self.store_original_file_path:
|
|
71
|
+
filesystem.copy_file(self.change_monitor_instance.check_object, self.store_original_file_path)
|
|
72
|
+
|
|
73
|
+
# Get hash of the file.
|
|
74
|
+
hash_string = hashing.hash_file(self.change_monitor_instance.check_object)
|
|
75
|
+
|
|
76
|
+
# Set the hash string to the 'check_object' variable.
|
|
77
|
+
self.diff_checker.check_object = hash_string
|
|
@@ -1,18 +1,17 @@
|
|
|
1
|
+
from ... import diff_check
|
|
1
2
|
from ...print_api import print_api
|
|
2
3
|
from .hash_checks import file, url
|
|
3
4
|
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
# '[input_directory] or [input_file_path] must be specified .')
|
|
6
|
+
DIFF_CHECKER = diff_check.DiffChecker(
|
|
7
|
+
return_first_cycle=False,
|
|
8
|
+
operation_type='single_object'
|
|
9
|
+
)
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
def setup_check(change_monitor_instance):
|
|
12
13
|
change_monitor_instance.set_input_file_path()
|
|
13
14
|
|
|
14
|
-
change_monitor_instance.diff_checker.operation_type = 'single_object'
|
|
15
|
-
|
|
16
15
|
if change_monitor_instance.object_type == 'file':
|
|
17
16
|
file.setup_check(change_monitor_instance, change_monitor_instance.check_object)
|
|
18
17
|
elif 'url_' in change_monitor_instance.object_type:
|
|
@@ -1,91 +1,91 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Union
|
|
3
|
+
|
|
1
4
|
from ...wrappers.psutilw import psutilw
|
|
2
5
|
from ...basics import list_of_dicts
|
|
3
6
|
from ...print_api import print_api
|
|
7
|
+
from ... import diff_check
|
|
4
8
|
|
|
5
9
|
|
|
6
|
-
|
|
7
|
-
original_name: str = str()
|
|
8
|
-
|
|
9
|
-
# Initialize objects for network monitoring.
|
|
10
|
-
change_monitor_instance.fetch_engine = psutilw.PsutilConnections()
|
|
11
|
-
|
|
12
|
-
# Change settings for the DiffChecker object.
|
|
13
|
-
change_monitor_instance.diff_checker.return_first_cycle = True
|
|
14
|
-
|
|
15
|
-
if change_monitor_instance.generate_input_file_name:
|
|
16
|
-
original_name = 'known_connections'
|
|
17
|
-
# Make path for 'input_file_name'.
|
|
18
|
-
change_monitor_instance.input_file_name = f'{original_name}.txt'
|
|
19
|
-
|
|
20
|
-
change_monitor_instance.diff_checker.check_object_display_name = \
|
|
21
|
-
f'{original_name}|{change_monitor_instance.object_type}'
|
|
22
|
-
|
|
23
|
-
# Set the 'check_object' to empty list, since we will append the list of DNS events.
|
|
24
|
-
change_monitor_instance.diff_checker.check_object = list()
|
|
25
|
-
|
|
26
|
-
change_monitor_instance.diff_checker.operation_type = 'single_object'
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def execute_cycle(change_monitor_instance, print_kwargs: dict = None):
|
|
30
|
-
"""
|
|
31
|
-
This function executes the cycle of the change monitor: network.
|
|
32
|
-
|
|
33
|
-
:param change_monitor_instance: Instance of the ChangeMonitor class.
|
|
34
|
-
:param print_kwargs: print_api kwargs.
|
|
35
|
-
|
|
36
|
-
:return: List of dictionaries with the results of the cycle.
|
|
37
|
-
"""
|
|
38
|
-
|
|
39
|
-
if print_kwargs is None:
|
|
40
|
-
print_kwargs = dict()
|
|
41
|
-
|
|
42
|
-
return_list = list()
|
|
43
|
-
|
|
44
|
-
_get_list(change_monitor_instance)
|
|
45
|
-
|
|
46
|
-
change_monitor_instance._set_input_file_path()
|
|
47
|
-
|
|
48
|
-
# Check if 'known_domains' list was updated from previous cycle.
|
|
49
|
-
result, message = change_monitor_instance.diff_checker.check_list_of_dicts(print_kwargs=print_kwargs)
|
|
10
|
+
INPUT_FILE_DEFAULT_NAME: str = 'known_connections.txt'
|
|
50
11
|
|
|
51
|
-
if result:
|
|
52
|
-
# Get list of new connections only.
|
|
53
|
-
new_connections_only: list = list_of_dicts.get_difference(result['old'], result['updated'])
|
|
54
12
|
|
|
55
|
-
|
|
56
|
-
message = \
|
|
57
|
-
f"New connection: {connection['name']} | " \
|
|
58
|
-
f"{connection['dst_ip']}:{connection['dst_port']} | " \
|
|
59
|
-
f"{connection['family']} | {connection['type']} | {connection['cmdline']}"
|
|
60
|
-
# f"{connection['src_ip']}:{connection['src_port']} -> " \
|
|
61
|
-
print_api(message, color='yellow', **print_kwargs)
|
|
62
|
-
|
|
63
|
-
return_list.append(message)
|
|
64
|
-
|
|
65
|
-
return return_list
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def _get_list(change_monitor_instance):
|
|
13
|
+
class NetworkCheck:
|
|
69
14
|
"""
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
:param change_monitor_instance: Instance of the ChangeMonitor class.
|
|
73
|
-
|
|
74
|
-
:return: list of dicts, of new network sockets.
|
|
15
|
+
Class for network monitoring.
|
|
75
16
|
"""
|
|
76
17
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
18
|
+
def __init__(self, change_monitor_instance):
|
|
19
|
+
self.change_monitor_instance = change_monitor_instance
|
|
20
|
+
self.diff_checker: Union[diff_check.DiffChecker, None] = None
|
|
21
|
+
self.fetch_engine = psutilw.PsutilConnections()
|
|
22
|
+
|
|
23
|
+
if not change_monitor_instance.input_file_name:
|
|
24
|
+
change_monitor_instance.input_file_name = INPUT_FILE_DEFAULT_NAME
|
|
25
|
+
input_file_path = (
|
|
26
|
+
str(Path(change_monitor_instance.input_directory, change_monitor_instance.input_file_name)))
|
|
27
|
+
|
|
28
|
+
diff_checker_display_name = \
|
|
29
|
+
f'{change_monitor_instance.input_file_name}|{change_monitor_instance.object_type}'
|
|
30
|
+
self.diff_checker = diff_check.DiffChecker(
|
|
31
|
+
check_object=list(), # we will append the list of connection events.
|
|
32
|
+
return_first_cycle=True,
|
|
33
|
+
operation_type='single_object',
|
|
34
|
+
check_object_display_name=diff_checker_display_name,
|
|
35
|
+
input_file_path=input_file_path
|
|
36
|
+
)
|
|
37
|
+
self.diff_checker.initiate_before_action()
|
|
38
|
+
|
|
39
|
+
def execute_cycle(self, print_kwargs: dict = None):
|
|
40
|
+
"""
|
|
41
|
+
This function executes the cycle of the change monitor: network.
|
|
42
|
+
|
|
43
|
+
:param print_kwargs: print_api kwargs.
|
|
44
|
+
:return: List of dictionaries with the results of the cycle.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
return_list = list()
|
|
48
|
+
|
|
49
|
+
self._get_list()
|
|
50
|
+
|
|
51
|
+
# Check if 'known_domains' list was updated from previous cycle.
|
|
52
|
+
result, message = self.diff_checker.check_list_of_dicts(print_kwargs=print_kwargs)
|
|
53
|
+
|
|
54
|
+
if result:
|
|
55
|
+
# Get list of new connections only.
|
|
56
|
+
new_connections_only: list = list_of_dicts.get_difference(result['old'], result['updated'])
|
|
57
|
+
|
|
58
|
+
for connection in new_connections_only:
|
|
59
|
+
message = \
|
|
60
|
+
f"New connection: {connection['name']} | " \
|
|
61
|
+
f"{connection['dst_ip']}:{connection['dst_port']} | " \
|
|
62
|
+
f"{connection['family']} | {connection['type']} | {connection['cmdline']}"
|
|
63
|
+
# f"{connection['src_ip']}:{connection['src_port']} -> " \
|
|
64
|
+
print_api(message, color='yellow', **(print_kwargs or {}))
|
|
65
|
+
|
|
66
|
+
return_list.append(message)
|
|
67
|
+
|
|
68
|
+
return return_list
|
|
69
|
+
|
|
70
|
+
def _get_list(self):
|
|
71
|
+
"""
|
|
72
|
+
The function will get the list of opened network sockets and return only the new ones.
|
|
73
|
+
|
|
74
|
+
:return: list of dicts, of new network sockets.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
# Get all connections (list of dicts), including process name and cmdline.
|
|
78
|
+
connections_list_of_dicts: list = \
|
|
79
|
+
self.fetch_engine.get_connections_with_process_as_list_of_dicts(
|
|
80
|
+
attrs=['name', 'cmdline', 'family', 'type', 'dst_ip', 'dst_port'], skip_empty_dst=True,
|
|
81
|
+
cmdline_to_string=True, remove_duplicates=True)
|
|
82
|
+
|
|
83
|
+
# Get list of connections that are not in 'known_connections' list.
|
|
84
|
+
missing_connections_from_cycle: list = list_of_dicts.get_difference(
|
|
85
|
+
self.diff_checker.check_object, connections_list_of_dicts)
|
|
86
|
+
# Add missing new connections to 'known_connections' list.
|
|
87
|
+
self.diff_checker.check_object.extend(missing_connections_from_cycle)
|
|
88
|
+
|
|
89
|
+
# Sort list of dicts by process name and then by process cmdline.
|
|
90
|
+
self.diff_checker.check_object = list_of_dicts.sort_by_keys(
|
|
91
|
+
self.diff_checker.check_object, key_list=['cmdline', 'name'], case_insensitive=True)
|
|
@@ -3,51 +3,50 @@ from ...basics import list_of_dicts
|
|
|
3
3
|
from ...print_api import print_api
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
change_monitor_instance.fetch_engine = psutilw.PsutilProcesses()
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def execute_cycle(change_monitor_instance, print_kwargs: dict = None):
|
|
6
|
+
class ProcessRunningCheck:
|
|
11
7
|
"""
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
:param change_monitor_instance: Instance of the ChangeMonitor class.
|
|
15
|
-
:param print_kwargs: Dictionary with the print arguments.
|
|
16
|
-
:return: List of dictionaries with the results of the cycle.
|
|
8
|
+
Class for process running monitoring.
|
|
17
9
|
"""
|
|
18
10
|
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
def __init__(self, change_monitor_instance):
|
|
12
|
+
self.change_monitor_instance = change_monitor_instance
|
|
13
|
+
self.fetch_engine = psutilw.PsutilProcesses()
|
|
21
14
|
|
|
22
|
-
|
|
15
|
+
def execute_cycle(self, print_kwargs: dict = None):
|
|
16
|
+
"""
|
|
17
|
+
This function executes the cycle of the change monitor: process_running.
|
|
23
18
|
|
|
24
|
-
|
|
19
|
+
:param print_kwargs: Dictionary with the print arguments.
|
|
20
|
+
:return: List of dictionaries with the results of the cycle.
|
|
21
|
+
"""
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
result = list_of_dicts.is_value_exist_in_key(processes, 'cmdline', process_name, value_case_insensitive=True)
|
|
23
|
+
return_list = list()
|
|
28
24
|
|
|
29
|
-
|
|
30
|
-
if result:
|
|
31
|
-
message = f"Process [{process_name}] is Running."
|
|
32
|
-
print_api(message, color='green', **print_kwargs)
|
|
33
|
-
# If the process name was not found in the list of currently running processes.
|
|
34
|
-
else:
|
|
35
|
-
message = f"Process [{process_name}] not Running!"
|
|
36
|
-
print_api(message, color='red', **print_kwargs)
|
|
25
|
+
processes = self._get_list()
|
|
37
26
|
|
|
38
|
-
|
|
27
|
+
for process_name in self.change_monitor_instance.check_object:
|
|
28
|
+
result = list_of_dicts.is_value_exist_in_key(
|
|
29
|
+
processes, 'cmdline', process_name, value_case_insensitive=True)
|
|
39
30
|
|
|
40
|
-
|
|
31
|
+
# If the process name was found in the list of currently running processes.
|
|
32
|
+
if result:
|
|
33
|
+
message = f"Process [{process_name}] is Running."
|
|
34
|
+
print_api(message, color='green', **(print_kwargs or {}))
|
|
35
|
+
# If the process name was not found in the list of currently running processes.
|
|
36
|
+
else:
|
|
37
|
+
message = f"Process [{process_name}] not Running!"
|
|
38
|
+
print_api(message, color='red', **(print_kwargs or {}))
|
|
41
39
|
|
|
40
|
+
return_list.append(message)
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
"""
|
|
45
|
-
The function will get the list of opened network sockets and return only the new ones.
|
|
42
|
+
return return_list
|
|
46
43
|
|
|
47
|
-
|
|
44
|
+
def _get_list(self):
|
|
45
|
+
"""
|
|
46
|
+
The function will get the list of opened network sockets and return only the new ones.
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
:return: list of dicts, of new network sockets.
|
|
49
|
+
"""
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
return self.fetch_engine.get_processes_as_list_of_dicts(
|
|
52
|
+
default_keys=True, cmdline_to_string=True)
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from ... import hashing, urls
|
|
4
|
+
from ... import diff_check
|
|
5
|
+
from ...print_api import print_api
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class UrlCheck:
|
|
9
|
+
"""
|
|
10
|
+
Class for file monitoring.
|
|
11
|
+
"""
|
|
12
|
+
def __init__(self, change_monitor_instance):
|
|
13
|
+
self.diff_checker = None
|
|
14
|
+
self.change_monitor_instance = None
|
|
15
|
+
self.store_original_file_path = None
|
|
16
|
+
self.get_method = None
|
|
17
|
+
|
|
18
|
+
# Extract the method name from the object type.
|
|
19
|
+
self.get_method = change_monitor_instance.object_type.split('_', 1)[1]
|
|
20
|
+
|
|
21
|
+
if not change_monitor_instance.input_file_name:
|
|
22
|
+
change_monitor_instance.input_file_name = (
|
|
23
|
+
urls.url_parser(change_monitor_instance.check_object))['directories'][-1]
|
|
24
|
+
change_monitor_instance.input_file_name = change_monitor_instance.input_file_name.lower()
|
|
25
|
+
change_monitor_instance.input_file_name = f'{change_monitor_instance.input_file_name}.txt'
|
|
26
|
+
|
|
27
|
+
input_file_path = (
|
|
28
|
+
str(Path(change_monitor_instance.input_directory, change_monitor_instance.input_file_name)))
|
|
29
|
+
|
|
30
|
+
# If 'store_original_object' is True, create filename for the store original object.
|
|
31
|
+
if change_monitor_instance.object_type_settings['store_original_object']:
|
|
32
|
+
# Add extension to the file name.
|
|
33
|
+
extension: str = str()
|
|
34
|
+
if 'playwright' in self.get_method:
|
|
35
|
+
extension = self.get_method.split('_')[1]
|
|
36
|
+
elif self.get_method == 'urllib':
|
|
37
|
+
extension = 'html'
|
|
38
|
+
|
|
39
|
+
store_original_file_name: str = Path(change_monitor_instance.input_file_name).stem
|
|
40
|
+
store_original_file_name = f'{store_original_file_name}.{extension}'
|
|
41
|
+
self.store_original_file_path = str(Path(change_monitor_instance.input_directory, store_original_file_name))
|
|
42
|
+
|
|
43
|
+
self.diff_checker = diff_check.DiffChecker(
|
|
44
|
+
return_first_cycle=False,
|
|
45
|
+
operation_type='single_object',
|
|
46
|
+
input_file_path=input_file_path,
|
|
47
|
+
check_object_display_name=f'{change_monitor_instance.input_file_name}|{change_monitor_instance.object_type}'
|
|
48
|
+
)
|
|
49
|
+
self.diff_checker.initiate_before_action()
|
|
50
|
+
self.change_monitor_instance = change_monitor_instance
|
|
51
|
+
|
|
52
|
+
def execute_cycle(self, print_kwargs: dict = None):
|
|
53
|
+
"""
|
|
54
|
+
This function executes the cycle of the change monitor: hash.
|
|
55
|
+
|
|
56
|
+
:param print_kwargs: print_api kwargs.
|
|
57
|
+
:return: List of dictionaries with the results of the cycle.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
return_list = list()
|
|
61
|
+
|
|
62
|
+
self._get_hash(print_kwargs=print_kwargs)
|
|
63
|
+
|
|
64
|
+
# Check if the object was updated.
|
|
65
|
+
result, message = self.diff_checker.check_string(
|
|
66
|
+
print_kwargs=print_kwargs)
|
|
67
|
+
|
|
68
|
+
# If the object was updated, print the message in yellow color, otherwise print in green color.
|
|
69
|
+
if result:
|
|
70
|
+
print_api(message, color='yellow', **print_kwargs)
|
|
71
|
+
# create_message_file(message, self.__class__.__name__, logger=self.logger)
|
|
72
|
+
|
|
73
|
+
return_list.append(message)
|
|
74
|
+
else:
|
|
75
|
+
print_api(message, color='green', **print_kwargs)
|
|
76
|
+
|
|
77
|
+
return return_list
|
|
78
|
+
|
|
79
|
+
def _get_hash(self, print_kwargs: dict = None):
|
|
80
|
+
"""
|
|
81
|
+
The function will get the hash of the URL content.
|
|
82
|
+
|
|
83
|
+
:param print_kwargs: print_api kwargs.
|
|
84
|
+
"""
|
|
85
|
+
# Get hash of the url. The hash will be different between direct hash of the URL content and the
|
|
86
|
+
# hash of the file that was downloaded from the URL. Since the file has headers and other information
|
|
87
|
+
# that is not part of the URL content. The Original downloaded file is for reference only to see
|
|
88
|
+
# what was the content of the URL at the time of the download.
|
|
89
|
+
hash_string = hashing.hash_url(
|
|
90
|
+
self.change_monitor_instance.check_object, get_method=self.get_method,
|
|
91
|
+
path=self.store_original_file_path, print_kwargs=print_kwargs)
|
|
92
|
+
|
|
93
|
+
# Set the hash string to the 'check_object' variable.
|
|
94
|
+
self.diff_checker.check_object = hash_string
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
atomicshop/__init__.py,sha256=
|
|
1
|
+
atomicshop/__init__.py,sha256=CBepG0XgfpgafeV__swI0Jz0kUF1uJvK3WLlJWWcQwk,124
|
|
2
2
|
atomicshop/_basics_temp.py,sha256=6cu2dd6r2dLrd1BRNcVDKTHlsHs_26Gpw8QS6v32lQ0,3699
|
|
3
3
|
atomicshop/_create_pdf_demo.py,sha256=Yi-PGZuMg0RKvQmLqVeLIZYadqEZwUm-4A9JxBl_vYA,3713
|
|
4
4
|
atomicshop/_patch_import.py,sha256=ENp55sKVJ0e6-4lBvZnpz9PQCt3Otbur7F6aXDlyje4,6334
|
|
@@ -9,7 +9,7 @@ atomicshop/config_init.py,sha256=z2RXD_mw9nQlAOpuGry1h9QT-2LhNscXgGAktN3dCVQ,249
|
|
|
9
9
|
atomicshop/console_output.py,sha256=AOSJjrRryE97PAGtgDL03IBtWSi02aNol8noDnW3k6M,4667
|
|
10
10
|
atomicshop/console_user_response.py,sha256=31HIy9QGXa7f-GVR8MzJauQ79E_ZqAeagF3Ks4GGdDU,3234
|
|
11
11
|
atomicshop/datetimes.py,sha256=olsL01S5tkXk4WPzucxujqgLOh198BLgJntDnGYukRU,15533
|
|
12
|
-
atomicshop/diff_check.py,sha256=
|
|
12
|
+
atomicshop/diff_check.py,sha256=0H4OeRxJodFIubpAoy2dFY9hixzLbkJ8NNlH6K3Xdus,27033
|
|
13
13
|
atomicshop/dns.py,sha256=bNZOo5jVPzq7OT2qCPukXoK3zb1oOsyaelUwQEyK1SA,2500
|
|
14
14
|
atomicshop/domains.py,sha256=Rxu6JhhMqFZRcoFs69IoEd1PtYca0lMCG6F1AomP7z4,3197
|
|
15
15
|
atomicshop/emails.py,sha256=I0KyODQpIMEsNRi9YWSOL8EUPBiWyon3HRdIuSj3AEU,1410
|
|
@@ -106,7 +106,7 @@ atomicshop/etw/etw.py,sha256=xVJNbfCq4KgRfsDnul6CrIdAMl9xRBixZ-hUyqiB2g4,2403
|
|
|
106
106
|
atomicshop/file_io/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
107
107
|
atomicshop/file_io/csvs.py,sha256=WOtDyVFhhA1RD3yrU9P33kDY1EKFEz8UmVCUkqYKuog,5503
|
|
108
108
|
atomicshop/file_io/docxs.py,sha256=6tcYFGp0vRsHR47VwcRqwhdt2DQOwrAUYhrwN996n9U,5117
|
|
109
|
-
atomicshop/file_io/file_io.py,sha256=
|
|
109
|
+
atomicshop/file_io/file_io.py,sha256=FOZ6_PjOASxSDHESe4fwDv5miXYR10OHTxkxtEHoZYQ,6555
|
|
110
110
|
atomicshop/file_io/jsons.py,sha256=q9ZU8slBKnHLrtn3TnbK1qxrRpj5ZvCm6AlsFzoANjo,5303
|
|
111
111
|
atomicshop/file_io/tomls.py,sha256=oa0Wm8yMkPRXKN9jgBuTnKbioSOee4mABW5IMUFCYyU,3041
|
|
112
112
|
atomicshop/file_io/xlsxs.py,sha256=v_dyg9GD4LqgWi6wA1QuWRZ8zG4ZwB6Dz52ytdcmmmI,2184
|
|
@@ -132,15 +132,14 @@ atomicshop/mitm/engines/__reference_general/parser___reference_general.py,sha256
|
|
|
132
132
|
atomicshop/mitm/engines/__reference_general/recorder___reference_general.py,sha256=KENDVf9OwXD9gwSh4B1XxACCe7iHYjrvnW1t6F64wdE,695
|
|
133
133
|
atomicshop/mitm/engines/__reference_general/responder___reference_general.py,sha256=1AM49UaFTKA0AHw-k3SV3uH3QbG-o6ux0c-GoWkKNU0,6993
|
|
134
134
|
atomicshop/monitor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
135
|
-
atomicshop/monitor/change_monitor.py,sha256=
|
|
135
|
+
atomicshop/monitor/change_monitor.py,sha256=mrLedkgXWxKzQLqjYd3bmD8-or6HlX9sejdXbSvhNMI,9016
|
|
136
136
|
atomicshop/monitor/checks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
137
|
-
atomicshop/monitor/checks/dns.py,sha256=
|
|
138
|
-
atomicshop/monitor/checks/
|
|
139
|
-
atomicshop/monitor/checks/
|
|
140
|
-
atomicshop/monitor/checks/
|
|
141
|
-
atomicshop/monitor/checks/
|
|
142
|
-
atomicshop/monitor/checks/
|
|
143
|
-
atomicshop/monitor/checks/hash_checks/url.py,sha256=XxBNjhQZO_JlicgadqBblvt6sIRizerwM-LVCOgMCQU,3020
|
|
137
|
+
atomicshop/monitor/checks/dns.py,sha256=bPqQACt8IgQ08U-x9G7pAN-iSfxbdOAubJTHZd-lJ84,6792
|
|
138
|
+
atomicshop/monitor/checks/file.py,sha256=2tIDSlX2KZNc_9i9ji1tcOqupbFTIOj7cKXLyBEDWMk,3263
|
|
139
|
+
atomicshop/monitor/checks/hash.py,sha256=r4mDOdjItN3eyaJk8TVz03f4bQ_uKZ4MDTXagjseazs,2011
|
|
140
|
+
atomicshop/monitor/checks/network.py,sha256=CGZWl4WlQrxayZeVF9JspJXwYA-zWx8ECWTVGSlXc98,3825
|
|
141
|
+
atomicshop/monitor/checks/process_running.py,sha256=x66wd6-l466r8sbRQaIli0yswyGt1dH2DVXkGDL6O0Q,1891
|
|
142
|
+
atomicshop/monitor/checks/url.py,sha256=1PvKt_d7wFg7rDMFpUejAQhj0mqWsmlmrNfjNAV2G4g,4123
|
|
144
143
|
atomicshop/ssh_scripts/process_from_ipv4.py,sha256=uDBKZ2Ds20614JW1xMLr4IPB-z1LzIwy6QH5-SJ4j0s,1681
|
|
145
144
|
atomicshop/ssh_scripts/process_from_port.py,sha256=uDTkVh4zc3HOTTGv1Et3IxM3PonDJCPuFRL6rnZDQZ4,1389
|
|
146
145
|
atomicshop/wrappers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -251,8 +250,8 @@ atomicshop/wrappers/socketw/socket_server_tester.py,sha256=AhpurHJmP2kgzHaUbq5ey
|
|
|
251
250
|
atomicshop/wrappers/socketw/socket_wrapper.py,sha256=aXBwlEIJhFT0-c4i8iNlFx2It9VpCEpsv--5Oqcpxao,11624
|
|
252
251
|
atomicshop/wrappers/socketw/ssl_base.py,sha256=k4V3gwkbq10MvOH4btU4onLX2GNOsSfUAdcHmL1rpVE,2274
|
|
253
252
|
atomicshop/wrappers/socketw/statistics_csv.py,sha256=t3dtDEfN47CfYVi0CW6Kc2QHTEeZVyYhc57IYYh5nmA,826
|
|
254
|
-
atomicshop-2.12.
|
|
255
|
-
atomicshop-2.12.
|
|
256
|
-
atomicshop-2.12.
|
|
257
|
-
atomicshop-2.12.
|
|
258
|
-
atomicshop-2.12.
|
|
253
|
+
atomicshop-2.12.19.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
|
|
254
|
+
atomicshop-2.12.19.dist-info/METADATA,sha256=XjMOMxBIk9wbHMRy4KgeBeYKoy8sD8FJjt-CGllbCsw,10479
|
|
255
|
+
atomicshop-2.12.19.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
256
|
+
atomicshop-2.12.19.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
|
|
257
|
+
atomicshop-2.12.19.dist-info/RECORD,,
|
|
File without changes
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
from .... import filesystem, hashing
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def setup_check(change_monitor_instance, check_object: str):
|
|
5
|
-
original_name: str = str()
|
|
6
|
-
|
|
7
|
-
# If 'generate_input_file_name' is True, or 'store_original_object' is True, we need to create a
|
|
8
|
-
# filename without extension.
|
|
9
|
-
if change_monitor_instance.store_original_object or change_monitor_instance.generate_input_file_name:
|
|
10
|
-
# Get the last directory from the url.
|
|
11
|
-
original_name = filesystem.get_file_name(check_object)
|
|
12
|
-
# Make characters lower case.
|
|
13
|
-
original_name = original_name.lower()
|
|
14
|
-
|
|
15
|
-
# If 'store_original_object' is True, then we need to create a filepath to store.
|
|
16
|
-
if change_monitor_instance.original_object_directory:
|
|
17
|
-
# Add extension to the file name.
|
|
18
|
-
original_file_name = original_name
|
|
19
|
-
|
|
20
|
-
# Make path for original object.
|
|
21
|
-
change_monitor_instance.original_object_file_path = filesystem.add_object_to_path(
|
|
22
|
-
change_monitor_instance.original_object_directory, original_file_name)
|
|
23
|
-
|
|
24
|
-
if change_monitor_instance.generate_input_file_name:
|
|
25
|
-
# Remove dots from the file name.
|
|
26
|
-
original_name_no_dots = original_name.replace('.', '-')
|
|
27
|
-
# Make path for 'input_file_name'.
|
|
28
|
-
change_monitor_instance.input_file_name = f'{original_name_no_dots}.txt'
|
|
29
|
-
|
|
30
|
-
# Change settings for the DiffChecker object.
|
|
31
|
-
change_monitor_instance.diff_checker.return_first_cycle = False
|
|
32
|
-
|
|
33
|
-
change_monitor_instance.diff_checker.check_object_display_name = \
|
|
34
|
-
f'{original_name}|{change_monitor_instance.object_type}'
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def get_hash(change_monitor_instance, check_object: str, print_kwargs: dict = None):
|
|
38
|
-
"""
|
|
39
|
-
The function will get the hash of the URL content.
|
|
40
|
-
|
|
41
|
-
:param change_monitor_instance: Instance of the ChangeMonitor class.
|
|
42
|
-
:param check_object: string, full URL to a web page.
|
|
43
|
-
:param print_kwargs: dict, that contains all the arguments for 'print_api' function.
|
|
44
|
-
"""
|
|
45
|
-
|
|
46
|
-
# Copy the file to the original object directory.
|
|
47
|
-
if change_monitor_instance.original_object_file_path:
|
|
48
|
-
filesystem.copy_file(check_object, change_monitor_instance.original_object_file_path)
|
|
49
|
-
|
|
50
|
-
# Get hash of the file.
|
|
51
|
-
hash_string = hashing.hash_file(check_object)
|
|
52
|
-
|
|
53
|
-
# Set the hash string to the 'check_object' variable.
|
|
54
|
-
change_monitor_instance.diff_checker.check_object = hash_string
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
from .... import filesystem, hashing, urls
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def setup_check(change_monitor_instance, check_object: str):
|
|
5
|
-
# Extract the method name from the object type.
|
|
6
|
-
get_method = change_monitor_instance.object_type.split('_', 1)[1]
|
|
7
|
-
|
|
8
|
-
original_name: str = str()
|
|
9
|
-
|
|
10
|
-
# If 'generate_input_file_name' is True, or 'store_original_object' is True, we need to create a
|
|
11
|
-
# filename without extension.
|
|
12
|
-
if change_monitor_instance.store_original_object or change_monitor_instance.generate_input_file_name:
|
|
13
|
-
# Get the last directory from the url.
|
|
14
|
-
original_name = urls.url_parser(check_object)['directories'][-1]
|
|
15
|
-
# Make characters lower case.
|
|
16
|
-
original_name = original_name.lower()
|
|
17
|
-
|
|
18
|
-
# If 'store_original_object' is True, then we need to create a filepath to store.
|
|
19
|
-
extension = None
|
|
20
|
-
if change_monitor_instance.original_object_directory:
|
|
21
|
-
# Add extension to the file name.
|
|
22
|
-
if 'playwright' in get_method:
|
|
23
|
-
extension = get_method.split('_')[1]
|
|
24
|
-
elif get_method == 'urllib':
|
|
25
|
-
extension = 'html'
|
|
26
|
-
original_file_name = f'{original_name}.{extension}'
|
|
27
|
-
|
|
28
|
-
# Make path for original object.
|
|
29
|
-
change_monitor_instance.original_object_file_path = filesystem.add_object_to_path(
|
|
30
|
-
change_monitor_instance.original_object_directory, original_file_name)
|
|
31
|
-
|
|
32
|
-
if change_monitor_instance.generate_input_file_name:
|
|
33
|
-
# Make path for 'input_file_name'.
|
|
34
|
-
change_monitor_instance.input_file_name = f'{original_name}.txt'
|
|
35
|
-
|
|
36
|
-
# Change settings for the DiffChecker object.
|
|
37
|
-
change_monitor_instance.diff_checker.return_first_cycle = False
|
|
38
|
-
|
|
39
|
-
change_monitor_instance.diff_checker.check_object_display_name = \
|
|
40
|
-
f'{original_name}|{change_monitor_instance.object_type}'
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def get_hash(change_monitor_instance, check_object: str, print_kwargs: dict = None):
|
|
44
|
-
"""
|
|
45
|
-
The function will get the hash of the URL content.
|
|
46
|
-
|
|
47
|
-
:param change_monitor_instance: Instance of the ChangeMonitor class.
|
|
48
|
-
:param check_object: string, full URL to a web page.
|
|
49
|
-
:param print_kwargs: dict, that contains all the arguments for 'print_api' function.
|
|
50
|
-
"""
|
|
51
|
-
# Extract the method name from the object type.
|
|
52
|
-
get_method = change_monitor_instance.object_type.split('_', 1)[1]
|
|
53
|
-
|
|
54
|
-
# Get hash of the url. The hash will be different between direct hash of the URL content and the
|
|
55
|
-
# hash of the file that was downloaded from the URL. Since the file has headers and other information
|
|
56
|
-
# that is not part of the URL content. The Original downloaded file is for reference only to see
|
|
57
|
-
# what was the content of the URL at the time of the download.
|
|
58
|
-
hash_string = hashing.hash_url(
|
|
59
|
-
check_object, get_method=get_method, path=change_monitor_instance.original_object_file_path,
|
|
60
|
-
print_kwargs=print_kwargs
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
# Set the hash string to the 'check_object' variable.
|
|
64
|
-
change_monitor_instance.diff_checker.check_object = hash_string
|
|
File without changes
|
|
File without changes
|
|
File without changes
|