atomicshop 3.3.28__py3-none-any.whl → 3.10.0__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/a_mains/get_local_tcp_ports.py +85 -0
- atomicshop/a_mains/install_ca_certificate.py +172 -0
- atomicshop/a_mains/process_from_port.py +119 -0
- atomicshop/a_mains/set_default_dns_gateway.py +90 -0
- atomicshop/basics/strings.py +1 -1
- atomicshop/certificates.py +2 -2
- atomicshop/dns.py +26 -28
- atomicshop/etws/traces/trace_tcp.py +1 -2
- atomicshop/mitm/centered_settings.py +133 -0
- atomicshop/mitm/config_static.py +18 -43
- atomicshop/mitm/connection_thread_worker.py +376 -162
- atomicshop/mitm/engines/__parent/recorder___parent.py +1 -1
- atomicshop/mitm/engines/__parent/requester___parent.py +1 -1
- atomicshop/mitm/engines/__parent/responder___parent.py +15 -2
- atomicshop/mitm/engines/create_module_template.py +1 -2
- atomicshop/mitm/import_config.py +79 -88
- atomicshop/mitm/initialize_engines.py +1 -2
- atomicshop/mitm/message.py +5 -4
- atomicshop/mitm/mitm_main.py +222 -121
- atomicshop/mitm/recs_files.py +61 -5
- atomicshop/mitm/ssh_tester.py +82 -0
- atomicshop/networks.py +108 -93
- atomicshop/package_mains_processor.py +84 -0
- atomicshop/permissions/ubuntu_permissions.py +47 -0
- atomicshop/print_api.py +3 -5
- atomicshop/python_functions.py +23 -108
- atomicshop/speech_recognize.py +8 -0
- atomicshop/ssh_remote.py +115 -51
- atomicshop/web.py +20 -7
- atomicshop/web_apis/google_llm.py +22 -14
- atomicshop/wrappers/ctyping/msi_windows_installer/cabs.py +2 -1
- atomicshop/wrappers/ctyping/msi_windows_installer/extract_msi_main.py +2 -1
- atomicshop/wrappers/dockerw/dockerw.py +2 -2
- atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py +5 -5
- atomicshop/wrappers/githubw.py +175 -63
- atomicshop/wrappers/loggingw/handlers.py +1 -1
- atomicshop/wrappers/loggingw/loggingw.py +17 -1
- atomicshop/wrappers/netshw.py +124 -3
- atomicshop/wrappers/playwrightw/scenarios.py +1 -1
- atomicshop/wrappers/powershell_networking.py +80 -0
- atomicshop/wrappers/psutilw/psutil_networks.py +9 -0
- atomicshop/wrappers/pywin32w/win_event_log/fetch.py +174 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_create.py +3 -105
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_terminate.py +3 -57
- atomicshop/wrappers/pywin32w/wmis/win32_networkadapterconfiguration.py +12 -27
- atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +15 -9
- atomicshop/wrappers/socketw/certificator.py +19 -9
- atomicshop/wrappers/socketw/creator.py +30 -7
- atomicshop/wrappers/socketw/dns_server.py +6 -6
- atomicshop/wrappers/socketw/exception_wrapper.py +3 -3
- atomicshop/wrappers/socketw/process_getter.py +86 -0
- atomicshop/wrappers/socketw/receiver.py +29 -9
- atomicshop/wrappers/socketw/sender.py +10 -9
- atomicshop/wrappers/socketw/sni.py +23 -6
- atomicshop/wrappers/socketw/{base.py → socket_base.py} +33 -1
- atomicshop/wrappers/socketw/socket_client.py +6 -8
- atomicshop/wrappers/socketw/socket_wrapper.py +82 -21
- atomicshop/wrappers/socketw/ssl_base.py +6 -2
- atomicshop/wrappers/win_auditw.py +189 -0
- {atomicshop-3.3.28.dist-info → atomicshop-3.10.0.dist-info}/METADATA +25 -30
- {atomicshop-3.3.28.dist-info → atomicshop-3.10.0.dist-info}/RECORD +74 -88
- atomicshop/_basics_temp.py +0 -101
- atomicshop/a_installs/ubuntu/docker_rootless.py +0 -11
- atomicshop/a_installs/ubuntu/docker_sudo.py +0 -11
- atomicshop/addons/a_setup_scripts/install_psycopg2_ubuntu.sh +0 -3
- atomicshop/addons/package_setup/CreateWheel.cmd +0 -7
- atomicshop/addons/package_setup/Setup in Edit mode.cmd +0 -6
- atomicshop/addons/package_setup/Setup.cmd +0 -7
- atomicshop/archiver/__init__.py +0 -0
- atomicshop/archiver/_search_in_zip.py +0 -189
- atomicshop/archiver/search_in_archive.py +0 -284
- atomicshop/archiver/sevenz_app_w.py +0 -86
- atomicshop/archiver/sevenzs.py +0 -73
- atomicshop/archiver/shutils.py +0 -34
- atomicshop/archiver/zips.py +0 -353
- atomicshop/file_types.py +0 -24
- atomicshop/pbtkmultifile_argparse.py +0 -88
- atomicshop/script_as_string_processor.py +0 -42
- atomicshop/ssh_scripts/process_from_ipv4.py +0 -37
- atomicshop/ssh_scripts/process_from_port.py +0 -27
- atomicshop/wrappers/_process_wrapper_curl.py +0 -27
- atomicshop/wrappers/_process_wrapper_tar.py +0 -21
- atomicshop/wrappers/dockerw/install_docker.py +0 -449
- atomicshop/wrappers/ffmpegw.py +0 -125
- atomicshop/wrappers/process_wrapper_pbtk.py +0 -16
- atomicshop/wrappers/socketw/get_process.py +0 -123
- /atomicshop/{addons → a_mains/addons}/PlayWrightCodegen.cmd +0 -0
- /atomicshop/{addons → a_mains/addons}/ScriptExecution.cmd +0 -0
- /atomicshop/{addons → a_mains/addons}/inits/init_to_import_all_modules.py +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/ReadMe.txt +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/compile.cmd +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/compiled/Win10x64/process_list.dll +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/compiled/Win10x64/process_list.exp +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/compiled/Win10x64/process_list.lib +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/process_list.cpp +0 -0
- {atomicshop-3.3.28.dist-info → atomicshop-3.10.0.dist-info}/WHEEL +0 -0
- {atomicshop-3.3.28.dist-info → atomicshop-3.10.0.dist-info}/licenses/LICENSE.txt +0 -0
- {atomicshop-3.3.28.dist-info → atomicshop-3.10.0.dist-info}/top_level.txt +0 -0
atomicshop/mitm/mitm_main.py
CHANGED
|
@@ -11,10 +11,11 @@ import atomicshop # Importing atomicshop package to get the version of the pac
|
|
|
11
11
|
|
|
12
12
|
from .. import filesystem, on_exit, print_api, networks, dns
|
|
13
13
|
from ..permissions import permissions
|
|
14
|
-
from ..
|
|
15
|
-
from ..wrappers.socketw import socket_wrapper, dns_server,
|
|
14
|
+
from .. import python_functions
|
|
15
|
+
from ..wrappers.socketw import socket_wrapper, dns_server, statistics_csv
|
|
16
16
|
from ..wrappers.loggingw import loggingw
|
|
17
17
|
from ..wrappers.ctyping import win_console
|
|
18
|
+
from ..wrappers import netshw
|
|
18
19
|
from ..basics import multiprocesses
|
|
19
20
|
|
|
20
21
|
from .connection_thread_worker import thread_worker_main
|
|
@@ -36,6 +37,7 @@ class NetworkSettings:
|
|
|
36
37
|
|
|
37
38
|
def __init__(
|
|
38
39
|
self,
|
|
40
|
+
name: str | None = None,
|
|
39
41
|
description: str | None = None,
|
|
40
42
|
interface_index: int | None = None,
|
|
41
43
|
is_dynamic: bool = False,
|
|
@@ -46,7 +48,7 @@ class NetworkSettings:
|
|
|
46
48
|
default_gateways: list[str] = None,
|
|
47
49
|
dns_gateways: list[str] = None
|
|
48
50
|
):
|
|
49
|
-
|
|
51
|
+
self.name: str | None = name
|
|
50
52
|
self.description: str | None = description
|
|
51
53
|
self.interface_index: int | None = interface_index
|
|
52
54
|
self.is_dynamic: bool = is_dynamic
|
|
@@ -60,8 +62,6 @@ class NetworkSettings:
|
|
|
60
62
|
|
|
61
63
|
# Global variables for setting the network interface to external IPs (eg: 192.168.0.1)
|
|
62
64
|
NETWORK_INTERFACE_SETTINGS: NetworkSettings = NetworkSettings()
|
|
63
|
-
CURRENT_IPV4S: list[str] = list()
|
|
64
|
-
CURRENT_IPV4_MASKS: list[str] = list()
|
|
65
65
|
IPS_TO_ASSIGN: list[str] = list()
|
|
66
66
|
MASKS_TO_ASSIGN: list[str] = list()
|
|
67
67
|
|
|
@@ -96,45 +96,37 @@ except win_console.NotWindowsConsoleError:
|
|
|
96
96
|
pass
|
|
97
97
|
|
|
98
98
|
|
|
99
|
+
# noinspection PyUnusedLocal
|
|
99
100
|
def _graceful_shutdown(signum, frame):
|
|
100
101
|
exit_cleanup()
|
|
101
102
|
|
|
102
103
|
|
|
103
104
|
def exit_cleanup():
|
|
104
|
-
if config_static.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if is_dns_dynamic != NETWORK_INTERFACE_IS_DYNAMIC or \
|
|
111
|
-
(not is_dns_dynamic and current_dns_gateway != NETWORK_INTERFACE_IPV4_ADDRESS_LIST):
|
|
112
|
-
if NETWORK_INTERFACE_IS_DYNAMIC:
|
|
113
|
-
dns.set_connection_dns_gateway_dynamic(use_default_connection=True)
|
|
114
|
-
else:
|
|
115
|
-
dns.set_connection_dns_gateway_static(
|
|
116
|
-
dns_servers=NETWORK_INTERFACE_IPV4_ADDRESS_LIST, use_default_connection=True)
|
|
117
|
-
|
|
118
|
-
print_api.print_api("Returned default DNS gateway...", color='blue')
|
|
119
|
-
else:
|
|
120
|
-
# Get current network interface state.
|
|
121
|
-
default_network_adapter_config, default_network_adapter, default_adapter_info = networks.get_wmi_network_adapter_configuration(
|
|
122
|
-
use_default_interface=True, get_info_from_network_config=True)
|
|
105
|
+
if not config_static.MainConfig.is_localhost:
|
|
106
|
+
# Remove all the virtual IPs from the interface.
|
|
107
|
+
current_virtual_ips: list[str] = networks.get_interface_ips_powershell(NETWORK_INTERFACE_SETTINGS.name, "virtual")
|
|
108
|
+
for ip in current_virtual_ips:
|
|
109
|
+
netshw.remove_virtual_ip(NETWORK_INTERFACE_SETTINGS.name, ip)
|
|
123
110
|
|
|
124
|
-
|
|
125
|
-
# If the network interface was dynamic before the script started, we will return it to dynamic.
|
|
126
|
-
networks.set_dynamic_ip_for_adapter(default_network_adapter_config)
|
|
127
|
-
else:
|
|
128
|
-
networks.set_static_ip_for_adapter(
|
|
129
|
-
default_network_adapter,
|
|
130
|
-
ips=NETWORK_INTERFACE_SETTINGS.ipv4s,
|
|
131
|
-
masks=NETWORK_INTERFACE_SETTINGS.ipv4_subnet_masks,
|
|
132
|
-
gateways=NETWORK_INTERFACE_SETTINGS.default_gateways,
|
|
133
|
-
dns_gateways=NETWORK_INTERFACE_SETTINGS.dns_gateways
|
|
134
|
-
)
|
|
111
|
+
netshw.disable_dhcp_static_coexistence(interface_name=NETWORK_INTERFACE_SETTINGS.name)
|
|
135
112
|
|
|
136
113
|
print_api.print_api("Returned network adapter settings...", color='blue')
|
|
137
114
|
|
|
115
|
+
if permissions.is_admin() and IS_SET_DNS_GATEWAY:
|
|
116
|
+
is_dns_dynamic, current_dns_gateway = dns.get_default_dns_gateway()
|
|
117
|
+
status_string = 'Dynamic' if is_dns_dynamic else 'Static'
|
|
118
|
+
print_api.print_api(f'Current DNS Gateway: {status_string}, {current_dns_gateway}')
|
|
119
|
+
|
|
120
|
+
if is_dns_dynamic != NETWORK_INTERFACE_IS_DYNAMIC or \
|
|
121
|
+
(not is_dns_dynamic and current_dns_gateway != NETWORK_INTERFACE_IPV4_ADDRESS_LIST):
|
|
122
|
+
if NETWORK_INTERFACE_IS_DYNAMIC:
|
|
123
|
+
dns.set_interface_dns_gateway_dynamic(interface_name=NETWORK_INTERFACE_SETTINGS.name)
|
|
124
|
+
else:
|
|
125
|
+
dns.set_interface_dns_gateway_static(
|
|
126
|
+
dns_servers=NETWORK_INTERFACE_IPV4_ADDRESS_LIST, interface_name=NETWORK_INTERFACE_SETTINGS.name)
|
|
127
|
+
|
|
128
|
+
print_api.print_api("Returned default DNS gateway...", color='blue')
|
|
129
|
+
|
|
138
130
|
# The process will not be executed if there was an exception in the beginning.
|
|
139
131
|
if RECS_PROCESS_INSTANCE is not None:
|
|
140
132
|
print_api.print_api(f'Recs archive process alive: {RECS_PROCESS_INSTANCE.is_alive()}')
|
|
@@ -161,7 +153,7 @@ def startup_output(system_logger, script_version: str):
|
|
|
161
153
|
# Writing first log.
|
|
162
154
|
system_logger.info("======================================")
|
|
163
155
|
system_logger.info("Server Started.")
|
|
164
|
-
system_logger.info(f"Python Version: {
|
|
156
|
+
system_logger.info(f"Python Version: {python_functions.get_python_version_string()}")
|
|
165
157
|
system_logger.info(f"Script Version: {script_version}")
|
|
166
158
|
system_logger.info(f"Atomic Workshop Version: {atomicshop.__version__}")
|
|
167
159
|
system_logger.info(f"Log folder: {config_static.LogRec.logs_path}")
|
|
@@ -198,6 +190,7 @@ def startup_output(system_logger, script_version: str):
|
|
|
198
190
|
# Printing the parsers using "start=1" for index to start counting from "1" and not "0"
|
|
199
191
|
system_logger.info("Imported engine info.")
|
|
200
192
|
print_api.print_api(f"[*] Found Engines:", logger=system_logger)
|
|
193
|
+
print_api.print_api( f"-------------------------", logger=system_logger)
|
|
201
194
|
|
|
202
195
|
if not config_static.ENGINES_LIST:
|
|
203
196
|
message = \
|
|
@@ -212,7 +205,6 @@ def startup_output(system_logger, script_version: str):
|
|
|
212
205
|
f"{engine.responder_class_object.__name__}, "
|
|
213
206
|
f"{engine.recorder_class_object.__name__}")
|
|
214
207
|
print_api.print_api(message, logger=system_logger)
|
|
215
|
-
print_api.print_api(f"[*] Name: {engine.engine_name}", logger=system_logger)
|
|
216
208
|
print_api.print_api(f"[*] Domains: {list(engine.domain_target_dict.keys())}", logger=system_logger)
|
|
217
209
|
dns_targets: list = list()
|
|
218
210
|
for domain, ip_port in engine.domain_target_dict.items():
|
|
@@ -223,9 +215,11 @@ def startup_output(system_logger, script_version: str):
|
|
|
223
215
|
print_api.print_api(f"[*] Connect Ports to IPs: {list(engine.on_port_connect.values())}", logger=system_logger)
|
|
224
216
|
print_api.print_api(f"[*] Connect Ports to IPs Targets: {list(engine.port_target_dict.values())}", logger=system_logger)
|
|
225
217
|
|
|
218
|
+
print_api.print_api("-------------------------", logger=system_logger)
|
|
219
|
+
|
|
226
220
|
# print_api.print_api(f"[*] TCP Listening Interfaces: {engine.tcp_listening_address_list}", logger=system_logger)
|
|
227
221
|
|
|
228
|
-
if config_static.DNSServer.
|
|
222
|
+
if config_static.DNSServer.is_enabled:
|
|
229
223
|
print_api.print_api("DNS Server is enabled.", logger=system_logger)
|
|
230
224
|
|
|
231
225
|
# If engines were found and dns is set to route by the engine domains.
|
|
@@ -249,13 +243,42 @@ def startup_output(system_logger, script_version: str):
|
|
|
249
243
|
else:
|
|
250
244
|
print_api.print_api("DNS Server is disabled.", logger=system_logger, color="yellow")
|
|
251
245
|
|
|
252
|
-
if config_static.TCPServer.
|
|
246
|
+
if config_static.TCPServer.is_enabled:
|
|
253
247
|
print_api.print_api("TCP Server is enabled.", logger=system_logger)
|
|
254
248
|
else:
|
|
255
249
|
print_api.print_api("TCP Server is disabled.", logger=system_logger, color="yellow")
|
|
256
250
|
|
|
251
|
+
if config_static.MainConfig.is_localhost:
|
|
252
|
+
selected_net_interface: str = config_static.MainConfig.network_interface
|
|
253
|
+
else:
|
|
254
|
+
selected_net_interface: str = NETWORK_INTERFACE_SETTINGS.name
|
|
255
|
+
print_api.print_api(f"Selected Network Interface: {selected_net_interface}", logger=system_logger)
|
|
256
|
+
|
|
257
|
+
print_api.print_api(f"Listening DNS address: {config_static.DNSServer.listening_address}", logger=system_logger)
|
|
257
258
|
|
|
258
|
-
|
|
259
|
+
|
|
260
|
+
def _get_interface_name() -> str | None:
|
|
261
|
+
if config_static.MainConfig.network_interface == '':
|
|
262
|
+
interface_name: str = networks.get_default_interface_name()
|
|
263
|
+
if interface_name == '':
|
|
264
|
+
print_api.print_api(
|
|
265
|
+
"Default network interface not found.",
|
|
266
|
+
error_type=True, color="red")
|
|
267
|
+
return None
|
|
268
|
+
else:
|
|
269
|
+
current_network_interface_names: list[str] = networks.list_network_interfaces()
|
|
270
|
+
if config_static.MainConfig.network_interface not in current_network_interface_names:
|
|
271
|
+
print_api.print_api(
|
|
272
|
+
f"Not found Network interface with the name: {config_static.MainConfig.network_interface}",
|
|
273
|
+
error_type=True, color="red")
|
|
274
|
+
return None
|
|
275
|
+
else:
|
|
276
|
+
interface_name = config_static.MainConfig.network_interface
|
|
277
|
+
|
|
278
|
+
return interface_name
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def get_ipv4s_for_tcp_server() -> int:
|
|
259
282
|
"""
|
|
260
283
|
Function to get the IPv4 addresses for the default network adapter to set them to the adapter.
|
|
261
284
|
"""
|
|
@@ -268,48 +291,82 @@ def get_ipv4s_for_tcp_server():
|
|
|
268
291
|
ports_to_create_ips_for += list(engine.on_port_connect.keys())
|
|
269
292
|
|
|
270
293
|
engine_ips: list[str] = list()
|
|
271
|
-
|
|
272
|
-
if config_static.ENGINES_LIST[0].is_localhost:
|
|
273
|
-
create_ips: int = len(domains_to_create_ips_for) + len(ports_to_create_ips_for)
|
|
294
|
+
create_ips: int = len(domains_to_create_ips_for) + len(ports_to_create_ips_for)
|
|
274
295
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
296
|
+
# Get network interface name.
|
|
297
|
+
interface_name: str = _get_interface_name()
|
|
298
|
+
if interface_name is None:
|
|
299
|
+
return 1
|
|
300
|
+
|
|
301
|
+
# Get selected network interface virtual IPs from previous runs.
|
|
302
|
+
# We still need network interface settings for DNS gateway assignment for the network interface doesn't matter in localhost mode or not.
|
|
303
|
+
current_virtual_ips: list[str] = networks.get_interface_ips_powershell(interface_name, "virtual")
|
|
304
|
+
|
|
305
|
+
if current_virtual_ips:
|
|
306
|
+
print_api.print_api(
|
|
307
|
+
f"Removing previous virtual IPs from interface [{interface_name}]: {current_virtual_ips}",
|
|
308
|
+
color="blue")
|
|
309
|
+
|
|
310
|
+
if not permissions.is_admin():
|
|
311
|
+
print_api.print_api(
|
|
312
|
+
f"Administrator permissions are required to remove virtual IPs from interface.",
|
|
313
|
+
error_type=True, color="red")
|
|
314
|
+
return 1
|
|
315
|
+
# Remove all the virtual IPs from the interface.
|
|
316
|
+
for ip in current_virtual_ips:
|
|
317
|
+
netshw.remove_virtual_ip(interface_name, ip)
|
|
318
|
+
|
|
319
|
+
network_adapter_config, network_adapter, adapter_info = networks.get_wmi_network_adapter_configuration(
|
|
320
|
+
interface_name=interface_name,
|
|
321
|
+
get_info_from_network_config=True)
|
|
322
|
+
|
|
323
|
+
global NETWORK_INTERFACE_SETTINGS
|
|
324
|
+
NETWORK_INTERFACE_SETTINGS = NetworkSettings(
|
|
325
|
+
name=adapter_info['name'],
|
|
326
|
+
description=adapter_info['description'],
|
|
327
|
+
interface_index=adapter_info['interface_index'],
|
|
328
|
+
is_dynamic=adapter_info['is_dynamic'],
|
|
329
|
+
ipv4s=adapter_info['ipv4s'],
|
|
330
|
+
ipv6s=adapter_info['ipv6s'],
|
|
331
|
+
ipv4_subnet_masks=adapter_info['ipv4_subnet_masks'],
|
|
332
|
+
ipv6_prefixes=adapter_info['ipv6_prefixes'],
|
|
333
|
+
default_gateways=adapter_info['default_gateways'],
|
|
334
|
+
dns_gateways=adapter_info['dns_gateways']
|
|
335
|
+
)
|
|
295
336
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
337
|
+
# Check if we need the localhost ips (12.0.0.1) or external local ips (192.168.0.100).
|
|
338
|
+
if config_static.MainConfig.is_localhost:
|
|
339
|
+
# Generate the list of localhost ips. We will start from 127.0.0.2 and end with 127.0.0.2(create_ips + 1)
|
|
340
|
+
for i in range(2, create_ips + 2):
|
|
341
|
+
engine_ips.append(f"127.0.0.{i}")
|
|
299
342
|
|
|
300
|
-
# If the
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
create_ips -= current_ips_count
|
|
343
|
+
# If the current default DNS gateway ipv4 is inside the engine_ips, then we will remove it and add the next in line.
|
|
344
|
+
if config_static.MainConfig.default_localhost_dns_gateway_ipv4 in engine_ips:
|
|
345
|
+
engine_ips.remove(config_static.MainConfig.default_localhost_dns_gateway_ipv4)
|
|
346
|
+
engine_ips.append(f"127.0.0.{create_ips + 2}")
|
|
305
347
|
|
|
348
|
+
dns_listening_ipv4: str = config_static.MainConfig.default_localhost_dns_gateway_ipv4
|
|
349
|
+
else:
|
|
306
350
|
# Generate the IPs for the domains.
|
|
307
|
-
global
|
|
308
|
-
|
|
351
|
+
global IPS_TO_ASSIGN, MASKS_TO_ASSIGN
|
|
352
|
+
assignment_result: tuple | None = networks.add_virtual_ips_to_network_interface(
|
|
353
|
+
interface_name=interface_name,
|
|
309
354
|
number_of_ips=create_ips,
|
|
310
355
|
simulate_only=True)
|
|
311
356
|
|
|
312
|
-
|
|
357
|
+
if assignment_result is None:
|
|
358
|
+
return 1
|
|
359
|
+
|
|
360
|
+
IPS_TO_ASSIGN, MASKS_TO_ASSIGN = assignment_result
|
|
361
|
+
|
|
362
|
+
engine_ips += IPS_TO_ASSIGN
|
|
363
|
+
dns_listening_ipv4: str = NETWORK_INTERFACE_SETTINGS.ipv4s[0]
|
|
364
|
+
|
|
365
|
+
# Assign DNS listening address.
|
|
366
|
+
if config_static.DNSServer.listening_ipv4 != '':
|
|
367
|
+
config_static.DNSServer.listening_address = f"{config_static.DNSServer.listening_ipv4}:{str(config_static.DNSServer.listening_port)}"
|
|
368
|
+
else:
|
|
369
|
+
config_static.DNSServer.listening_address = f"{dns_listening_ipv4}:{str(config_static.DNSServer.listening_port)}"
|
|
313
370
|
|
|
314
371
|
# Add the ips to engines.
|
|
315
372
|
for engine in config_static.ENGINES_LIST:
|
|
@@ -322,23 +379,31 @@ def get_ipv4s_for_tcp_server():
|
|
|
322
379
|
if port in ports_to_create_ips_for:
|
|
323
380
|
engine.port_target_dict[port]['ip'] = engine_ips.pop(0)
|
|
324
381
|
|
|
382
|
+
return 0
|
|
325
383
|
|
|
326
|
-
|
|
384
|
+
|
|
385
|
+
def mitm_server(config_file_path: str, script_version: str) -> int:
|
|
327
386
|
on_exit.register_exit_handler(exit_cleanup, at_exit=False, kill_signal=False)
|
|
328
387
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
388
|
+
python_version: str = python_functions.get_python_version_string()
|
|
389
|
+
print_api.print_api(f"[*] Python Version: {python_version}")
|
|
390
|
+
|
|
391
|
+
compliance_message: str | None = python_functions.check_python_version_compliance(min_ver=(3,13), max_ver=(3,13,99))
|
|
392
|
+
if compliance_message is not None:
|
|
393
|
+
print_api.print_api(f"[!] {compliance_message}", error_type=True, color="red")
|
|
333
394
|
return 1
|
|
334
395
|
|
|
396
|
+
print_api.print_api("[*] Version Check PASSED.", color="green")
|
|
397
|
+
|
|
335
398
|
# Import the configuration file.
|
|
336
|
-
|
|
337
|
-
if
|
|
338
|
-
return
|
|
399
|
+
rc: int = config_static.load_config(config_file_path, print_kwargs=dict(stdout=False))
|
|
400
|
+
if rc != 0:
|
|
401
|
+
return rc
|
|
339
402
|
|
|
340
403
|
# Get the IPs that will be set for the adapter and fill the engine configuration with the IPs.
|
|
341
|
-
get_ipv4s_for_tcp_server()
|
|
404
|
+
rc: int = get_ipv4s_for_tcp_server()
|
|
405
|
+
if rc != 0:
|
|
406
|
+
return rc
|
|
342
407
|
|
|
343
408
|
global MITM_ERROR_LOGGER
|
|
344
409
|
MITM_ERROR_LOGGER = loggingw.ExceptionCsvLogger(
|
|
@@ -410,7 +475,7 @@ def mitm_server(config_file_path: str, script_version: str):
|
|
|
410
475
|
is_ready_multiprocessing_event_list: list[multiprocessing.Event] = list()
|
|
411
476
|
|
|
412
477
|
# === Initialize TCP Server ====================================================================================
|
|
413
|
-
if config_static.TCPServer.
|
|
478
|
+
if config_static.TCPServer.is_enabled:
|
|
414
479
|
# Get the default network adapter configuration and set the one from config.
|
|
415
480
|
# We set the virtual IPs in the network adapter here, so the server multiprocessing processes can listen on them.
|
|
416
481
|
setting_result: int = _add_virtual_ips_set_default_dns_gateway(system_logger)
|
|
@@ -502,6 +567,8 @@ def mitm_server(config_file_path: str, script_version: str):
|
|
|
502
567
|
exceptions_logger_queue=EXCEPTIONS_CSV_LOGGER_QUEUE,
|
|
503
568
|
forwarding_dns_service_ipv4_list___only_for_localhost=[config_static.DNSServer.forwarding_dns_service_ipv4],
|
|
504
569
|
skip_extension_id_list=config_static.SkipExtensions.SKIP_EXTENSION_ID_LIST,
|
|
570
|
+
enable_sslkeylogfile_env_to_client_ssl_context=config_static.Certificates.enable_sslkeylogfile_env_to_client_ssl_context,
|
|
571
|
+
sslkeylog_file_path=config_static.Certificates.sslkeylog_file_path,
|
|
505
572
|
print_kwargs=dict(stdout=False)
|
|
506
573
|
)
|
|
507
574
|
|
|
@@ -534,7 +601,7 @@ def mitm_server(config_file_path: str, script_version: str):
|
|
|
534
601
|
# === EOF Initialize TCP Server ====================================================================================
|
|
535
602
|
|
|
536
603
|
# === Initialize DNS module ========================================================================================
|
|
537
|
-
if config_static.DNSServer.
|
|
604
|
+
if config_static.DNSServer.is_enabled:
|
|
538
605
|
# noinspection PyTypeHints
|
|
539
606
|
is_dns_process_ready: multiprocessing.Event = multiprocessing.Event()
|
|
540
607
|
|
|
@@ -549,7 +616,7 @@ def mitm_server(config_file_path: str, script_version: str):
|
|
|
549
616
|
resolve_regular_pass_thru=config_static.DNSServer.resolve_regular_pass_thru,
|
|
550
617
|
resolve_all_domains_to_ipv4=(
|
|
551
618
|
config_static.DNSServer.resolve_all_domains_to_ipv4_enable, config_static.DNSServer.target_ipv4),
|
|
552
|
-
offline_mode=config_static.MainConfig.
|
|
619
|
+
offline_mode=config_static.MainConfig.is_offline,
|
|
553
620
|
cache_timeout_minutes=config_static.DNSServer.cache_timeout_minutes,
|
|
554
621
|
logging_queue=NETWORK_LOGGER_QUEUE,
|
|
555
622
|
logger_name=network_logger_name,
|
|
@@ -571,7 +638,7 @@ def mitm_server(config_file_path: str, script_version: str):
|
|
|
571
638
|
return 1
|
|
572
639
|
# === EOF Initialize DNS module ====================================================================================
|
|
573
640
|
|
|
574
|
-
if config_static.DNSServer.
|
|
641
|
+
if config_static.DNSServer.is_enabled or config_static.TCPServer.is_enabled:
|
|
575
642
|
print_api.print_api("The Server is Ready for Operation!", color="green", logger=system_logger)
|
|
576
643
|
print_api.print_api("Press [Ctrl]+[C] to stop.", color='blue', logger=system_logger)
|
|
577
644
|
|
|
@@ -591,6 +658,8 @@ def mitm_server(config_file_path: str, script_version: str):
|
|
|
591
658
|
|
|
592
659
|
time.sleep(1)
|
|
593
660
|
|
|
661
|
+
return 0
|
|
662
|
+
|
|
594
663
|
|
|
595
664
|
# noinspection PyTypeHints
|
|
596
665
|
def _create_tcp_server_process(
|
|
@@ -694,48 +763,59 @@ def _add_virtual_ips_set_default_dns_gateway(system_logger: logging.Logger) -> i
|
|
|
694
763
|
# This setting is needed only for the dns gateways configurations from the main config on localhost.
|
|
695
764
|
set_local_dns_gateway: bool = False
|
|
696
765
|
# Set the default gateway if specified.
|
|
697
|
-
if config_static.
|
|
698
|
-
dns_gateway_server_list = config_static.
|
|
766
|
+
if config_static.MainConfig.set_default_dns_gateway:
|
|
767
|
+
dns_gateway_server_list = config_static.MainConfig.set_default_dns_gateway
|
|
699
768
|
set_local_dns_gateway = True
|
|
700
|
-
elif config_static.
|
|
701
|
-
dns_gateway_server_list = [
|
|
769
|
+
elif config_static.MainConfig.set_default_dns_gateway_to_localhost:
|
|
770
|
+
dns_gateway_server_list = [config_static.MainConfig.default_localhost_dns_gateway_ipv4]
|
|
702
771
|
set_local_dns_gateway = True
|
|
703
|
-
elif config_static.
|
|
704
|
-
dns_gateway_server_list = [
|
|
772
|
+
elif config_static.MainConfig.set_default_dns_gateway_to_network_interface_ipv4:
|
|
773
|
+
dns_gateway_server_list = [NETWORK_INTERFACE_SETTINGS.ipv4s[0]]
|
|
705
774
|
set_local_dns_gateway = True
|
|
706
775
|
else:
|
|
707
776
|
dns_gateway_server_list = NETWORK_INTERFACE_SETTINGS.dns_gateways
|
|
708
777
|
|
|
709
|
-
if
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
778
|
+
if set_local_dns_gateway:
|
|
779
|
+
global IS_SET_DNS_GATEWAY
|
|
780
|
+
IS_SET_DNS_GATEWAY = True
|
|
781
|
+
|
|
782
|
+
# Get current network interface state.
|
|
783
|
+
global NETWORK_INTERFACE_IS_DYNAMIC, NETWORK_INTERFACE_IPV4_ADDRESS_LIST
|
|
784
|
+
NETWORK_INTERFACE_IS_DYNAMIC, NETWORK_INTERFACE_IPV4_ADDRESS_LIST = dns.get_default_dns_gateway()
|
|
785
|
+
|
|
786
|
+
# Set the DNS gateway to the specified one only if the DNS gateway is dynamic, or it is static but different
|
|
787
|
+
# from the one specified in the configuration file.
|
|
788
|
+
if (NETWORK_INTERFACE_IS_DYNAMIC or (not NETWORK_INTERFACE_IS_DYNAMIC and
|
|
789
|
+
NETWORK_INTERFACE_IPV4_ADDRESS_LIST != dns_gateway_server_list)):
|
|
790
|
+
try:
|
|
791
|
+
dns.set_interface_dns_gateway_static(
|
|
792
|
+
interface_name=NETWORK_INTERFACE_SETTINGS.name,
|
|
793
|
+
dns_servers=dns_gateway_server_list
|
|
794
|
+
)
|
|
795
|
+
except PermissionError as e:
|
|
796
|
+
print_api.print_api(e, error_type=True, color="red", logger=system_logger)
|
|
797
|
+
# Wait for the message to be printed and saved to file.
|
|
798
|
+
time.sleep(1)
|
|
799
|
+
# network_logger_queue_listener.stop()
|
|
800
|
+
return 1
|
|
801
|
+
|
|
802
|
+
if not config_static.MainConfig.is_localhost:
|
|
734
803
|
# Change the adapter settings and add the virtual IPs.
|
|
735
804
|
try:
|
|
736
|
-
networks.
|
|
737
|
-
|
|
738
|
-
|
|
805
|
+
networks.add_virtual_ips_to_network_interface(
|
|
806
|
+
interface_name=NETWORK_INTERFACE_SETTINGS.name,
|
|
807
|
+
virtual_ipv4s_to_add=IPS_TO_ASSIGN,
|
|
808
|
+
virtual_ipv4_masks_to_add=MASKS_TO_ASSIGN,
|
|
809
|
+
verbose=True,
|
|
810
|
+
logger=system_logger
|
|
811
|
+
)
|
|
812
|
+
|
|
813
|
+
for engine in config_static.ENGINES_LIST:
|
|
814
|
+
bindable_test_dict: dict = engine.domain_target_dict | engine.port_target_dict
|
|
815
|
+
for port_or_domain_name, ip_port_dict in bindable_test_dict.items():
|
|
816
|
+
print_api.print_api(f"Checking that virtual IP is bindable: {ip_port_dict['ip']}:{ip_port_dict['port']}", logger=system_logger)
|
|
817
|
+
networks.wait_for_ip_bindable_socket(ip_port_dict['ip'], port=int(ip_port_dict['port']), timeout=15)
|
|
818
|
+
print_api.print_api("BIND test successful for all virtual IPs.", logger=system_logger)
|
|
739
819
|
except (PermissionError, TimeoutError) as e:
|
|
740
820
|
print_api.print_api(e, error_type=True, color="red", logger=system_logger)
|
|
741
821
|
# Wait for the message to be printed and saved to file.
|
|
@@ -773,7 +853,28 @@ def _loop_at_midnight_recs_archive(network_logger_name):
|
|
|
773
853
|
|
|
774
854
|
|
|
775
855
|
def mitm_server_main(config_file_path: str, script_version: str):
|
|
856
|
+
# This is for Linux and macOS.
|
|
857
|
+
signal.signal(signal.SIGTERM, _graceful_shutdown)
|
|
776
858
|
signal.signal(signal.SIGINT, _graceful_shutdown)
|
|
859
|
+
# This is for Windows.
|
|
860
|
+
"""
|
|
861
|
+
Example:
|
|
862
|
+
script = (Path(__file__).resolve().parent / "ServerTCPWithDNS.py").resolve()
|
|
863
|
+
p = subprocess.Popen(
|
|
864
|
+
[sys.executable, "-u", str(script)],
|
|
865
|
+
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP,
|
|
866
|
+
# inherit console; do NOT use CREATE_NEW_CONSOLE
|
|
867
|
+
)
|
|
868
|
+
time.sleep(30)
|
|
869
|
+
p.send_signal(signal.CTRL_BREAK_EVENT)
|
|
870
|
+
try:
|
|
871
|
+
p.wait(timeout=5)
|
|
872
|
+
except subprocess.TimeoutExpired:
|
|
873
|
+
print("Graceful interrupt timed out; terminating")
|
|
874
|
+
p.terminate()
|
|
875
|
+
p.wait()
|
|
876
|
+
"""
|
|
877
|
+
signal.signal(signal.SIGBREAK, _graceful_shutdown)
|
|
777
878
|
|
|
778
879
|
try:
|
|
779
880
|
# Main function should return integer with error code, 0 is successful.
|
atomicshop/mitm/recs_files.py
CHANGED
|
@@ -2,8 +2,9 @@ import datetime
|
|
|
2
2
|
import os
|
|
3
3
|
import multiprocessing
|
|
4
4
|
import logging
|
|
5
|
+
import zipfile
|
|
6
|
+
import shutil
|
|
5
7
|
|
|
6
|
-
from ..archiver import zips
|
|
7
8
|
from .. import filesystem, print_api
|
|
8
9
|
from .. wrappers.loggingw import consts, loggingw
|
|
9
10
|
|
|
@@ -13,6 +14,40 @@ REC_FILE_DATE_TIME_FORMAT: str = f'{consts.DEFAULT_ROTATING_SUFFIXES_FROM_WHEN["
|
|
|
13
14
|
REC_FILE_DATE_FORMAT: str = REC_FILE_DATE_TIME_FORMAT.split('_')[0]
|
|
14
15
|
|
|
15
16
|
|
|
17
|
+
def archive(
|
|
18
|
+
directory_path: str,
|
|
19
|
+
include_root_directory: bool = True,
|
|
20
|
+
) -> str:
|
|
21
|
+
"""
|
|
22
|
+
Function archives the directory.
|
|
23
|
+
:param directory_path: string, full path to the directory.
|
|
24
|
+
:param include_root_directory: boolean, default is 'True'.
|
|
25
|
+
'True': The root directory will be included in the archive.
|
|
26
|
+
'False': The root directory will not be included in the archive.
|
|
27
|
+
True is usually the case in most archiving utilities.
|
|
28
|
+
:return: string, full path to the archived file.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
# This is commonly used and supported by most ZIP utilities.
|
|
32
|
+
compression_method = zipfile.ZIP_DEFLATED
|
|
33
|
+
|
|
34
|
+
archive_path: str = directory_path + '.zip'
|
|
35
|
+
with zipfile.ZipFile(archive_path, 'w', compression_method) as zip_object:
|
|
36
|
+
for root, _, files in os.walk(directory_path):
|
|
37
|
+
for file in files:
|
|
38
|
+
file_path = os.path.join(root, file)
|
|
39
|
+
|
|
40
|
+
# If including the root directory, use the relative path from the parent directory of the root
|
|
41
|
+
if include_root_directory:
|
|
42
|
+
arcname = os.path.relpath(file_path, os.path.dirname(directory_path))
|
|
43
|
+
else:
|
|
44
|
+
arcname = os.path.relpath(file_path, directory_path)
|
|
45
|
+
|
|
46
|
+
zip_object.write(file_path, arcname)
|
|
47
|
+
|
|
48
|
+
return archive_path
|
|
49
|
+
|
|
50
|
+
|
|
16
51
|
def recs_archiver(
|
|
17
52
|
recs_directory: str,
|
|
18
53
|
logging_queue: multiprocessing.Queue,
|
|
@@ -69,6 +104,8 @@ def recs_archiver(
|
|
|
69
104
|
try:
|
|
70
105
|
archived_files: list = list()
|
|
71
106
|
for directory_path, all_recs_files in file_list_per_directory:
|
|
107
|
+
print_api.print_api(f"Archiving recs files in directory: {directory_path.path}",
|
|
108
|
+
logger=rec_packer_logger_with_queue_handler, color='blue')
|
|
72
109
|
for recs_atomic_path in all_recs_files:
|
|
73
110
|
# We don't need to archive today's files.
|
|
74
111
|
if today_date_string == recs_atomic_path.datetime_string:
|
|
@@ -82,10 +119,29 @@ def recs_archiver(
|
|
|
82
119
|
# Archive directories.
|
|
83
120
|
archive_directories: list = filesystem.get_paths_from_directory(
|
|
84
121
|
directory_path.path, get_directory=True, recursive=False)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
122
|
+
|
|
123
|
+
if not archive_directories:
|
|
124
|
+
print_api.print_api(
|
|
125
|
+
f"No directories to archive in: {directory_path.path}",
|
|
126
|
+
color='blue',
|
|
127
|
+
logger=rec_packer_logger_with_queue_handler
|
|
128
|
+
)
|
|
129
|
+
else:
|
|
130
|
+
total_archived_files: int = 0
|
|
131
|
+
for archive_directory in archive_directories:
|
|
132
|
+
files_to_archive: list = filesystem.get_paths_from_directory(
|
|
133
|
+
directory_path=archive_directory.path, get_file=True, recursive=False)
|
|
134
|
+
total_archived_files += len(files_to_archive)
|
|
135
|
+
archived_file: str = archive(archive_directory.path, include_root_directory=True)
|
|
136
|
+
# Remove the original directory after archiving.
|
|
137
|
+
shutil.rmtree(archive_directory.path, ignore_errors=True)
|
|
138
|
+
archived_files.append(archived_file)
|
|
139
|
+
|
|
140
|
+
print_api.print_api(
|
|
141
|
+
f'Archived: 'f'Directories: {len(archive_directories)} | '
|
|
142
|
+
f'Total Files: {total_archived_files} | In: {directory_path.path}',
|
|
143
|
+
logger=rec_packer_logger_with_queue_handler, color='blue')
|
|
144
|
+
print_api.print_api(f'Archived files: {archived_files}', logger=rec_packer_logger_with_queue_handler)
|
|
89
145
|
|
|
90
146
|
finalize_output_queue.put(None)
|
|
91
147
|
|