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
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import multiprocessing
|
|
2
2
|
import threading
|
|
3
|
-
import time
|
|
4
|
-
|
|
5
3
|
import select
|
|
6
4
|
from typing import Literal, Union, Callable, Any
|
|
7
5
|
from pathlib import Path
|
|
@@ -9,17 +7,20 @@ import socket
|
|
|
9
7
|
import shutil
|
|
10
8
|
import os
|
|
11
9
|
|
|
10
|
+
import paramiko
|
|
11
|
+
|
|
12
12
|
from ...mitm import initialize_engines
|
|
13
13
|
from ..psutilw import psutil_networks
|
|
14
14
|
from ..certauthw import certauthw
|
|
15
15
|
from ..loggingw import loggingw
|
|
16
|
-
from ...
|
|
16
|
+
from ... import package_mains_processor
|
|
17
17
|
from ...permissions import permissions
|
|
18
18
|
from ... import filesystem, certificates
|
|
19
19
|
from ...basics import booleans, tracebacks
|
|
20
20
|
from ...print_api import print_api
|
|
21
|
+
from ...ssh_remote import SSHRemote
|
|
21
22
|
|
|
22
|
-
from . import
|
|
23
|
+
from . import socket_base, creator, process_getter, accepter, statistics_csv, ssl_base, sni
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
class SocketWrapperPortInUseError(Exception):
|
|
@@ -67,10 +68,7 @@ class SocketWrapper:
|
|
|
67
68
|
ssh_user: str = None,
|
|
68
69
|
ssh_pass: str = None,
|
|
69
70
|
ssh_script_to_execute: Union[
|
|
70
|
-
Literal[
|
|
71
|
-
'process_from_port',
|
|
72
|
-
'process_from_ipv4'
|
|
73
|
-
],
|
|
71
|
+
Literal['process_from_port'],
|
|
74
72
|
None
|
|
75
73
|
] = None,
|
|
76
74
|
logs_directory: str = None,
|
|
@@ -80,6 +78,8 @@ class SocketWrapper:
|
|
|
80
78
|
statistics_logger_queue: multiprocessing.Queue = None,
|
|
81
79
|
exceptions_logger_name: str = 'SocketWrapperExceptions',
|
|
82
80
|
exceptions_logger_queue: multiprocessing.Queue = None,
|
|
81
|
+
enable_sslkeylogfile_env_to_client_ssl_context: bool = False,
|
|
82
|
+
sslkeylog_file_path: str = None,
|
|
83
83
|
print_kwargs: dict = None,
|
|
84
84
|
):
|
|
85
85
|
"""
|
|
@@ -173,6 +173,12 @@ class SocketWrapper:
|
|
|
173
173
|
:param exceptions_logger_name: string, name of the logger that will be used to log exceptions.
|
|
174
174
|
:param exceptions_logger_queue: multiprocessing.Queue, queue that will be used to log exceptions in
|
|
175
175
|
multiprocessing. You need to start the logger listener in the main process to handle the queue.
|
|
176
|
+
:param enable_sslkeylogfile_env_to_client_ssl_context: boolean, if True, each client SSL context
|
|
177
|
+
that will be created by the SocketWrapper will have save the SSL handshake keys to the file
|
|
178
|
+
defined in 'sslkeylog_file_path' parameter.
|
|
179
|
+
:param sslkeylog_file_path: string, path to file where SSL handshake keys will be saved.
|
|
180
|
+
If not provided and 'enable_sslkeylogfile_env_to_client_ssl_context' is True, then
|
|
181
|
+
the environment variable 'SSLKEYLOGFILE' will be used.
|
|
176
182
|
:param print_kwargs: dict, additional arguments to pass to the print function.
|
|
177
183
|
"""
|
|
178
184
|
|
|
@@ -208,6 +214,9 @@ class SocketWrapper:
|
|
|
208
214
|
self.ssh_script_to_execute = ssh_script_to_execute
|
|
209
215
|
self.forwarding_dns_service_ipv4_list___only_for_localhost = (
|
|
210
216
|
forwarding_dns_service_ipv4_list___only_for_localhost)
|
|
217
|
+
self.enable_sslkeylogfile_env_to_client_ssl_context: bool = (
|
|
218
|
+
enable_sslkeylogfile_env_to_client_ssl_context)
|
|
219
|
+
self.sslkeylog_file_path: str = sslkeylog_file_path
|
|
211
220
|
self.print_kwargs: dict = print_kwargs
|
|
212
221
|
|
|
213
222
|
self.socket_object = None
|
|
@@ -226,12 +235,17 @@ class SocketWrapper:
|
|
|
226
235
|
# Defining listening sockets list, which will be used with "select" library in 'loop_for_incoming_sockets'.
|
|
227
236
|
self.listening_sockets: list = list()
|
|
228
237
|
|
|
229
|
-
# Defining '
|
|
238
|
+
# Defining 'ssh_script_string' variable, which will be used to process SSH scripts.
|
|
230
239
|
self.ssh_script_processor = None
|
|
231
240
|
if self.get_process_name:
|
|
232
241
|
# noinspection PyTypeChecker
|
|
233
|
-
self.
|
|
234
|
-
|
|
242
|
+
self.package_processor: package_mains_processor.PackageMainsProcessor | None = package_mains_processor.PackageMainsProcessor(script_file_stem=self.ssh_script_to_execute)
|
|
243
|
+
|
|
244
|
+
else:
|
|
245
|
+
self.package_processor = None
|
|
246
|
+
|
|
247
|
+
# We will initialize it during the first 'get_process_name' function call.
|
|
248
|
+
self.ssh_client: SSHRemote | None = None
|
|
235
249
|
|
|
236
250
|
# If logs directory was not set, we will use the working directory.
|
|
237
251
|
if not logs_directory:
|
|
@@ -551,8 +565,12 @@ class SocketWrapper:
|
|
|
551
565
|
print_kwargs={'logger': self.logger})
|
|
552
566
|
|
|
553
567
|
source_ip: str = client_address[0]
|
|
568
|
+
source_port: int = client_address[1]
|
|
554
569
|
dest_port: int = listening_socket_object.getsockname()[1]
|
|
555
570
|
|
|
571
|
+
message: str = f"Accepted connection from [{source_ip}:{source_port}] to [{listening_ip}:{dest_port}] | domain: {domain_from_engine}"
|
|
572
|
+
print_api(message, logger=self.logger)
|
|
573
|
+
|
|
556
574
|
# Not always there will be a hostname resolved by the IP address, so we will leave it empty if it fails.
|
|
557
575
|
try:
|
|
558
576
|
source_hostname = socket.gethostbyaddr(source_ip)[0]
|
|
@@ -564,21 +582,61 @@ class SocketWrapper:
|
|
|
564
582
|
# SSH Remote / LOCALHOST script execution to identify process section.
|
|
565
583
|
# If 'get_process_name' was set to True, then this will be executed.
|
|
566
584
|
if self.get_process_name:
|
|
585
|
+
# Initializing SSHRemote class if not initialized.
|
|
586
|
+
if self.ssh_client is None:
|
|
587
|
+
self.ssh_client = SSHRemote(
|
|
588
|
+
ip_address=source_ip, username=self.ssh_user, password=self.ssh_pass, logger=self.logger)
|
|
589
|
+
|
|
567
590
|
# Get the process name from the socket.
|
|
568
|
-
get_command_instance =
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
591
|
+
get_command_instance = process_getter.GetCommandLine(
|
|
592
|
+
client_ip=source_ip,
|
|
593
|
+
client_port=source_port,
|
|
594
|
+
package_processor=self.package_processor,
|
|
595
|
+
ssh_client=self.ssh_client,
|
|
573
596
|
logger=self.logger)
|
|
574
597
|
process_name = get_command_instance.get_process_name(print_kwargs={'logger': self.logger})
|
|
575
598
|
|
|
599
|
+
# from ..pywin32w.win_event_log import fetch
|
|
600
|
+
# events = fetch.get_latest_events(
|
|
601
|
+
# server_ip=source_ip,
|
|
602
|
+
# username=self.ssh_user,
|
|
603
|
+
# password=self.ssh_pass,
|
|
604
|
+
# log_name='Security',
|
|
605
|
+
# count=50,
|
|
606
|
+
# event_id_list=[5156]
|
|
607
|
+
# )
|
|
608
|
+
#
|
|
609
|
+
# source_port = client_address[1]
|
|
610
|
+
# for event in events:
|
|
611
|
+
# if source_port == event['StringsDict']['Source Port']:
|
|
612
|
+
# process_name = event['StringsDict']['Application Name']
|
|
613
|
+
# break
|
|
614
|
+
#
|
|
615
|
+
# if process_name == '':
|
|
616
|
+
# raise RuntimeError("Failed to get process name from the remote host via Event Log.")
|
|
617
|
+
|
|
576
618
|
# If 'accept()' function worked well, SSL worked well, then 'client_socket' won't be empty.
|
|
577
619
|
if client_socket:
|
|
578
620
|
# Get the protocol type from the socket.
|
|
579
621
|
is_tls: bool = False
|
|
580
622
|
|
|
581
|
-
|
|
623
|
+
try:
|
|
624
|
+
tls_properties = ssl_base.is_tls(client_socket, timeout=1)
|
|
625
|
+
except TimeoutError:
|
|
626
|
+
error: str = "TimeoutError: TLS detection timed out. Dropping accepted socket."
|
|
627
|
+
self.logger.error(error)
|
|
628
|
+
|
|
629
|
+
self.statistics_writer.write_accept_error(
|
|
630
|
+
engine=engine_name,
|
|
631
|
+
source_host=source_hostname,
|
|
632
|
+
source_ip=source_ip,
|
|
633
|
+
error_message=error,
|
|
634
|
+
dest_port=str(dest_port),
|
|
635
|
+
host=domain_from_engine,
|
|
636
|
+
process_name=process_name)
|
|
637
|
+
|
|
638
|
+
client_socket.close()
|
|
639
|
+
continue
|
|
582
640
|
|
|
583
641
|
if tls_properties:
|
|
584
642
|
is_tls = True
|
|
@@ -616,7 +674,9 @@ class SocketWrapper:
|
|
|
616
674
|
forwarding_dns_service_ipv4_list___only_for_localhost=(
|
|
617
675
|
self.forwarding_dns_service_ipv4_list___only_for_localhost),
|
|
618
676
|
tls=is_tls,
|
|
619
|
-
exceptions_logger=self.exceptions_logger
|
|
677
|
+
exceptions_logger=self.exceptions_logger,
|
|
678
|
+
enable_sslkeylogfile_env_to_client_ssl_context=self.enable_sslkeylogfile_env_to_client_ssl_context,
|
|
679
|
+
sslkeylog_file_path=self.sslkeylog_file_path
|
|
620
680
|
)
|
|
621
681
|
|
|
622
682
|
ssl_client_socket, accept_error_message = \
|
|
@@ -678,7 +738,7 @@ class SocketWrapper:
|
|
|
678
738
|
self.threads_list.append(thread_current)
|
|
679
739
|
|
|
680
740
|
# 'thread_callable_args[1][0]' is the client socket.
|
|
681
|
-
client_address =
|
|
741
|
+
client_address = socket_base.get_source_address_from_socket(client_socket)
|
|
682
742
|
|
|
683
743
|
self.logger.info(f"Accepted connection, thread created {client_address}. Continue listening...")
|
|
684
744
|
# Else, if no client_socket was opened during, accept, then print the error.
|
|
@@ -692,7 +752,8 @@ class SocketWrapper:
|
|
|
692
752
|
dest_port=str(dest_port),
|
|
693
753
|
host=domain_from_engine,
|
|
694
754
|
process_name=process_name)
|
|
695
|
-
|
|
755
|
+
# Sometimes paramiko SSH connection return EOFError on connection reset, so we need to catch it separately.
|
|
756
|
+
except (ConnectionResetError, paramiko.ssh_exception.SSHException, EOFError) as e:
|
|
696
757
|
exception_string: str = tracebacks.get_as_string()
|
|
697
758
|
full_string: str = f"{str(e)} | {exception_string}"
|
|
698
759
|
self.statistics_writer.write_accept_error(
|
|
@@ -726,7 +787,7 @@ def before_socket_thread_worker(
|
|
|
726
787
|
try:
|
|
727
788
|
callable_function(*callable_args)
|
|
728
789
|
except Exception as e:
|
|
729
|
-
exceptions_logger.write(e)
|
|
790
|
+
exceptions_logger.write(e, custom_exception_attribute='engine_name', custom_exception_attribute_placement='before')
|
|
730
791
|
|
|
731
792
|
|
|
732
793
|
def get_engine_name(domain: str, engine_list: list):
|
|
@@ -24,15 +24,19 @@ def convert_der_x509_bytes_to_pem_string(certificate) -> str:
|
|
|
24
24
|
return ssl.DER_cert_to_PEM_cert(certificate)
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
def is_tls(
|
|
27
|
+
def is_tls(
|
|
28
|
+
client_socket,
|
|
29
|
+
timeout: float = None
|
|
30
|
+
) -> Optional[Tuple[str, str]]:
|
|
28
31
|
"""
|
|
29
32
|
Return protocol type of the incoming socket after 'accept()'.
|
|
30
33
|
:param client_socket: incoming socket after 'accept()'.
|
|
34
|
+
:param timeout: optional timeout for receiving/peeking the first bytes.
|
|
31
35
|
:return: tuple with content type, protocol type + version.
|
|
32
36
|
If the length of the first bytes is less than 3, return None.
|
|
33
37
|
"""
|
|
34
38
|
|
|
35
|
-
first_bytes = receiver.peek_first_bytes(client_socket, bytes_amount=3)
|
|
39
|
+
first_bytes = receiver.peek_first_bytes(client_socket, bytes_amount=3, timeout=timeout)
|
|
36
40
|
|
|
37
41
|
# Sometimes only one byte is available, so we need to handle that case.
|
|
38
42
|
# convert to a tuple of ints, add three Nones, and keep only the first 3 items.
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import winreg
|
|
3
|
+
|
|
4
|
+
from ..print_api import print_api
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
AUDITING_REG_PATH: str = r"Software\Microsoft\Windows\CurrentVersion\Policies\System\Audit"
|
|
8
|
+
PROCESS_CREATION_INCLUDE_CMDLINE_VALUE: str = "ProcessCreationIncludeCmdLine_Enabled"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def enable_command_line_auditing(print_kwargs: dict = None):
|
|
12
|
+
"""
|
|
13
|
+
Enable the 'Include command line in process creation events' policy.
|
|
14
|
+
|
|
15
|
+
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Audit" /v ProcessCreationIncludeCmdLine_Enabled /t REG_DWORD /d 1 /f
|
|
16
|
+
|
|
17
|
+
:param print_kwargs: Optional keyword arguments for the print function.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
if is_command_line_auditing_enabled():
|
|
21
|
+
print_api(
|
|
22
|
+
"[Include command line in process creation events] is already enabled.", color='blue',
|
|
23
|
+
**(print_kwargs or {}))
|
|
24
|
+
return
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
# Open the registry key
|
|
28
|
+
with winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, AUDITING_REG_PATH) as reg_key:
|
|
29
|
+
# Set the value
|
|
30
|
+
winreg.SetValueEx(reg_key, PROCESS_CREATION_INCLUDE_CMDLINE_VALUE, 0, winreg.REG_DWORD, 1)
|
|
31
|
+
|
|
32
|
+
print_api(
|
|
33
|
+
"Successfully enabled [Include command line in process creation events].",
|
|
34
|
+
color='green', **(print_kwargs or {}))
|
|
35
|
+
except WindowsError as e:
|
|
36
|
+
print_api(
|
|
37
|
+
f"Failed to enable [Include command line in process creation events]: {e}", error_type=True,
|
|
38
|
+
color='red', **(print_kwargs or {}))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def is_command_line_auditing_enabled():
|
|
42
|
+
try:
|
|
43
|
+
# Open the registry key
|
|
44
|
+
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, AUDITING_REG_PATH, 0, winreg.KEY_READ) as reg_key:
|
|
45
|
+
# Query the value
|
|
46
|
+
value, reg_type = winreg.QueryValueEx(reg_key, PROCESS_CREATION_INCLUDE_CMDLINE_VALUE)
|
|
47
|
+
# Check if the value is 1 (enabled)
|
|
48
|
+
return value == 1
|
|
49
|
+
except FileNotFoundError:
|
|
50
|
+
# Key or value not found, assume it's not enabled
|
|
51
|
+
return False
|
|
52
|
+
except WindowsError as e:
|
|
53
|
+
print(f"Failed to read the 'Include command line in process creation events' setting: {e}")
|
|
54
|
+
return False
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def enable_audit_process_creation(print_kwargs: dict = None):
|
|
58
|
+
"""
|
|
59
|
+
Enable the 'Audit Process Creation' policy.
|
|
60
|
+
Log: Security
|
|
61
|
+
Event ID: 4688 - A new process has been created.
|
|
62
|
+
|
|
63
|
+
auditpol /set /subcategory:"Process Creation" /success:enable /failure:enable
|
|
64
|
+
|
|
65
|
+
:param print_kwargs: Optional keyword arguments for the print function.
|
|
66
|
+
"""
|
|
67
|
+
if is_audit_process_creation_enabled():
|
|
68
|
+
print_api("Audit Process Creation is already enabled.", color='blue', **(print_kwargs or {}))
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
# Enable "Audit Process Creation" policy
|
|
72
|
+
audit_policy_command = [
|
|
73
|
+
"auditpol", "/set", "/subcategory:Process Creation", "/success:enable", "/failure:enable"
|
|
74
|
+
]
|
|
75
|
+
try:
|
|
76
|
+
subprocess.run(audit_policy_command, check=True)
|
|
77
|
+
print_api("Successfully enabled 'Audit Process Creation'.", color='green', **(print_kwargs or {}))
|
|
78
|
+
except subprocess.CalledProcessError as e:
|
|
79
|
+
print_api(f"Failed to enable 'Audit Process Creation': {e}", error_type=True, color='red', **(print_kwargs or {}))
|
|
80
|
+
raise e
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def is_audit_process_creation_enabled(print_kwargs: dict = None) -> bool:
|
|
84
|
+
"""
|
|
85
|
+
Check if the 'Audit Process Creation' policy is enabled.
|
|
86
|
+
|
|
87
|
+
:param print_kwargs: Optional keyword arguments for the print function.
|
|
88
|
+
"""
|
|
89
|
+
# Command to check the "Audit Process Creation" policy
|
|
90
|
+
audit_policy_check_command = [
|
|
91
|
+
"auditpol", "/get", "/subcategory:Process Creation"
|
|
92
|
+
]
|
|
93
|
+
try:
|
|
94
|
+
result = subprocess.run(audit_policy_check_command, check=True, capture_output=True, text=True)
|
|
95
|
+
output = result.stdout
|
|
96
|
+
# print_api(output) # Print the output for inspection
|
|
97
|
+
|
|
98
|
+
if "Process Creation" in output and "Success and Failure" in output:
|
|
99
|
+
# print_api(
|
|
100
|
+
# "'Audit Process Creation' is enabled for both success and failure.",
|
|
101
|
+
# color='green', **(print_kwargs or {}))
|
|
102
|
+
return True
|
|
103
|
+
else:
|
|
104
|
+
# print_api(output, **(print_kwargs or {}))
|
|
105
|
+
# print_api(
|
|
106
|
+
# "'Audit Process Creation' is not fully enabled. Check the output above for details.",
|
|
107
|
+
# color='yellow', **(print_kwargs or {}))
|
|
108
|
+
return False
|
|
109
|
+
except subprocess.CalledProcessError as e:
|
|
110
|
+
print_api(f"Failed to check 'Audit Process Creation': {e}", color='red', error_type=True, **(print_kwargs or {}))
|
|
111
|
+
return False
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def enable_audit_process_termination(print_kwargs: dict = None):
|
|
115
|
+
"""
|
|
116
|
+
Enable the 'Audit Process Termination' policy.
|
|
117
|
+
|
|
118
|
+
:param print_kwargs: Optional keyword arguments for the print function.
|
|
119
|
+
"""
|
|
120
|
+
if is_audit_process_termination_enabled():
|
|
121
|
+
print_api("Audit Process Termination is already enabled.", color='blue', **(print_kwargs or {}))
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
audit_policy_command = [
|
|
125
|
+
"auditpol", "/set", "/subcategory:Process Termination", "/success:enable", "/failure:enable"
|
|
126
|
+
]
|
|
127
|
+
try:
|
|
128
|
+
subprocess.run(audit_policy_command, check=True)
|
|
129
|
+
print_api("Successfully enabled 'Audit Process Termination'.", color='green', **(print_kwargs or {}))
|
|
130
|
+
except subprocess.CalledProcessError as e:
|
|
131
|
+
print_api(f"Failed to enable 'Audit Process Termination': {e}", error_type=True, color='red', **(print_kwargs or {}))
|
|
132
|
+
raise e
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def is_audit_process_termination_enabled(print_kwargs: dict = None) -> bool:
|
|
136
|
+
"""
|
|
137
|
+
Check if the 'Audit Process Termination' policy is enabled.
|
|
138
|
+
|
|
139
|
+
:param print_kwargs: Optional keyword arguments for the print function.
|
|
140
|
+
"""
|
|
141
|
+
# Command to check the "Audit Process Creation" policy
|
|
142
|
+
audit_policy_check_command = [
|
|
143
|
+
"auditpol", "/get", "/subcategory:Process Termination"
|
|
144
|
+
]
|
|
145
|
+
try:
|
|
146
|
+
result = subprocess.run(audit_policy_check_command, check=True, capture_output=True, text=True)
|
|
147
|
+
output = result.stdout
|
|
148
|
+
# print_api(output) # Print the output for inspection
|
|
149
|
+
|
|
150
|
+
if "Process Termination" in output and "Success and Failure" in output:
|
|
151
|
+
# print_api(
|
|
152
|
+
# "'Audit Process Termination' is enabled for both success and failure.",
|
|
153
|
+
# color='green', **(print_kwargs or {}))
|
|
154
|
+
return True
|
|
155
|
+
else:
|
|
156
|
+
# print_api(output, **(print_kwargs or {}))
|
|
157
|
+
# print_api(
|
|
158
|
+
# "'Audit Process Termination' is not fully enabled. Check the output above for details.",
|
|
159
|
+
# color='yellow', **(print_kwargs or {}))
|
|
160
|
+
return False
|
|
161
|
+
except subprocess.CalledProcessError as e:
|
|
162
|
+
print_api(f"Failed to check 'Audit Process Termination': {e}", color='red', error_type=True, **(print_kwargs or {}))
|
|
163
|
+
return False
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def enable_audit_filtering_platform_connection(print_kwargs: dict = None):
|
|
167
|
+
"""
|
|
168
|
+
Enable the 'Filtering Platform Connection' policy.
|
|
169
|
+
This enables you to fetch connection creations and deletions from the Windows Security Event Log.
|
|
170
|
+
Log: Security
|
|
171
|
+
Event IDs:
|
|
172
|
+
5156 - The Windows Filtering Platform has permitted a connection.
|
|
173
|
+
5158 - The Windows Filtering Platform has blocked a connection.
|
|
174
|
+
Events include information about source and destination IP addresses and ports.
|
|
175
|
+
|
|
176
|
+
auditpol /set /subcategory:"Filtering Platform Connection" /success:enable /failure:enable
|
|
177
|
+
|
|
178
|
+
:param print_kwargs: Optional keyword arguments for the print function.
|
|
179
|
+
"""
|
|
180
|
+
|
|
181
|
+
audit_policy_command = [
|
|
182
|
+
"auditpol", "/set", '/subcategory:"Filtering Platform Connection"', "/success:enable", "/failure:enable"
|
|
183
|
+
]
|
|
184
|
+
try:
|
|
185
|
+
subprocess.run(audit_policy_command, check=True)
|
|
186
|
+
print_api("Successfully enabled 'Audit Filtering Platform Connection'.", color='green', **(print_kwargs or {}))
|
|
187
|
+
except subprocess.CalledProcessError as e:
|
|
188
|
+
print_api(f"Failed to enable 'Audit Filtering Platform Connection': {e}", error_type=True, color='red', **(print_kwargs or {}))
|
|
189
|
+
raise e
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: atomicshop
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.10.0
|
|
4
4
|
Summary: Atomic functions and classes to make developer life easier
|
|
5
5
|
Author: Denis Kras
|
|
6
6
|
License-Expression: MIT
|
|
@@ -8,44 +8,39 @@ Project-URL: Homepage, https://github.com/BugSec-Official/atomicshop
|
|
|
8
8
|
Classifier: Intended Audience :: Developers
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
10
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
11
|
-
Requires-Python: <3.
|
|
11
|
+
Requires-Python: <3.14,>=3.12
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE.txt
|
|
14
14
|
Requires-Dist: wheel
|
|
15
|
-
Requires-Dist:
|
|
16
|
-
Requires-Dist:
|
|
15
|
+
Requires-Dist: setuptools
|
|
16
|
+
Requires-Dist: beautifulsoup4==4.14.3
|
|
17
|
+
Requires-Dist: cryptography==46.0.3
|
|
18
|
+
Requires-Dist: dkarchiver==1.0.1
|
|
17
19
|
Requires-Dist: dkinst
|
|
18
|
-
Requires-Dist: dnslib
|
|
19
|
-
Requires-Dist: dnspython
|
|
20
|
-
Requires-Dist: docker
|
|
21
|
-
Requires-Dist: flask_socketio
|
|
22
|
-
Requires-Dist: google-api-python-client
|
|
23
|
-
Requires-Dist: google-
|
|
24
|
-
Requires-Dist: icmplib
|
|
20
|
+
Requires-Dist: dnslib==0.9.26
|
|
21
|
+
Requires-Dist: dnspython==2.8.0
|
|
22
|
+
Requires-Dist: docker==7.1.0
|
|
23
|
+
Requires-Dist: flask_socketio==5.5.1
|
|
24
|
+
Requires-Dist: google-api-python-client==2.187.0
|
|
25
|
+
Requires-Dist: google-genai==1.53.0
|
|
26
|
+
Requires-Dist: icmplib==3.0.4
|
|
25
27
|
Requires-Dist: numpy
|
|
26
|
-
Requires-Dist: olefile
|
|
27
|
-
Requires-Dist: openpyxl
|
|
28
|
-
Requires-Dist: pandas
|
|
29
|
-
Requires-Dist: paramiko
|
|
30
|
-
Requires-Dist: pefile
|
|
31
|
-
Requires-Dist: playwright
|
|
32
|
-
Requires-Dist:
|
|
33
|
-
Requires-Dist:
|
|
34
|
-
Requires-Dist:
|
|
35
|
-
Requires-Dist: pyautogui
|
|
36
|
-
Requires-Dist: pymongo
|
|
37
|
-
Requires-Dist: pyopenssl
|
|
38
|
-
Requires-Dist: python-bidi
|
|
28
|
+
Requires-Dist: olefile==0.47
|
|
29
|
+
Requires-Dist: openpyxl==3.1.5
|
|
30
|
+
Requires-Dist: pandas==2.3.3
|
|
31
|
+
Requires-Dist: paramiko==4.0.0
|
|
32
|
+
Requires-Dist: pefile==2024.8.26
|
|
33
|
+
Requires-Dist: playwright==1.56.0
|
|
34
|
+
Requires-Dist: psutil==7.1.3
|
|
35
|
+
Requires-Dist: pymongo==4.15.5
|
|
36
|
+
Requires-Dist: pyopenssl==25.3.0
|
|
39
37
|
Requires-Dist: python-docx
|
|
40
|
-
Requires-Dist:
|
|
41
|
-
Requires-Dist: pywin32; platform_system == "Windows"
|
|
42
|
-
Requires-Dist: reportlab
|
|
43
|
-
Requires-Dist: setuptools
|
|
38
|
+
Requires-Dist: pywin32==311; platform_system == "Windows"
|
|
44
39
|
Requires-Dist: SoundCard
|
|
45
40
|
Requires-Dist: soundfile
|
|
46
41
|
Requires-Dist: SpeechRecognition
|
|
47
|
-
Requires-Dist: tldextract
|
|
48
|
-
Requires-Dist: websockets
|
|
42
|
+
Requires-Dist: tldextract==5.3.0
|
|
43
|
+
Requires-Dist: websockets==15.0.1
|
|
49
44
|
Dynamic: license-file
|
|
50
45
|
|
|
51
46
|
<h1 align="center">Atomic Workshop</h1>
|