atomicshop 2.16.10__py3-none-any.whl → 2.16.11__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/dns.py +2 -4
- atomicshop/file_io/file_io.py +12 -0
- atomicshop/mitm/config_static.py +6 -7
- atomicshop/mitm/connection_thread_worker.py +59 -39
- atomicshop/mitm/engines/__parent/parser___parent.py +0 -1
- atomicshop/mitm/engines/__parent/recorder___parent.py +5 -6
- atomicshop/mitm/engines/__parent/responder___parent.py +0 -1
- atomicshop/mitm/import_config.py +6 -4
- atomicshop/mitm/initialize_mitm_server.py +53 -29
- atomicshop/mitm/message.py +1 -0
- atomicshop/mitm/recs_files.py +0 -1
- atomicshop/ssh_remote.py +9 -9
- atomicshop/wrappers/pywin32w/wmis/helpers.py +5 -1
- atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +0 -32
- atomicshop/wrappers/socketw/dns_server.py +9 -10
- atomicshop/wrappers/socketw/exception_wrapper.py +5 -7
- atomicshop/wrappers/socketw/get_process.py +3 -3
- atomicshop/wrappers/socketw/receiver.py +3 -3
- atomicshop/wrappers/socketw/sender.py +1 -1
- atomicshop/wrappers/socketw/sni.py +1 -1
- atomicshop/wrappers/winregw/__init__.py +0 -0
- atomicshop/wrappers/winregw/winreg_network.py +174 -0
- {atomicshop-2.16.10.dist-info → atomicshop-2.16.11.dist-info}/METADATA +1 -1
- {atomicshop-2.16.10.dist-info → atomicshop-2.16.11.dist-info}/RECORD +28 -26
- {atomicshop-2.16.10.dist-info → atomicshop-2.16.11.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.16.10.dist-info → atomicshop-2.16.11.dist-info}/WHEEL +0 -0
- {atomicshop-2.16.10.dist-info → atomicshop-2.16.11.dist-info}/top_level.txt +0 -0
atomicshop/__init__.py
CHANGED
atomicshop/dns.py
CHANGED
|
@@ -5,6 +5,7 @@ import dns.resolver
|
|
|
5
5
|
from .print_api import print_api
|
|
6
6
|
from .permissions import permissions
|
|
7
7
|
from .wrappers.pywin32w.wmis import win32networkadapter
|
|
8
|
+
from .wrappers.winregw import winreg_network
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
# Defining Dictionary of Numeric to String DNS Query Types.
|
|
@@ -71,10 +72,7 @@ def get_default_dns_gateway() -> tuple[bool, list[str]]:
|
|
|
71
72
|
:return: tuple(is dynamic boolean, list of DNS server IPv4s).
|
|
72
73
|
"""
|
|
73
74
|
|
|
74
|
-
|
|
75
|
-
dns_servers = list(resolver.nameservers)
|
|
76
|
-
|
|
77
|
-
is_dynamic = win32networkadapter.is_adapter_dns_gateway_from_dhcp(use_default_interface=True)
|
|
75
|
+
is_dynamic, dns_servers = winreg_network.get_default_dns_gateway()
|
|
78
76
|
return is_dynamic, dns_servers
|
|
79
77
|
|
|
80
78
|
|
atomicshop/file_io/file_io.py
CHANGED
|
@@ -21,6 +21,15 @@ def write_file_decorator(function_name):
|
|
|
21
21
|
|
|
22
22
|
print_api(message=f"Writing file: {kwargs['file_path']}", **kwargs)
|
|
23
23
|
|
|
24
|
+
if kwargs['enable_long_file_path']:
|
|
25
|
+
# A simpler string method would be to add '\\?\' to the beginning of the file path.
|
|
26
|
+
# kwargs['file_path'] = rf"\\?\{kwargs['file_path']}"
|
|
27
|
+
|
|
28
|
+
# Enable long file path.
|
|
29
|
+
from ctypes import windll
|
|
30
|
+
# Enable long file path.
|
|
31
|
+
windll.kernel32.SetFileAttributesW(kwargs['file_path'], 0x80)
|
|
32
|
+
|
|
24
33
|
try:
|
|
25
34
|
with open(kwargs['file_path'], kwargs['file_mode'], encoding=kwargs['encoding']) as output_file:
|
|
26
35
|
# Pass the 'output_file' object to kwargs that will pass the object to the executing function.
|
|
@@ -78,6 +87,7 @@ def write_file(
|
|
|
78
87
|
file_path: str,
|
|
79
88
|
file_mode: str = 'w',
|
|
80
89
|
encoding: str = None,
|
|
90
|
+
enable_long_file_path: bool = False,
|
|
81
91
|
file_object=None,
|
|
82
92
|
**kwargs) -> None:
|
|
83
93
|
"""
|
|
@@ -89,6 +99,8 @@ def write_file(
|
|
|
89
99
|
Default is 'w'.
|
|
90
100
|
:param encoding: string, write the file with encoding. Example: 'utf-8'. 'None' is default, since it is default
|
|
91
101
|
in 'open()' function.
|
|
102
|
+
:param enable_long_file_path: Boolean, by default Windows has a limit of 260 characters for file path. If True,
|
|
103
|
+
the long file path will be enabled, and the limit will be 32,767 characters.
|
|
92
104
|
:param file_object: file object of the 'open()' function in the decorator. Decorator executes the 'with open()'
|
|
93
105
|
statement and passes to this function. That's why the default is 'None', since we get it from the decorator.
|
|
94
106
|
:return:
|
atomicshop/mitm/config_static.py
CHANGED
|
@@ -19,6 +19,7 @@ LIST_OF_BOOLEANS: list = [
|
|
|
19
19
|
('tcp', 'enable'),
|
|
20
20
|
('tcp', 'engines_usage'),
|
|
21
21
|
('tcp', 'server_response_mode'),
|
|
22
|
+
('logrec', 'enable_request_response_recordings_in_logs'),
|
|
22
23
|
('certificates', 'default_server_certificate_usage'),
|
|
23
24
|
('certificates', 'sni_add_new_domains_to_default_server_certificate'),
|
|
24
25
|
('certificates', 'custom_server_certificate_usage'),
|
|
@@ -34,8 +35,7 @@ LIST_OF_BOOLEANS: list = [
|
|
|
34
35
|
TOML_TO_STATIC_CATEGORIES: dict = {
|
|
35
36
|
'dns': 'DNSServer',
|
|
36
37
|
'tcp': 'TCPServer',
|
|
37
|
-
'
|
|
38
|
-
'recorder': 'Recorder',
|
|
38
|
+
'logrec': 'LogRec',
|
|
39
39
|
'certificates': 'Certificates',
|
|
40
40
|
'skip_extensions': 'SkipExtensions',
|
|
41
41
|
'process_name': 'ProcessName'
|
|
@@ -101,13 +101,12 @@ class TCPServer:
|
|
|
101
101
|
|
|
102
102
|
|
|
103
103
|
@dataclass
|
|
104
|
-
class
|
|
104
|
+
class LogRec:
|
|
105
105
|
logs_path: str
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
@dataclass
|
|
109
|
-
class Recorder:
|
|
110
106
|
recordings_path: str
|
|
107
|
+
enable_request_response_recordings_in_logs: bool
|
|
108
|
+
|
|
109
|
+
recordings_directory_name: str = 'recs'
|
|
111
110
|
|
|
112
111
|
|
|
113
112
|
@dataclass
|
|
@@ -24,7 +24,25 @@ def thread_worker_main(
|
|
|
24
24
|
reference_module
|
|
25
25
|
):
|
|
26
26
|
def output_statistics_csv_row():
|
|
27
|
-
|
|
27
|
+
# If there is no '.code' attribute in HTTPResponse, this means that this is not a HTTP message, so there is no
|
|
28
|
+
# status code.
|
|
29
|
+
try:
|
|
30
|
+
http_status_code: str = ','.join([str(x.code) for x in client_message.response_list_of_raw_decoded])
|
|
31
|
+
except AttributeError:
|
|
32
|
+
http_status_code: str = str()
|
|
33
|
+
|
|
34
|
+
# Same goes for the '.path' attribute, if it is not HTTP message then there will be no path.
|
|
35
|
+
try:
|
|
36
|
+
http_path: str = client_message.request_raw_decoded.path
|
|
37
|
+
except AttributeError:
|
|
38
|
+
http_path: str = str()
|
|
39
|
+
|
|
40
|
+
# Same goes for the '.command' attribute, if it is not HTTP message then there will be no command.
|
|
41
|
+
try:
|
|
42
|
+
http_command: str = client_message.request_raw_decoded.command
|
|
43
|
+
except AttributeError:
|
|
44
|
+
http_command: str = str()
|
|
45
|
+
|
|
28
46
|
response_size_bytes = ','.join([str(len(x)) for x in client_message.response_list_of_raw_bytes])
|
|
29
47
|
|
|
30
48
|
statistics_writer.write_row(
|
|
@@ -32,13 +50,13 @@ def thread_worker_main(
|
|
|
32
50
|
tls_type=tls_type,
|
|
33
51
|
tls_version=tls_version,
|
|
34
52
|
protocol=client_message.protocol,
|
|
35
|
-
path=
|
|
36
|
-
status_code=
|
|
37
|
-
command=
|
|
53
|
+
path=http_path,
|
|
54
|
+
status_code=http_status_code,
|
|
55
|
+
command=http_command,
|
|
38
56
|
request_time_sent=client_message.request_time_received,
|
|
39
57
|
request_size_bytes=len(client_message.request_raw_bytes),
|
|
40
58
|
response_size_bytes=response_size_bytes,
|
|
41
|
-
recorded_file_path=
|
|
59
|
+
recorded_file_path=client_message.recorded_file_path,
|
|
42
60
|
process_cmd=process_commandline,
|
|
43
61
|
error=str())
|
|
44
62
|
|
|
@@ -126,7 +144,7 @@ def thread_worker_main(
|
|
|
126
144
|
message = "There was an exception in HTTP Parsing module!"
|
|
127
145
|
print_api(
|
|
128
146
|
message, error_type=True, logger=network_logger, logger_method='critical',
|
|
129
|
-
traceback_string=True
|
|
147
|
+
traceback_string=True)
|
|
130
148
|
# Socket connection can be closed since we have a problem in current thread and break the loop
|
|
131
149
|
client_connection_boolean = False
|
|
132
150
|
break
|
|
@@ -160,10 +178,10 @@ def thread_worker_main(
|
|
|
160
178
|
message = "Exception in Parser"
|
|
161
179
|
print_api(
|
|
162
180
|
message, error_type=True, logger=parser.logger, logger_method='critical',
|
|
163
|
-
traceback_string=True
|
|
181
|
+
traceback_string=True)
|
|
164
182
|
print_api(
|
|
165
183
|
message, error_type=True, logger=network_logger, logger_method='critical',
|
|
166
|
-
traceback_string=True
|
|
184
|
+
traceback_string=True)
|
|
167
185
|
# At this point we can pass the exception and continue the script.
|
|
168
186
|
pass
|
|
169
187
|
# Socket connection can be closed since we have a problem in current thread and break the loop
|
|
@@ -193,10 +211,10 @@ def thread_worker_main(
|
|
|
193
211
|
message = "Exception in Responder"
|
|
194
212
|
print_api(
|
|
195
213
|
message, error_type=True, logger=responder.logger, logger_method='critical',
|
|
196
|
-
traceback_string=True
|
|
214
|
+
traceback_string=True)
|
|
197
215
|
print_api(
|
|
198
216
|
message, error_type=True, logger=network_logger, logger_method='critical',
|
|
199
|
-
traceback_string=True
|
|
217
|
+
traceback_string=True)
|
|
200
218
|
pass
|
|
201
219
|
# Socket connection can be closed since we have a problem in current thread and break the loop.
|
|
202
220
|
client_connection_boolean = False
|
|
@@ -220,8 +238,9 @@ def thread_worker_main(
|
|
|
220
238
|
service_client = socket_client.SocketClient(
|
|
221
239
|
service_name=client_message.server_name, service_port=client_message.destination_port,
|
|
222
240
|
tls=is_tls,
|
|
223
|
-
dns_servers_list=
|
|
224
|
-
|
|
241
|
+
dns_servers_list=(
|
|
242
|
+
config_static.TCPServer.forwarding_dns_service_ipv4_list___only_for_localhost)
|
|
243
|
+
)
|
|
225
244
|
# If we're not on localhost, then connect to domain directly.
|
|
226
245
|
else:
|
|
227
246
|
service_client = socket_client.SocketClient(
|
|
@@ -253,18 +272,19 @@ def thread_worker_main(
|
|
|
253
272
|
|
|
254
273
|
# This is the point after the response mode check was finished.
|
|
255
274
|
# Recording the message, doesn't matter what type of mode this is.
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
message
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
275
|
+
if config_static.LogRec.enable_request_response_recordings_in_logs:
|
|
276
|
+
try:
|
|
277
|
+
recorded_file = recorder(class_client_message=client_message,
|
|
278
|
+
record_path=config_static.LogRec.recordings_path).record()
|
|
279
|
+
client_message.recorded_file_path = recorded_file
|
|
280
|
+
except Exception:
|
|
281
|
+
message = "Exception in Recorder"
|
|
282
|
+
print_api(
|
|
283
|
+
message, error_type=True, logger=recorder.logger, logger_method='critical',
|
|
284
|
+
traceback_string=True)
|
|
285
|
+
print_api(
|
|
286
|
+
message, error_type=True, logger=network_logger, logger_method='critical',
|
|
287
|
+
traceback_string=True)
|
|
268
288
|
|
|
269
289
|
function_recorded = True
|
|
270
290
|
|
|
@@ -294,7 +314,7 @@ def thread_worker_main(
|
|
|
294
314
|
message = "Not sending anything to the client, since there is no response available"
|
|
295
315
|
print_api(
|
|
296
316
|
message, error_type=True, logger=network_logger, logger_method='critical',
|
|
297
|
-
traceback_string=True
|
|
317
|
+
traceback_string=True)
|
|
298
318
|
# Pass the exception
|
|
299
319
|
pass
|
|
300
320
|
# Break the while loop
|
|
@@ -312,18 +332,19 @@ def thread_worker_main(
|
|
|
312
332
|
# === At this point while loop of 'client_connection_boolean' was broken =======================================
|
|
313
333
|
# If recorder wasn't executed before, then execute it now
|
|
314
334
|
if not function_recorded:
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
message
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
335
|
+
if config_static.LogRec.enable_request_response_recordings_in_logs:
|
|
336
|
+
try:
|
|
337
|
+
recorded_file = recorder(
|
|
338
|
+
class_client_message=client_message, record_path=config_static.LogRec.recordings_path).record()
|
|
339
|
+
client_message.recorded_file_path = recorded_file
|
|
340
|
+
except Exception:
|
|
341
|
+
message = "Exception in Recorder"
|
|
342
|
+
print_api(
|
|
343
|
+
message, error_type=True, logger=recorder.logger, logger_method='critical',
|
|
344
|
+
traceback_string=True)
|
|
345
|
+
print_api(
|
|
346
|
+
message, error_type=True, logger=network_logger, logger_method='critical',
|
|
347
|
+
traceback_string=True)
|
|
327
348
|
|
|
328
349
|
# Save statistics file.
|
|
329
350
|
output_statistics_csv_row()
|
|
@@ -343,5 +364,4 @@ def thread_worker_main(
|
|
|
343
364
|
except Exception:
|
|
344
365
|
message = "Undocumented exception in thread worker"
|
|
345
366
|
print_api(
|
|
346
|
-
message, error_type=True, logger=network_logger, logger_method='critical',
|
|
347
|
-
traceback_string=True, oneline=True)
|
|
367
|
+
message, error_type=True, logger=network_logger, logger_method='critical', traceback_string=True)
|
|
@@ -3,8 +3,8 @@ from datetime import datetime
|
|
|
3
3
|
|
|
4
4
|
from ...shared_functions import build_module_names, create_custom_logger, get_json
|
|
5
5
|
from ... import message, recs_files
|
|
6
|
-
from ....
|
|
7
|
-
from .... import
|
|
6
|
+
from .... import filesystem, urls
|
|
7
|
+
from ....file_io import file_io
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
# The class that is responsible for Recording Requests / Responses.
|
|
@@ -52,7 +52,7 @@ class RecorderParent:
|
|
|
52
52
|
# This will happen if the message is not HTTP.
|
|
53
53
|
try:
|
|
54
54
|
# Parse the url to components.
|
|
55
|
-
http_path_parsed = url_parser(self.class_client_message.request_raw_decoded.path)
|
|
55
|
+
http_path_parsed = urls.url_parser(self.class_client_message.request_raw_decoded.path)
|
|
56
56
|
# Get only directories.
|
|
57
57
|
http_path_directories_string = '-'.join(http_path_parsed['directories'])
|
|
58
58
|
# Add '_' character before 'http_path' to look better on the file name.
|
|
@@ -64,7 +64,7 @@ class RecorderParent:
|
|
|
64
64
|
# If HTTP Path is not defined, 'http_path' will be empty, and it will not interfere with file name.
|
|
65
65
|
self.record_file_path: str = \
|
|
66
66
|
self.engine_record_path + os.sep + \
|
|
67
|
-
day_time_format + "_" + self.class_client_message.server_name +
|
|
67
|
+
day_time_format + "_" + self.class_client_message.server_name + self.file_extension
|
|
68
68
|
|
|
69
69
|
def convert_messages(self):
|
|
70
70
|
"""
|
|
@@ -91,8 +91,7 @@ class RecorderParent:
|
|
|
91
91
|
record_message = get_json(self.class_client_message)
|
|
92
92
|
|
|
93
93
|
# Since we already dumped the object to dictionary string, we'll just save the object to regular file.
|
|
94
|
-
|
|
95
|
-
output_file.write(record_message)
|
|
94
|
+
file_io.write_file(record_message, self.record_file_path, enable_long_file_path=True)
|
|
96
95
|
|
|
97
96
|
self.logger.info(f"Recorded to file: {self.record_file_path}")
|
|
98
97
|
|
atomicshop/mitm/import_config.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import os
|
|
1
2
|
from pathlib import Path
|
|
2
3
|
|
|
3
4
|
from ..print_api import print_api
|
|
@@ -131,13 +132,14 @@ def manipulations_after_import():
|
|
|
131
132
|
config_static.SkipExtensions.SKIP_EXTENSION_ID_LIST = skip_extensions
|
|
132
133
|
|
|
133
134
|
# If the paths are relative, convert them to absolute paths.
|
|
134
|
-
config_static.
|
|
135
|
-
config_static.
|
|
136
|
-
config_static.Recorder.recordings_path = filesystem.check_absolute_path___add_full(
|
|
137
|
-
config_static.Recorder.recordings_path, config_static.MainConfig.SCRIPT_DIRECTORY)
|
|
135
|
+
config_static.LogRec.logs_path = filesystem.check_absolute_path___add_full(
|
|
136
|
+
config_static.LogRec.logs_path, config_static.MainConfig.SCRIPT_DIRECTORY)
|
|
138
137
|
config_static.Certificates.custom_server_certificate_path = filesystem.check_absolute_path___add_full(
|
|
139
138
|
config_static.Certificates.custom_server_certificate_path, config_static.MainConfig.SCRIPT_DIRECTORY)
|
|
140
139
|
|
|
140
|
+
config_static.LogRec.recordings_path = (
|
|
141
|
+
config_static.LogRec.logs_path + os.sep + config_static.LogRec.recordings_directory_name)
|
|
142
|
+
|
|
141
143
|
# At this point the user that sets the config can set it to null or empty string ''. We will make sure
|
|
142
144
|
# that the path is None if it's empty.
|
|
143
145
|
if config_static.Certificates.custom_private_key_path:
|
|
@@ -17,15 +17,19 @@ from .connection_thread_worker import thread_worker_main
|
|
|
17
17
|
from . import config_static, recs_files
|
|
18
18
|
|
|
19
19
|
|
|
20
|
+
NETWORK_INTERFACE_IS_DYNAMIC: bool = bool()
|
|
21
|
+
NETWORK_INTERFACE_IPV4_ADDRESS_LIST: list[str] = list()
|
|
22
|
+
|
|
23
|
+
|
|
20
24
|
def exit_cleanup():
|
|
21
|
-
if
|
|
25
|
+
if permissions.is_admin():
|
|
22
26
|
is_dns_dynamic, current_dns_gateway = dns.get_default_dns_gateway()
|
|
23
27
|
print_api(f'Current DNS Gateway: {current_dns_gateway}')
|
|
24
28
|
|
|
25
|
-
if
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
if is_dns_dynamic != NETWORK_INTERFACE_IS_DYNAMIC or \
|
|
30
|
+
(not is_dns_dynamic and current_dns_gateway != NETWORK_INTERFACE_IPV4_ADDRESS_LIST):
|
|
31
|
+
dns.set_connection_dns_gateway_dynamic(use_default_connection=True)
|
|
32
|
+
print_api("Returned default DNS gateway...", color='blue')
|
|
29
33
|
|
|
30
34
|
|
|
31
35
|
def initialize_mitm_server(config_file_path: str):
|
|
@@ -42,20 +46,22 @@ def initialize_mitm_server(config_file_path: str):
|
|
|
42
46
|
return result
|
|
43
47
|
|
|
44
48
|
# Create folders.
|
|
45
|
-
filesystem.create_directory(config_static.
|
|
46
|
-
|
|
49
|
+
filesystem.create_directory(config_static.LogRec.logs_path)
|
|
50
|
+
|
|
51
|
+
if config_static.LogRec.enable_request_response_recordings_in_logs:
|
|
52
|
+
filesystem.create_directory(config_static.LogRec.recordings_path)
|
|
53
|
+
# Compress recordings of the previous days if there are any.
|
|
54
|
+
recs_files.recs_archiver_in_process(config_static.LogRec.recordings_path)
|
|
55
|
+
|
|
47
56
|
if config_static.Certificates.sni_get_server_certificate_from_server_socket:
|
|
48
57
|
filesystem.create_directory(
|
|
49
58
|
config_static.Certificates.sni_server_certificate_from_server_socket_download_directory)
|
|
50
59
|
|
|
51
|
-
# Compress recordings of the previous days if there are any.
|
|
52
|
-
recs_files.recs_archiver_in_process(config_static.Recorder.recordings_path)
|
|
53
|
-
|
|
54
60
|
# Create a logger that will log messages to file, Initiate System logger.
|
|
55
61
|
logger_name = "system"
|
|
56
62
|
system_logger = loggingw.create_logger(
|
|
57
63
|
logger_name=logger_name,
|
|
58
|
-
file_path=f"{config_static.
|
|
64
|
+
file_path=f"{config_static.LogRec.logs_path}{os.sep}{logger_name}.txt",
|
|
59
65
|
add_stream=True,
|
|
60
66
|
add_timedfile=True,
|
|
61
67
|
formatter_streamhandler='DEFAULT',
|
|
@@ -68,8 +74,9 @@ def initialize_mitm_server(config_file_path: str):
|
|
|
68
74
|
system_logger.info(f"Python Version: {get_current_python_version_string()}")
|
|
69
75
|
system_logger.info(f"Script Version: {config_static.SCRIPT_VERSION}")
|
|
70
76
|
system_logger.info(f"Atomic Workshop Version: {atomicshop.__version__}")
|
|
71
|
-
system_logger.info(f"Log folder: {config_static.
|
|
72
|
-
|
|
77
|
+
system_logger.info(f"Log folder: {config_static.LogRec.logs_path}")
|
|
78
|
+
if config_static.LogRec.enable_request_response_recordings_in_logs:
|
|
79
|
+
system_logger.info(f"Recordings folder for Requests/Responses: {config_static.LogRec.recordings_path}")
|
|
73
80
|
system_logger.info(f"Loaded system logger: {system_logger}")
|
|
74
81
|
|
|
75
82
|
system_logger.info(f"TCP Server Target IP: {config_static.DNSServer.target_tcp_server_ipv4}")
|
|
@@ -114,7 +121,7 @@ def initialize_mitm_server(config_file_path: str):
|
|
|
114
121
|
# Initialize engine.
|
|
115
122
|
current_module = ModuleCategory(config_static.MainConfig.SCRIPT_DIRECTORY)
|
|
116
123
|
current_module.fill_engine_fields_from_config(engine_config_path)
|
|
117
|
-
current_module.initialize_engine(logs_path=config_static.
|
|
124
|
+
current_module.initialize_engine(logs_path=config_static.LogRec.logs_path,
|
|
118
125
|
logger=system_logger)
|
|
119
126
|
|
|
120
127
|
# Extending the full engine domain list with this list.
|
|
@@ -125,7 +132,7 @@ def initialize_mitm_server(config_file_path: str):
|
|
|
125
132
|
# ==== Initialize Reference Module =============================================================================
|
|
126
133
|
reference_module = ModuleCategory(config_static.MainConfig.SCRIPT_DIRECTORY)
|
|
127
134
|
reference_module.fill_engine_fields_from_general_reference(config_static.MainConfig.ENGINES_DIRECTORY_PATH)
|
|
128
|
-
reference_module.initialize_engine(logs_path=config_static.
|
|
135
|
+
reference_module.initialize_engine(logs_path=config_static.LogRec.logs_path,
|
|
129
136
|
logger=system_logger, stdout=False, reference_general=True)
|
|
130
137
|
# === EOF Initialize Reference Module ==========================================================================
|
|
131
138
|
# === Engine logging ===========================================================================================
|
|
@@ -151,8 +158,12 @@ def initialize_mitm_server(config_file_path: str):
|
|
|
151
158
|
message = f"[*] Engine domains found, but the DNS routing is set not to use them for routing."
|
|
152
159
|
print_api(message, color="yellow", logger=system_logger)
|
|
153
160
|
elif not engines_list and config_static.DNSServer.resolve_to_tcp_server_only_engine_domains:
|
|
154
|
-
|
|
155
|
-
|
|
161
|
+
error_message = (
|
|
162
|
+
f"No engines were found in: [{config_static.MainConfig.ENGINES_DIRECTORY_PATH}]\n"
|
|
163
|
+
f"But the DNS routing is set to use them for routing.\n"
|
|
164
|
+
f"Please check your DNS configuration in the 'config.ini' file.")
|
|
165
|
+
print_api(error_message, color="red")
|
|
166
|
+
return 1
|
|
156
167
|
|
|
157
168
|
if config_static.DNSServer.resolve_to_tcp_server_all_domains:
|
|
158
169
|
print_api("All domains will be routed by the DNS server to Built-in TCP Server.", logger=system_logger)
|
|
@@ -175,8 +186,12 @@ def initialize_mitm_server(config_file_path: str):
|
|
|
175
186
|
message = f"Engines found, and the TCP server is set to use them for processing."
|
|
176
187
|
print_api(message, logger=system_logger)
|
|
177
188
|
elif not engines_list and config_static.TCPServer.engines_usage:
|
|
178
|
-
|
|
179
|
-
|
|
189
|
+
error_message = (
|
|
190
|
+
f"No engines were found in: [{config_static.MainConfig.ENGINES_DIRECTORY_PATH}]\n"
|
|
191
|
+
f"But the TCP server is set to use them for processing.\n"
|
|
192
|
+
f"Please check your TCP configuration in the 'config.ini' file.")
|
|
193
|
+
print_api(error_message, color="red")
|
|
194
|
+
return 1
|
|
180
195
|
else:
|
|
181
196
|
print_api("TCP Server is disabled.", logger=system_logger, color="yellow")
|
|
182
197
|
|
|
@@ -188,7 +203,7 @@ def initialize_mitm_server(config_file_path: str):
|
|
|
188
203
|
network_logger_name = "network"
|
|
189
204
|
network_logger = loggingw.create_logger(
|
|
190
205
|
logger_name=network_logger_name,
|
|
191
|
-
directory_path=config_static.
|
|
206
|
+
directory_path=config_static.LogRec.logs_path,
|
|
192
207
|
add_stream=True,
|
|
193
208
|
add_timedfile=True,
|
|
194
209
|
formatter_streamhandler='DEFAULT',
|
|
@@ -216,7 +231,7 @@ def initialize_mitm_server(config_file_path: str):
|
|
|
216
231
|
# Passing the engine domain list to DNS server to work with.
|
|
217
232
|
# 'list' function re-initializes the current list, or else it will be the same instance object.
|
|
218
233
|
tcp_resolve_domain_list=list(config_static.Certificates.domains_all_times),
|
|
219
|
-
log_directory_path=config_static.
|
|
234
|
+
log_directory_path=config_static.LogRec.logs_path,
|
|
220
235
|
offline_mode=config_static.DNSServer.offline_mode,
|
|
221
236
|
resolve_to_tcp_server_only_tcp_resolve_domains=(
|
|
222
237
|
config_static.DNSServer.resolve_to_tcp_server_only_engine_domains),
|
|
@@ -268,7 +283,7 @@ def initialize_mitm_server(config_file_path: str):
|
|
|
268
283
|
ssh_pass=config_static.ProcessName.ssh_pass,
|
|
269
284
|
ssh_script_to_execute=config_static.ProcessName.ssh_script_to_execute,
|
|
270
285
|
logger=listener_logger,
|
|
271
|
-
statistics_logs_directory=config_static.
|
|
286
|
+
statistics_logs_directory=config_static.LogRec.logs_path,
|
|
272
287
|
forwarding_dns_service_ipv4_list___only_for_localhost=(
|
|
273
288
|
config_static.TCPServer.forwarding_dns_service_ipv4_list___only_for_localhost),
|
|
274
289
|
skip_extension_id_list=config_static.SkipExtensions.SKIP_EXTENSION_ID_LIST,
|
|
@@ -298,11 +313,18 @@ def initialize_mitm_server(config_file_path: str):
|
|
|
298
313
|
set_dns_gateway = True
|
|
299
314
|
|
|
300
315
|
if set_dns_gateway:
|
|
301
|
-
#
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
316
|
+
# Get current network interface state.
|
|
317
|
+
global NETWORK_INTERFACE_IS_DYNAMIC, NETWORK_INTERFACE_IPV4_ADDRESS_LIST
|
|
318
|
+
NETWORK_INTERFACE_IS_DYNAMIC, NETWORK_INTERFACE_IPV4_ADDRESS_LIST = dns.get_default_dns_gateway()
|
|
319
|
+
|
|
320
|
+
# Set the DNS gateway to the specified one only if the DNS gateway is dynamic or it is static but different
|
|
321
|
+
# from the one specified in the configuration file.
|
|
322
|
+
if (NETWORK_INTERFACE_IS_DYNAMIC or (not NETWORK_INTERFACE_IS_DYNAMIC and
|
|
323
|
+
NETWORK_INTERFACE_IPV4_ADDRESS_LIST != dns_gateway_server_list)):
|
|
324
|
+
dns.set_connection_dns_gateway_static(
|
|
325
|
+
dns_servers=dns_gateway_server_list,
|
|
326
|
+
use_default_connection=True
|
|
327
|
+
)
|
|
306
328
|
|
|
307
329
|
# General exception handler will catch all the exceptions that occurred in the threads and write it to the log.
|
|
308
330
|
# noinspection PyBroadException
|
|
@@ -319,13 +341,14 @@ def initialize_mitm_server(config_file_path: str):
|
|
|
319
341
|
socket_thread.start()
|
|
320
342
|
except Exception:
|
|
321
343
|
message = f"Unhandled Exception occurred in 'loop_for_incoming_sockets' function"
|
|
322
|
-
print_api(message, error_type=True, color="red", logger=network_logger, traceback_string=True
|
|
344
|
+
print_api(message, error_type=True, color="red", logger=network_logger, traceback_string=True)
|
|
323
345
|
|
|
324
346
|
# Compress recordings each day in a separate process.
|
|
325
347
|
recs_archiver_thread = threading.Thread(target=_loop_at_midnight_recs_archive)
|
|
326
348
|
recs_archiver_thread.daemon = True
|
|
327
349
|
recs_archiver_thread.start()
|
|
328
350
|
|
|
351
|
+
if config_static.DNSServer.enable or config_static.TCPServer.enable:
|
|
329
352
|
# This is needed for Keyboard Exception.
|
|
330
353
|
while True:
|
|
331
354
|
time.sleep(1)
|
|
@@ -338,7 +361,8 @@ def _loop_at_midnight_recs_archive():
|
|
|
338
361
|
current_date = datetime.datetime.now().strftime('%d')
|
|
339
362
|
# If it's midnight, start the archiving process.
|
|
340
363
|
if current_date != previous_date:
|
|
341
|
-
|
|
364
|
+
if config_static.LogRec.enable_request_response_recordings_in_logs:
|
|
365
|
+
recs_files.recs_archiver_in_process(config_static.LogRec.recordings_path)
|
|
342
366
|
# Update the previous date.
|
|
343
367
|
previous_date = current_date
|
|
344
368
|
# Sleep for 1 minute.
|
atomicshop/mitm/message.py
CHANGED
atomicshop/mitm/recs_files.py
CHANGED
atomicshop/ssh_remote.py
CHANGED
|
@@ -126,24 +126,24 @@ class SSHRemote:
|
|
|
126
126
|
except paramiko.ssh_exception.NoValidConnectionsError as e:
|
|
127
127
|
error = str(e)
|
|
128
128
|
# Logging the error also. Since the process name isn't critical, we'll continue script execution.
|
|
129
|
-
print_api(error, logger=self.logger, logger_method='error', traceback_string=True
|
|
129
|
+
print_api(error, logger=self.logger, logger_method='error', traceback_string=True)
|
|
130
130
|
pass
|
|
131
131
|
except paramiko.ssh_exception.SSHException as e:
|
|
132
132
|
error = str(e)
|
|
133
133
|
# Logging the error also. Since the process name isn't critical, we'll continue script execution.
|
|
134
|
-
print_api(error, logger=self.logger, logger_method='error', traceback_string=True
|
|
134
|
+
print_api(error, logger=self.logger, logger_method='error', traceback_string=True)
|
|
135
135
|
pass
|
|
136
136
|
except ConnectionResetError:
|
|
137
137
|
# Returning the error.
|
|
138
138
|
error = "An existing connection was forcibly closed by the remote host."
|
|
139
139
|
# Logging the error also. Since the process name isn't critical, we'll continue script execution.
|
|
140
|
-
print_api(error, logger=self.logger, logger_method='error', traceback_string=True
|
|
140
|
+
print_api(error, logger=self.logger, logger_method='error', traceback_string=True)
|
|
141
141
|
pass
|
|
142
142
|
except TimeoutError:
|
|
143
143
|
# Returning the error.
|
|
144
144
|
error = "Connection timed out."
|
|
145
145
|
# Logging the error also. Since the process name isn't critical, we'll continue script execution.
|
|
146
|
-
print_api(error, logger=self.logger, logger_method='error', traceback_string=True
|
|
146
|
+
print_api(error, logger=self.logger, logger_method='error', traceback_string=True)
|
|
147
147
|
pass
|
|
148
148
|
|
|
149
149
|
return error
|
|
@@ -165,24 +165,24 @@ class SSHRemote:
|
|
|
165
165
|
except AttributeError as function_exception_object:
|
|
166
166
|
if function_exception_object.name == "open_session":
|
|
167
167
|
result_exception = "'SSHRemote().connect' wasn't executed."
|
|
168
|
-
print_api(result_exception, logger=self.logger, logger_method='error', traceback_string=True
|
|
168
|
+
print_api(result_exception, logger=self.logger, logger_method='error', traceback_string=True)
|
|
169
169
|
|
|
170
170
|
# Since getting Process name is not the main feature of the server, we can pass the exception
|
|
171
171
|
pass
|
|
172
172
|
else:
|
|
173
173
|
result_exception = f"Couldn't execute script over SSH. Unknown yet exception with 'AttributeError' " \
|
|
174
174
|
f"and name: {function_exception_object.name}"
|
|
175
|
-
print_api(result_exception, logger=self.logger, logger_method='error', traceback_string=True
|
|
175
|
+
print_api(result_exception, logger=self.logger, logger_method='error', traceback_string=True)
|
|
176
176
|
# Since getting Process name is not the main feature of the server, we can pass the exception
|
|
177
177
|
pass
|
|
178
178
|
except socket.error:
|
|
179
179
|
result_exception = "Couldn't execute script over SSH. SSH socket closed."
|
|
180
|
-
print_api(result_exception, logger=self.logger, logger_method='error', traceback_string=True
|
|
180
|
+
print_api(result_exception, logger=self.logger, logger_method='error', traceback_string=True)
|
|
181
181
|
# Since getting Process name is not the main feature of the server, we can pass the exception
|
|
182
182
|
pass
|
|
183
183
|
except Exception:
|
|
184
184
|
result_exception = "Couldn't execute script over SSH. Unknown yet exception."
|
|
185
|
-
print_api(result_exception, logger=self.logger, logger_method='error', traceback_string=True
|
|
185
|
+
print_api(result_exception, logger=self.logger, logger_method='error', traceback_string=True)
|
|
186
186
|
# Since getting Process name is not the main feature of the server, we can pass the exception
|
|
187
187
|
pass
|
|
188
188
|
|
|
@@ -334,7 +334,7 @@ class SSHRemote:
|
|
|
334
334
|
# Basically we don't care much about SSH exceptions. Just log them and pass to record.
|
|
335
335
|
except Exception as function_exception_object:
|
|
336
336
|
execution_error = function_exception_object
|
|
337
|
-
print_api(execution_error, logger=self.logger, logger_method='error', traceback_string=True
|
|
337
|
+
print_api(execution_error, logger=self.logger, logger_method='error', traceback_string=True)
|
|
338
338
|
pass
|
|
339
339
|
|
|
340
340
|
# Closing SSH connection at this stage.
|
|
@@ -114,7 +114,11 @@ def call_method(
|
|
|
114
114
|
# Check if the method executed successfully.
|
|
115
115
|
for result in results:
|
|
116
116
|
if result != 0:
|
|
117
|
-
|
|
117
|
+
if result == 91:
|
|
118
|
+
raise PermissionError(f"Failed to execute method '{method_name}' with error code: {result}, "
|
|
119
|
+
f"Try with Admin rights.")
|
|
120
|
+
else:
|
|
121
|
+
raise WmiMethodExecutionError(f"Failed to execute method '{method_name}' with error code: {result}")
|
|
118
122
|
|
|
119
123
|
|
|
120
124
|
"""
|
|
@@ -133,35 +133,3 @@ def set_dns_server(
|
|
|
133
133
|
|
|
134
134
|
# Set DNS servers
|
|
135
135
|
helpers.call_method(adapter_config, 'SetDNSServerSearchOrder', dns_servers)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
def is_adapter_dns_gateway_from_dhcp(
|
|
139
|
-
use_default_interface: bool = False,
|
|
140
|
-
connection_name: str = None,
|
|
141
|
-
mac_address: str = None
|
|
142
|
-
) -> bool:
|
|
143
|
-
"""
|
|
144
|
-
Check if the adapter is set to obtain the DNS servers automatically from DHCP.
|
|
145
|
-
:param use_default_interface: bool, if True, the default network interface will be used.
|
|
146
|
-
This is the adapter that your internet is being used from.
|
|
147
|
-
:param connection_name: string, adapter name as shown in the network settings.
|
|
148
|
-
:param mac_address: string, MAC address of the adapter. Format: '00:00:00:00:00:00'.
|
|
149
|
-
:return: bool, True if DHCP is enabled, False otherwise.
|
|
150
|
-
"""
|
|
151
|
-
|
|
152
|
-
adapter_config, current_adapter = get_wmi_network_configuration(
|
|
153
|
-
use_default_interface=use_default_interface, connection_name=connection_name, mac_address=mac_address)
|
|
154
|
-
|
|
155
|
-
# If DHCP is not enabled.
|
|
156
|
-
if not adapter_config.DHCPEnabled:
|
|
157
|
-
# Then it is obvious that DNS Gateway is also Statis.
|
|
158
|
-
return False
|
|
159
|
-
# If DHCP is enabled.
|
|
160
|
-
else:
|
|
161
|
-
# Then we need to check if Default IP gateway is the same as DNS Gateway, if so.
|
|
162
|
-
if adapter_config.DefaultIPGateway == adapter_config.DNSServerSearchOrder:
|
|
163
|
-
# Then it is set dynamically from DHCP.
|
|
164
|
-
return True
|
|
165
|
-
else:
|
|
166
|
-
# If not, so it is static.
|
|
167
|
-
return False
|
|
@@ -230,17 +230,16 @@ class DnsServer:
|
|
|
230
230
|
# This error happens when the client closes the connection before the server.
|
|
231
231
|
# This is not an error for a DNS Server, but we'll log it anyway only with the full DNS logger.
|
|
232
232
|
message = "Error: to receive DNS request, An existing connection was forcibly closed"
|
|
233
|
-
# print_api(message, logger=self.logger, logger_method='error', traceback_string=True
|
|
233
|
+
# print_api(message, logger=self.logger, logger_method='error', traceback_string=True)
|
|
234
234
|
print_api(
|
|
235
|
-
message, logger=self.dns_full_logger, logger_method='error', traceback_string=True
|
|
236
|
-
oneline=True)
|
|
235
|
+
message, logger=self.dns_full_logger, logger_method='error', traceback_string=True)
|
|
237
236
|
self.dns_full_logger.info("==========")
|
|
238
237
|
pass
|
|
239
238
|
continue
|
|
240
239
|
except Exception:
|
|
241
240
|
message = "Unknown Exception: to receive DNS request"
|
|
242
241
|
print_api(
|
|
243
|
-
message, logger=self.logger, logger_method='critical', traceback_string=True
|
|
242
|
+
message, logger=self.logger, logger_method='critical', traceback_string=True)
|
|
244
243
|
self.logger.info("==========")
|
|
245
244
|
pass
|
|
246
245
|
continue
|
|
@@ -417,9 +416,9 @@ class DnsServer:
|
|
|
417
416
|
except ValueError:
|
|
418
417
|
message = f"Looks like wrong type of response for QTYPE: {qtype_string}. Response: "
|
|
419
418
|
print_api(message, logger=self.logger, logger_method='critical',
|
|
420
|
-
traceback_string=True
|
|
419
|
+
traceback_string=True)
|
|
421
420
|
print_api(f"{dns_built_response}", logger=self.logger, logger_method='critical',
|
|
422
|
-
traceback_string=True
|
|
421
|
+
traceback_string=True)
|
|
423
422
|
# Pass the exception.
|
|
424
423
|
pass
|
|
425
424
|
# Continue to the next DNS request, since there's nothing to do here right now.
|
|
@@ -430,9 +429,9 @@ class DnsServer:
|
|
|
430
429
|
(f"Unknown exception while creating response for QTYPE: {qtype_string}. "
|
|
431
430
|
f"Response: ")
|
|
432
431
|
print_api(message, logger=self.logger, logger_method='critical',
|
|
433
|
-
traceback_string=True
|
|
432
|
+
traceback_string=True)
|
|
434
433
|
print_api(f"{dns_built_response}", logger=self.logger, logger_method='critical',
|
|
435
|
-
traceback_string=True
|
|
434
|
+
traceback_string=True)
|
|
436
435
|
# Pass the exception.
|
|
437
436
|
pass
|
|
438
437
|
# Continue to the next DNS request, since there's nothing to do here right now.
|
|
@@ -479,7 +478,7 @@ class DnsServer:
|
|
|
479
478
|
google_dns_ipv4_socket.recvfrom(self.buffer_size_receive)
|
|
480
479
|
except TimeoutError as function_exception_object:
|
|
481
480
|
print_api(function_exception_object, logger=self.logger, logger_method='error',
|
|
482
|
-
traceback_string=True
|
|
481
|
+
traceback_string=True)
|
|
483
482
|
google_dns_ipv4_socket.close()
|
|
484
483
|
counter += 1
|
|
485
484
|
# Pass the exception.
|
|
@@ -725,7 +724,7 @@ class DnsServer:
|
|
|
725
724
|
except Exception:
|
|
726
725
|
message = "Unknown Exception: to parse DNS request"
|
|
727
726
|
print_api(
|
|
728
|
-
message, logger=self.logger, logger_method='critical', traceback_string=True
|
|
727
|
+
message, logger=self.logger, logger_method='critical', traceback_string=True)
|
|
729
728
|
self.logger.info("==========")
|
|
730
729
|
pass
|
|
731
730
|
continue
|
|
@@ -27,14 +27,12 @@ def connection_exception_decorator(function_name):
|
|
|
27
27
|
message = f"Socket Accept: {kwargs['domain_from_dns_server']}:{port}: " \
|
|
28
28
|
f"* Established connection was aborted by software on the host..."
|
|
29
29
|
wrapper_handle_connection_exceptions.message = message
|
|
30
|
-
print_api(message, logger_method='error', traceback_string=True, **kwargs['print_kwargs'])
|
|
31
|
-
pass
|
|
30
|
+
print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
|
|
32
31
|
except ConnectionResetError:
|
|
33
32
|
message = f"Socket Accept: {kwargs['domain_from_dns_server']}:{port}: " \
|
|
34
33
|
f"* An existing connection was forcibly closed by the remote host..."
|
|
35
34
|
wrapper_handle_connection_exceptions.message = message
|
|
36
35
|
print_api(message, logger_method='error', traceback_string=True, oneline=True, **kwargs['print_kwargs'])
|
|
37
|
-
pass
|
|
38
36
|
except ssl.SSLEOFError as e:
|
|
39
37
|
# A subclass of SSLError raised when the SSL connection has been terminated abruptly. Generally, you
|
|
40
38
|
# shouldn't try to reuse the underlying transport when this error is encountered.
|
|
@@ -47,7 +45,7 @@ def connection_exception_decorator(function_name):
|
|
|
47
45
|
message = \
|
|
48
46
|
f"Socket Accept: {kwargs['domain_from_dns_server']}:{port}: {message}"
|
|
49
47
|
wrapper_handle_connection_exceptions.message = message
|
|
50
|
-
print_api(message, error_type=True, logger_method='error', **kwargs['print_kwargs'])
|
|
48
|
+
print_api(message, error_type=True, logger_method='error', oneline=True, **kwargs['print_kwargs'])
|
|
51
49
|
except Exception:
|
|
52
50
|
message = f"Socket Accept: port {port}: {message}"
|
|
53
51
|
wrapper_handle_connection_exceptions.message = message
|
|
@@ -61,7 +59,7 @@ def connection_exception_decorator(function_name):
|
|
|
61
59
|
message = \
|
|
62
60
|
f"Socket Accept: {kwargs['domain_from_dns_server']}:{port}: {message}"
|
|
63
61
|
wrapper_handle_connection_exceptions.message = message
|
|
64
|
-
print_api(message, logger_method='error', **kwargs['print_kwargs'])
|
|
62
|
+
print_api(message, logger_method='error', oneline=True, **kwargs['print_kwargs'])
|
|
65
63
|
except Exception:
|
|
66
64
|
message = f"Socket Accept: port {port}: {message}"
|
|
67
65
|
wrapper_handle_connection_exceptions.message = message
|
|
@@ -88,14 +86,14 @@ def connection_exception_decorator(function_name):
|
|
|
88
86
|
|
|
89
87
|
message = "SSLError on accept. Not documented..."
|
|
90
88
|
wrapper_handle_connection_exceptions.message = message
|
|
91
|
-
print_api(message, logger_method='error', **kwargs['print_kwargs'])
|
|
89
|
+
print_api(message, logger_method='error', oneline=True, **kwargs['print_kwargs'])
|
|
92
90
|
|
|
93
91
|
message = f'ssl.SSLError:{exception_object}'
|
|
94
92
|
wrapper_handle_connection_exceptions.message = message
|
|
95
93
|
message = \
|
|
96
94
|
f"Socket Accept: {kwargs['domain_from_dns_server']}:{port}: {message}"
|
|
97
95
|
wrapper_handle_connection_exceptions.message = message
|
|
98
|
-
print_api(message, logger_method='error', **kwargs['print_kwargs'])
|
|
96
|
+
print_api(message, logger_method='error', oneline=True, **kwargs['print_kwargs'])
|
|
99
97
|
pass
|
|
100
98
|
except FileNotFoundError:
|
|
101
99
|
message = "'SSLSocket.accept()' crashed: 'FileNotFoundError'. Some problem with SSL during Handshake - " \
|
|
@@ -67,20 +67,20 @@ class GetCommandLine:
|
|
|
67
67
|
except ModuleNotFoundError as function_exception_object:
|
|
68
68
|
execution_error = f"Module not installed: {function_exception_object}"
|
|
69
69
|
print_api(
|
|
70
|
-
execution_error, error_type=True, logger_method="error", traceback_string=True,
|
|
70
|
+
execution_error, error_type=True, logger_method="error", traceback_string=True,
|
|
71
71
|
**print_kwargs)
|
|
72
72
|
pass
|
|
73
73
|
except psutil.AccessDenied:
|
|
74
74
|
execution_error = f"Access Denied for 'psutil' to read system process command line. " \
|
|
75
75
|
f"Run script with Admin Rights."
|
|
76
76
|
print_api(
|
|
77
|
-
execution_error, error_type=True, logger_method="error", traceback_string=True,
|
|
77
|
+
execution_error, error_type=True, logger_method="error", traceback_string=True,
|
|
78
78
|
**print_kwargs)
|
|
79
79
|
pass
|
|
80
80
|
except Exception:
|
|
81
81
|
execution_error = "There was undocumented exception in localhost script execution."
|
|
82
82
|
print_api(
|
|
83
|
-
execution_error, error_type=True, logger_method="error", traceback_string=True,
|
|
83
|
+
execution_error, error_type=True, logger_method="error", traceback_string=True,
|
|
84
84
|
**print_kwargs)
|
|
85
85
|
pass
|
|
86
86
|
|
|
@@ -49,17 +49,17 @@ class Receiver:
|
|
|
49
49
|
class_data = self.ssl_socket.recv(self.buffer_size_receive)
|
|
50
50
|
except ConnectionAbortedError:
|
|
51
51
|
message = "* Connection was aborted by the client. Exiting..."
|
|
52
|
-
print_api(message, logger=self.logger, logger_method='critical', traceback_string=True
|
|
52
|
+
print_api(message, logger=self.logger, logger_method='critical', traceback_string=True)
|
|
53
53
|
# This will be treated as empty message - indicate that socket was closed and will be handled properly.
|
|
54
54
|
pass
|
|
55
55
|
except ConnectionResetError:
|
|
56
56
|
message = "* Connection was forcibly closed by the client. Exiting..."
|
|
57
|
-
print_api(message, logger=self.logger, logger_method='critical', traceback_string=True
|
|
57
|
+
print_api(message, logger=self.logger, logger_method='critical', traceback_string=True)
|
|
58
58
|
# This will be treated as empty message - indicate that socket was closed and will be handled properly.
|
|
59
59
|
pass
|
|
60
60
|
except ssl.SSLError:
|
|
61
61
|
message = "* Encountered SSL error on packet receive. Exiting..."
|
|
62
|
-
print_api(message, logger=self.logger, logger_method='critical', traceback_string=True
|
|
62
|
+
print_api(message, logger=self.logger, logger_method='critical', traceback_string=True)
|
|
63
63
|
# This will be treated as empty message - indicate that socket was closed and will be handled properly.
|
|
64
64
|
pass
|
|
65
65
|
|
|
@@ -50,7 +50,7 @@ class Sender:
|
|
|
50
50
|
self.logger.info(f"Sent the message to destination.")
|
|
51
51
|
except ConnectionResetError:
|
|
52
52
|
message = "* Couldn't reach the server - Connection was reset. Exiting..."
|
|
53
|
-
print_api(message, logger=self.logger, logger_method='critical', traceback_string=True
|
|
53
|
+
print_api(message, logger=self.logger, logger_method='critical', traceback_string=True)
|
|
54
54
|
# Since the connection is down, it will be handled in thread_worker_main
|
|
55
55
|
function_result = False
|
|
56
56
|
pass
|
|
@@ -267,7 +267,7 @@ class SNIHandler:
|
|
|
267
267
|
print_api(message, **(print_kwargs or {}))
|
|
268
268
|
except Exception as exception_object:
|
|
269
269
|
message = f"SNI Handler: Undocumented exception general settings section: {exception_object}"
|
|
270
|
-
print_api(message, error_type=True, logger_method="error", traceback_string=True,
|
|
270
|
+
print_api(message, error_type=True, logger_method="error", traceback_string=True,
|
|
271
271
|
**(print_kwargs or {}))
|
|
272
272
|
pass
|
|
273
273
|
|
|
File without changes
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import winreg
|
|
2
|
+
import socket
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def get_network_interfaces_settings(
|
|
6
|
+
interface_guid: str = None
|
|
7
|
+
) -> dict:
|
|
8
|
+
"""
|
|
9
|
+
Get network interface settings from the Windows registry.
|
|
10
|
+
|
|
11
|
+
:param interface_guid: str, GUID of the network interface to retrieve settings for.
|
|
12
|
+
If None, settings for all interfaces will be retrieved.
|
|
13
|
+
:return: dict, network interface settings.
|
|
14
|
+
"""
|
|
15
|
+
registry_path = r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces"
|
|
16
|
+
network_info = {}
|
|
17
|
+
|
|
18
|
+
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, registry_path) as interfaces_key:
|
|
19
|
+
interface_count = winreg.QueryInfoKey(interfaces_key)[0]
|
|
20
|
+
|
|
21
|
+
for i in range(interface_count):
|
|
22
|
+
current_interface_guid = winreg.EnumKey(interfaces_key, i)
|
|
23
|
+
|
|
24
|
+
# If an interface GUID is provided, and it doesn't match the current one, skip it
|
|
25
|
+
if interface_guid and interface_guid != current_interface_guid:
|
|
26
|
+
continue
|
|
27
|
+
|
|
28
|
+
interface_path = f"{registry_path}\\{current_interface_guid}"
|
|
29
|
+
interface_data = {}
|
|
30
|
+
|
|
31
|
+
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, interface_path) as key:
|
|
32
|
+
value_count = winreg.QueryInfoKey(key)[1]
|
|
33
|
+
|
|
34
|
+
for j in range(value_count):
|
|
35
|
+
value_name, value_data, _ = winreg.EnumValue(key, j)
|
|
36
|
+
interface_data[value_name] = value_data
|
|
37
|
+
|
|
38
|
+
# Populate the dictionary for the current interface
|
|
39
|
+
network_info[current_interface_guid] = interface_data
|
|
40
|
+
|
|
41
|
+
return network_info
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def get_network_connections_to_guids() -> dict:
|
|
45
|
+
"""
|
|
46
|
+
Get a dictionary mapping network connection names to their corresponding GUIDs.
|
|
47
|
+
|
|
48
|
+
:return: dict, GUIDs to connection names.
|
|
49
|
+
"""
|
|
50
|
+
adapters = {}
|
|
51
|
+
registry_path = r"SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}"
|
|
52
|
+
|
|
53
|
+
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, registry_path) as network_key:
|
|
54
|
+
adapter_count = winreg.QueryInfoKey(network_key)[0]
|
|
55
|
+
|
|
56
|
+
for i in range(adapter_count):
|
|
57
|
+
adapter_guid = winreg.EnumKey(network_key, i)
|
|
58
|
+
adapter_path = f"{registry_path}\\{adapter_guid}\\Connection"
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, adapter_path) as connection_key:
|
|
62
|
+
adapter_name, _ = winreg.QueryValueEx(connection_key, "Name")
|
|
63
|
+
adapters[adapter_guid] = adapter_name
|
|
64
|
+
except FileNotFoundError:
|
|
65
|
+
# Some GUIDs might not have a corresponding 'Connection' key, so we skip them
|
|
66
|
+
continue
|
|
67
|
+
|
|
68
|
+
return adapters
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def get_enum_info_by_pnpinstanceid(
|
|
72
|
+
pnp_instance_id: str
|
|
73
|
+
) -> dict:
|
|
74
|
+
"""
|
|
75
|
+
Get all information from the Enum registry key for a device with a specific PnPInstanceId.
|
|
76
|
+
|
|
77
|
+
:param pnp_instance_id: str, PnPInstanceId of the device.
|
|
78
|
+
:return: dict, device information.
|
|
79
|
+
"""
|
|
80
|
+
enum_registry_path = r"SYSTEM\CurrentControlSet\Enum"
|
|
81
|
+
device_info = {}
|
|
82
|
+
|
|
83
|
+
# Construct the full path to the device in the Enum registry
|
|
84
|
+
hardware_path = f"{enum_registry_path}\\{pnp_instance_id}"
|
|
85
|
+
|
|
86
|
+
# Open the registry key corresponding to the device
|
|
87
|
+
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, hardware_path) as hardware_key:
|
|
88
|
+
num_values = winreg.QueryInfoKey(hardware_key)[1]
|
|
89
|
+
|
|
90
|
+
# Retrieve all values under this key
|
|
91
|
+
for i in range(num_values):
|
|
92
|
+
value_name, value_data, _ = winreg.EnumValue(hardware_key, i)
|
|
93
|
+
device_info[value_name] = value_data
|
|
94
|
+
|
|
95
|
+
return device_info
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def get_network_connections_details(get_enum_info: bool = True) -> dict:
|
|
99
|
+
"""
|
|
100
|
+
Get network adapter details from the Windows registry.
|
|
101
|
+
|
|
102
|
+
:param get_enum_info: bool, if True, retrieve all information from the corresponding Enum key.
|
|
103
|
+
This is useful for getting additional information about the network adapter, like make, model, diver details.
|
|
104
|
+
:return: dict, network adapter details.
|
|
105
|
+
"""
|
|
106
|
+
adapter_details = {}
|
|
107
|
+
network_registry_path = r"SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}"
|
|
108
|
+
|
|
109
|
+
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, network_registry_path) as network_key:
|
|
110
|
+
adapter_count = winreg.QueryInfoKey(network_key)[0]
|
|
111
|
+
|
|
112
|
+
for i in range(adapter_count):
|
|
113
|
+
adapter_guid = winreg.EnumKey(network_key, i)
|
|
114
|
+
adapter_path = f"{network_registry_path}\\{adapter_guid}\\Connection"
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, adapter_path) as connection_key:
|
|
118
|
+
adapter_name, _ = winreg.QueryValueEx(connection_key, "Name")
|
|
119
|
+
pnp_instance_id, _ = winreg.QueryValueEx(connection_key, "PnPInstanceId")
|
|
120
|
+
|
|
121
|
+
# Get all information from the corresponding Enum key
|
|
122
|
+
if get_enum_info:
|
|
123
|
+
enum_info: dict = get_enum_info_by_pnpinstanceid(pnp_instance_id)
|
|
124
|
+
else:
|
|
125
|
+
enum_info: dict = {}
|
|
126
|
+
|
|
127
|
+
# Store the retrieved information
|
|
128
|
+
adapter_details[adapter_guid] = {
|
|
129
|
+
"Name": adapter_name,
|
|
130
|
+
"PnPInstanceId": pnp_instance_id,
|
|
131
|
+
"EnumInfo": enum_info
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
except FileNotFoundError:
|
|
135
|
+
continue
|
|
136
|
+
|
|
137
|
+
return adapter_details
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def get_default_dns_gateway() -> tuple[bool, list[str]]:
|
|
141
|
+
"""
|
|
142
|
+
Get the default DNS gateway from the Windows registry.
|
|
143
|
+
|
|
144
|
+
:return: tuple(is dynamic boolean, list of DNS server IPv4s).
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
# Get current default IPv4 address of the interface that is being used for internet.
|
|
148
|
+
default_ipv4_address: str = socket.gethostbyname(socket.gethostname())
|
|
149
|
+
|
|
150
|
+
# Get all network interface settings from the registry.
|
|
151
|
+
all_interfaces_configurations = get_network_interfaces_settings()
|
|
152
|
+
|
|
153
|
+
# Find the interface that has this IPv4 assigned.
|
|
154
|
+
function_result: tuple = tuple()
|
|
155
|
+
for interface_guid, interface_settings in all_interfaces_configurations.items():
|
|
156
|
+
current_interface_static_ipv4_address: list = interface_settings.get('IPAddress', None)
|
|
157
|
+
current_interface_dynamic_ipv4_address: str = interface_settings.get('DhcpIPAddress', None)
|
|
158
|
+
|
|
159
|
+
static_and_ip_match: bool = (
|
|
160
|
+
current_interface_static_ipv4_address and
|
|
161
|
+
current_interface_static_ipv4_address[0] == default_ipv4_address)
|
|
162
|
+
dynamic_and_ip_match: bool = (
|
|
163
|
+
current_interface_dynamic_ipv4_address and
|
|
164
|
+
current_interface_dynamic_ipv4_address == default_ipv4_address)
|
|
165
|
+
if static_and_ip_match or dynamic_and_ip_match:
|
|
166
|
+
if interface_settings['NameServer']:
|
|
167
|
+
function_result = (False, interface_settings['NameServer'].split(' '))
|
|
168
|
+
else:
|
|
169
|
+
function_result = (True, interface_settings['DhcpNameServer'].split(' '))
|
|
170
|
+
|
|
171
|
+
break
|
|
172
|
+
|
|
173
|
+
# noinspection PyTypeChecker
|
|
174
|
+
return function_result
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
atomicshop/__init__.py,sha256=
|
|
1
|
+
atomicshop/__init__.py,sha256=x-01pyB2pWZ28cjWHPctucw-rKzH4SbGkVDLBeV4ww8,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
|
|
@@ -10,7 +10,7 @@ atomicshop/console_output.py,sha256=AOSJjrRryE97PAGtgDL03IBtWSi02aNol8noDnW3k6M,
|
|
|
10
10
|
atomicshop/console_user_response.py,sha256=31HIy9QGXa7f-GVR8MzJauQ79E_ZqAeagF3Ks4GGdDU,3234
|
|
11
11
|
atomicshop/datetimes.py,sha256=IQZ66lmta-ZqxYbyHzm_9eugbJFSilXK1e0kfMgoXGg,18371
|
|
12
12
|
atomicshop/diff_check.py,sha256=Q9RCqRa-jEgo7Fujx08_JTuZ6qcgttMI6aNYB6zN9Ik,27173
|
|
13
|
-
atomicshop/dns.py,sha256=
|
|
13
|
+
atomicshop/dns.py,sha256=J4yX6vCaRdL0McYWnlJ9arCDKW-yRui7Y5WyL5BoD6M,6391
|
|
14
14
|
atomicshop/domains.py,sha256=Rxu6JhhMqFZRcoFs69IoEd1PtYca0lMCG6F1AomP7z4,3197
|
|
15
15
|
atomicshop/emails.py,sha256=I0KyODQpIMEsNRi9YWSOL8EUPBiWyon3HRdIuSj3AEU,1410
|
|
16
16
|
atomicshop/file_types.py,sha256=-0jzQMRlmU1AP9DARjk-HJm1tVE22E6ngP2mRblyEjY,763
|
|
@@ -35,7 +35,7 @@ atomicshop/scheduling.py,sha256=MvF20M6uU0Kh_CQn2ERxMTLvvF-ToBrdMhXNrKxYFj8,4682
|
|
|
35
35
|
atomicshop/script_as_string_processor.py,sha256=uAIWwhHE-eP2FniuwBqEiM6VzyQX96uwdE3aA31rIm8,1883
|
|
36
36
|
atomicshop/sound.py,sha256=tHiQQbFBk7EYN3pAfGNcxfF9oNsoYnZgu9z9iq8hxQE,24352
|
|
37
37
|
atomicshop/speech_recognize.py,sha256=55-dIjgkpF93mvJnJuxSFuft5H5eRvGNlUj9BeIOZxk,5903
|
|
38
|
-
atomicshop/ssh_remote.py,sha256=
|
|
38
|
+
atomicshop/ssh_remote.py,sha256=HUP4FHaEHexI0EnoLI9i2AgVQNTpsMNPNC4ZCI22EAA,17029
|
|
39
39
|
atomicshop/sys_functions.py,sha256=MTBxRve5bh58SPvhX3gMiGqHlSBuI_rdNN1NnnBBWqI,906
|
|
40
40
|
atomicshop/system_resource_monitor.py,sha256=WvnnQrD5W9NRqOWI2YNcL-ut2UrvhrYToVlRR2c1vs8,13720
|
|
41
41
|
atomicshop/system_resources.py,sha256=0mhDZBEcMzToCOw5ArJhtqYjktOW6iJGdyRkJ01Cpwk,9272
|
|
@@ -115,29 +115,29 @@ atomicshop/etws/traces/trace_sysmon_process_creation.py,sha256=OM-bkK38uYMwWLZKN
|
|
|
115
115
|
atomicshop/file_io/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
116
116
|
atomicshop/file_io/csvs.py,sha256=oZiaIEd1q50ypNdd9mlHWb-f7HAdGa_D6jLd3T_4sWU,8777
|
|
117
117
|
atomicshop/file_io/docxs.py,sha256=rZnv2VMOvct6KBSQn-bHhwbKOi8886jB5u387flq-0E,5755
|
|
118
|
-
atomicshop/file_io/file_io.py,sha256=
|
|
118
|
+
atomicshop/file_io/file_io.py,sha256=fkOgoeS8Ow69rj6KfEDmnMeFT3FhJmOJ0X-C_7Udiik,7047
|
|
119
119
|
atomicshop/file_io/jsons.py,sha256=q9ZU8slBKnHLrtn3TnbK1qxrRpj5ZvCm6AlsFzoANjo,5303
|
|
120
120
|
atomicshop/file_io/tomls.py,sha256=ol8EvQPf9sryTmZUf1v55BYSUQ6ml7HVVBHpNKbsIlA,9768
|
|
121
121
|
atomicshop/file_io/xlsxs.py,sha256=v_dyg9GD4LqgWi6wA1QuWRZ8zG4ZwB6Dz52ytdcmmmI,2184
|
|
122
122
|
atomicshop/file_io/xmls.py,sha256=zh3SuK-dNaFq2NDNhx6ivcf4GYCfGM8M10PcEwDSpxk,2104
|
|
123
123
|
atomicshop/mitm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
124
|
-
atomicshop/mitm/config_static.py,sha256=
|
|
124
|
+
atomicshop/mitm/config_static.py,sha256=uDuzGl4M96WYJv6WWiQ89speJSCmXzNKwMKcKdaP6ME,7105
|
|
125
125
|
atomicshop/mitm/config_toml_editor.py,sha256=2p1CMcktWRR_NW-SmyDwylu63ad5e0-w1QPMa8ZLDBw,1635
|
|
126
|
-
atomicshop/mitm/connection_thread_worker.py,sha256=
|
|
127
|
-
atomicshop/mitm/import_config.py,sha256=
|
|
126
|
+
atomicshop/mitm/connection_thread_worker.py,sha256=1MBpRoLpzWJMvxqQKizo6IVQ4XYsbKGsjxianNQLUlE,20051
|
|
127
|
+
atomicshop/mitm/import_config.py,sha256=5peDr6cT0ZWK3J53yG-VEew77CKrvB88CphM10SQd3I,7868
|
|
128
128
|
atomicshop/mitm/initialize_engines.py,sha256=YoSNksMdu4vHjr5xy77t9t5W74zyDZIdjIXrzd3eRXc,8204
|
|
129
|
-
atomicshop/mitm/initialize_mitm_server.py,sha256=
|
|
130
|
-
atomicshop/mitm/message.py,sha256=
|
|
131
|
-
atomicshop/mitm/recs_files.py,sha256=
|
|
129
|
+
atomicshop/mitm/initialize_mitm_server.py,sha256=oSmL-MspKZY_5s-RDlTZ7-v4gIK_L-6Jyus3R1YeTe8,20665
|
|
130
|
+
atomicshop/mitm/message.py,sha256=d_sm3O_aoZf87dDQP44xOMNEG-uZBN1ZecQgMCacbZs,1814
|
|
131
|
+
atomicshop/mitm/recs_files.py,sha256=lVe-H9IOxm8QShW1-KHlSSHINqRN7pHu3bVxgg5NsTw,2927
|
|
132
132
|
atomicshop/mitm/shared_functions.py,sha256=hplm98tz8pgJ4WHUVI9sf_oVqUM2KJ1Y2pD6EFSb8P0,1879
|
|
133
133
|
atomicshop/mitm/statistic_analyzer.py,sha256=E0ba1PjsUEcmQUPPw2YH911lyWkbQb9OSAdgB3pihsY,24658
|
|
134
134
|
atomicshop/mitm/engines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
135
135
|
atomicshop/mitm/engines/create_module_template.py,sha256=tRjVSm1sD6FzML71Qbuwvita0qsusdFGm8NZLsZ-XMs,4853
|
|
136
136
|
atomicshop/mitm/engines/create_module_template_example.py,sha256=X5xhvbV6-g9jU_bQVhf_crZmaH50LRWz3bS-faQ18ds,489
|
|
137
137
|
atomicshop/mitm/engines/__parent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
138
|
-
atomicshop/mitm/engines/__parent/parser___parent.py,sha256=
|
|
139
|
-
atomicshop/mitm/engines/__parent/recorder___parent.py,sha256=
|
|
140
|
-
atomicshop/mitm/engines/__parent/responder___parent.py,sha256=
|
|
138
|
+
atomicshop/mitm/engines/__parent/parser___parent.py,sha256=Q1hEhbOXa8oBm9uD1VG2hLRCzUzpMjGeeS2Npd0a4Hw,1336
|
|
139
|
+
atomicshop/mitm/engines/__parent/recorder___parent.py,sha256=G1TNVxUKFfRopUgENcLCQS0XGzNJmKYBep70wWHvPAQ,4650
|
|
140
|
+
atomicshop/mitm/engines/__parent/responder___parent.py,sha256=gufSZP2Pic6iF7eTzbIi0z5-TPIDeIgoRQAplUwtcNk,12185
|
|
141
141
|
atomicshop/mitm/engines/__reference_general/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
142
142
|
atomicshop/mitm/engines/__reference_general/parser___reference_general.py,sha256=QolWZKm8SiPxxSoyWY_UK7ODam7EUMAgVfOPFnXxODE,2987
|
|
143
143
|
atomicshop/mitm/engines/__reference_general/recorder___reference_general.py,sha256=KENDVf9OwXD9gwSh4B1XxACCe7iHYjrvnW1t6F64wdE,695
|
|
@@ -286,27 +286,29 @@ atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_create.py,sha256=1
|
|
|
286
286
|
atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_terminate.py,sha256=0k09fiAwKDJO404bjxUWSSSLOiNANl-VTJDD_YLq-I8,3763
|
|
287
287
|
atomicshop/wrappers/pywin32w/win_event_log/subscribes/schannel_logging.py,sha256=8nxIcNcbeEuvoBwhujgh7-oIpL9A6J-gg1NM8hOGAVA,3442
|
|
288
288
|
atomicshop/wrappers/pywin32w/wmis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
289
|
-
atomicshop/wrappers/pywin32w/wmis/helpers.py,sha256=
|
|
290
|
-
atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py,sha256=
|
|
289
|
+
atomicshop/wrappers/pywin32w/wmis/helpers.py,sha256=uMXa27UfBpqXInvnmk7CZlqwRI2pg_I_HXelxO9nLLg,5020
|
|
290
|
+
atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py,sha256=9H9MdS__GDBMm8H-xINEPFrJ8j-ErIb1ZqzkulTwLTo,5443
|
|
291
291
|
atomicshop/wrappers/pywin32w/wmis/win32process.py,sha256=qMzXtJ5hBZ5ydAyqpDbSx0nO2RJQL95HdmV5SzNKMhk,6826
|
|
292
292
|
atomicshop/wrappers/socketw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
293
293
|
atomicshop/wrappers/socketw/accepter.py,sha256=hZZKVYlF3LOHQJsSIEKXZUf6QXXWm-AtqXZevvaYigE,1732
|
|
294
294
|
atomicshop/wrappers/socketw/base.py,sha256=evoOIxg5Xff3THJnrVX00D5HobaOpDp6_e_gso7TJmA,2191
|
|
295
295
|
atomicshop/wrappers/socketw/certificator.py,sha256=3CpQKtcW68FSbH6LVSEZTqWBS6Yg_-3K0x4nFkId4UY,12236
|
|
296
296
|
atomicshop/wrappers/socketw/creator.py,sha256=3_OraDkw2DAWZfoSdY3svCGMOIxpjLEEY7NxWd7M5P4,9873
|
|
297
|
-
atomicshop/wrappers/socketw/dns_server.py,sha256=
|
|
298
|
-
atomicshop/wrappers/socketw/exception_wrapper.py,sha256=
|
|
299
|
-
atomicshop/wrappers/socketw/get_process.py,sha256=
|
|
300
|
-
atomicshop/wrappers/socketw/receiver.py,sha256=
|
|
301
|
-
atomicshop/wrappers/socketw/sender.py,sha256=
|
|
302
|
-
atomicshop/wrappers/socketw/sni.py,sha256=
|
|
297
|
+
atomicshop/wrappers/socketw/dns_server.py,sha256=VIpz6cluQ53nZ14QGhnXU9zJqlcOa5fEZsHeKJWr9ec,45127
|
|
298
|
+
atomicshop/wrappers/socketw/exception_wrapper.py,sha256=B-X5SHLSUIWToihH2MKnOB1F4A81_X0DpLLfnYKYbEc,7067
|
|
299
|
+
atomicshop/wrappers/socketw/get_process.py,sha256=_YMVxYhVlzjJpeOR36tphZ5QWeKYwk03Ilw0muCxDbg,5950
|
|
300
|
+
atomicshop/wrappers/socketw/receiver.py,sha256=G3hDTacm7nwwUNHEbKZpxO0c8rHcl0NeKpZy7Xc6zpA,9008
|
|
301
|
+
atomicshop/wrappers/socketw/sender.py,sha256=d7YQFlCBMFTYtkGxbS-8cm5rh5WWFeBVvrEivWHYstI,3666
|
|
302
|
+
atomicshop/wrappers/socketw/sni.py,sha256=fVwyh3h9IqfLMnf4__bMIzcF4c-Kk9mlbDWMRXKN-ow,17155
|
|
303
303
|
atomicshop/wrappers/socketw/socket_client.py,sha256=FNmTt94YvjZP0X4RPb7icO3xD_nBHQ_XynnObdWFiAU,19682
|
|
304
304
|
atomicshop/wrappers/socketw/socket_server_tester.py,sha256=SdchUf9qrPk1Rrat0RzvMeN_2NioD7b7a97MkToCYgM,6332
|
|
305
305
|
atomicshop/wrappers/socketw/socket_wrapper.py,sha256=g7f_8RkW80EZeQWNTqGYnfrQkgAI56T3SwWybq7ZsXg,28521
|
|
306
306
|
atomicshop/wrappers/socketw/ssl_base.py,sha256=k4V3gwkbq10MvOH4btU4onLX2GNOsSfUAdcHmL1rpVE,2274
|
|
307
307
|
atomicshop/wrappers/socketw/statistics_csv.py,sha256=Jc0D12crkKRaqoCRQ-2Mz1zm6n4UUx9dXakf-N2TYWA,3065
|
|
308
|
-
atomicshop
|
|
309
|
-
atomicshop
|
|
310
|
-
atomicshop-2.16.
|
|
311
|
-
atomicshop-2.16.
|
|
312
|
-
atomicshop-2.16.
|
|
308
|
+
atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
309
|
+
atomicshop/wrappers/winregw/winreg_network.py,sha256=bQ8Jql8bVGBJ0dt3VQ56lga_1LBOMLI3Km_otvvbU6c,7138
|
|
310
|
+
atomicshop-2.16.11.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
|
|
311
|
+
atomicshop-2.16.11.dist-info/METADATA,sha256=zixHONTS2uk6ixSrH4AIvVi7_E9uCZ_0aqYDrzwlgyc,10503
|
|
312
|
+
atomicshop-2.16.11.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
313
|
+
atomicshop-2.16.11.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
|
|
314
|
+
atomicshop-2.16.11.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|