atomicshop 2.15.11__py3-none-any.whl → 3.10.5__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.
- atomicshop/__init__.py +1 -1
- atomicshop/{addons/mains → a_mains}/FACT/update_extract.py +3 -2
- atomicshop/a_mains/dns_gateway_setting.py +11 -0
- atomicshop/a_mains/get_local_tcp_ports.py +85 -0
- atomicshop/a_mains/github_wrapper.py +11 -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/a_mains/update_config_toml.py +38 -0
- atomicshop/basics/ansi_escape_codes.py +3 -1
- atomicshop/basics/argparse_template.py +2 -0
- atomicshop/basics/booleans.py +27 -30
- atomicshop/basics/bytes_arrays.py +43 -0
- atomicshop/basics/classes.py +149 -1
- atomicshop/basics/enums.py +2 -2
- atomicshop/basics/exceptions.py +5 -1
- atomicshop/basics/list_of_classes.py +29 -0
- atomicshop/basics/multiprocesses.py +374 -50
- atomicshop/basics/strings.py +72 -3
- atomicshop/basics/threads.py +14 -0
- atomicshop/basics/tracebacks.py +13 -3
- atomicshop/certificates.py +153 -52
- atomicshop/config_init.py +11 -6
- atomicshop/console_user_response.py +7 -14
- atomicshop/consoles.py +9 -0
- atomicshop/datetimes.py +1 -1
- atomicshop/diff_check.py +3 -3
- atomicshop/dns.py +128 -3
- atomicshop/etws/_pywintrace_fix.py +17 -0
- atomicshop/etws/trace.py +40 -42
- atomicshop/etws/traces/trace_dns.py +56 -44
- atomicshop/etws/traces/trace_tcp.py +130 -0
- atomicshop/file_io/csvs.py +27 -5
- atomicshop/file_io/docxs.py +34 -17
- atomicshop/file_io/file_io.py +31 -17
- atomicshop/file_io/jsons.py +49 -0
- atomicshop/file_io/tomls.py +139 -0
- atomicshop/filesystem.py +616 -291
- atomicshop/get_process_list.py +3 -3
- atomicshop/http_parse.py +149 -93
- atomicshop/ip_addresses.py +6 -1
- atomicshop/mitm/centered_settings.py +132 -0
- atomicshop/mitm/config_static.py +207 -0
- atomicshop/mitm/config_toml_editor.py +55 -0
- atomicshop/mitm/connection_thread_worker.py +875 -357
- atomicshop/mitm/engines/__parent/parser___parent.py +4 -17
- atomicshop/mitm/engines/__parent/recorder___parent.py +108 -51
- atomicshop/mitm/engines/__parent/requester___parent.py +116 -0
- atomicshop/mitm/engines/__parent/responder___parent.py +75 -114
- atomicshop/mitm/engines/__reference_general/parser___reference_general.py +10 -7
- atomicshop/mitm/engines/__reference_general/recorder___reference_general.py +5 -5
- atomicshop/mitm/engines/__reference_general/requester___reference_general.py +47 -0
- atomicshop/mitm/engines/__reference_general/responder___reference_general.py +95 -13
- atomicshop/mitm/engines/create_module_template.py +58 -14
- atomicshop/mitm/import_config.py +359 -139
- atomicshop/mitm/initialize_engines.py +160 -80
- atomicshop/mitm/message.py +64 -23
- atomicshop/mitm/mitm_main.py +892 -0
- atomicshop/mitm/recs_files.py +183 -0
- atomicshop/mitm/shared_functions.py +4 -10
- atomicshop/mitm/ssh_tester.py +82 -0
- atomicshop/mitm/statistic_analyzer.py +136 -40
- atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py +265 -83
- atomicshop/monitor/checks/dns.py +1 -1
- atomicshop/networks.py +671 -0
- atomicshop/on_exit.py +39 -9
- atomicshop/package_mains_processor.py +84 -0
- atomicshop/permissions/permissions.py +22 -0
- atomicshop/permissions/ubuntu_permissions.py +239 -0
- atomicshop/permissions/win_permissions.py +33 -0
- atomicshop/print_api.py +24 -42
- atomicshop/process.py +24 -6
- atomicshop/process_poller/process_pool.py +0 -1
- atomicshop/process_poller/simple_process_pool.py +204 -5
- atomicshop/python_file_patcher.py +1 -1
- atomicshop/python_functions.py +27 -75
- atomicshop/speech_recognize.py +8 -0
- atomicshop/ssh_remote.py +158 -172
- atomicshop/system_resource_monitor.py +61 -47
- atomicshop/system_resources.py +8 -8
- atomicshop/tempfiles.py +1 -2
- atomicshop/urls.py +6 -0
- atomicshop/venvs.py +28 -0
- atomicshop/versioning.py +27 -0
- atomicshop/web.py +98 -27
- atomicshop/web_apis/google_custom_search.py +44 -0
- atomicshop/web_apis/google_llm.py +188 -0
- atomicshop/websocket_parse.py +450 -0
- atomicshop/wrappers/certauthw/certauth.py +1 -0
- atomicshop/wrappers/cryptographyw.py +29 -8
- atomicshop/wrappers/ctyping/etw_winapi/const.py +97 -47
- atomicshop/wrappers/ctyping/etw_winapi/etw_functions.py +178 -49
- atomicshop/wrappers/ctyping/file_details_winapi.py +67 -0
- atomicshop/wrappers/ctyping/msi_windows_installer/cabs.py +2 -1
- atomicshop/wrappers/ctyping/msi_windows_installer/extract_msi_main.py +2 -2
- atomicshop/wrappers/ctyping/setup_device.py +466 -0
- atomicshop/wrappers/ctyping/win_console.py +39 -0
- atomicshop/wrappers/dockerw/dockerw.py +113 -2
- atomicshop/wrappers/elasticsearchw/config_basic.py +0 -12
- atomicshop/wrappers/elasticsearchw/elastic_infra.py +75 -0
- atomicshop/wrappers/elasticsearchw/elasticsearchw.py +2 -20
- atomicshop/wrappers/factw/get_file_data.py +12 -5
- atomicshop/wrappers/factw/install/install_after_restart.py +89 -5
- atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py +20 -14
- atomicshop/wrappers/githubw.py +537 -54
- atomicshop/wrappers/loggingw/consts.py +1 -1
- atomicshop/wrappers/loggingw/filters.py +23 -0
- atomicshop/wrappers/loggingw/formatters.py +12 -0
- atomicshop/wrappers/loggingw/handlers.py +214 -107
- atomicshop/wrappers/loggingw/loggers.py +19 -0
- atomicshop/wrappers/loggingw/loggingw.py +860 -22
- atomicshop/wrappers/loggingw/reading.py +134 -112
- atomicshop/wrappers/mongodbw/mongo_infra.py +31 -0
- atomicshop/wrappers/mongodbw/mongodbw.py +1324 -36
- atomicshop/wrappers/netshw.py +271 -0
- atomicshop/wrappers/playwrightw/engine.py +34 -19
- atomicshop/wrappers/playwrightw/infra.py +5 -0
- atomicshop/wrappers/playwrightw/javascript.py +7 -3
- atomicshop/wrappers/playwrightw/keyboard.py +14 -0
- atomicshop/wrappers/playwrightw/scenarios.py +172 -5
- atomicshop/wrappers/playwrightw/waits.py +9 -7
- atomicshop/wrappers/powershell_networking.py +80 -0
- atomicshop/wrappers/psutilw/processes.py +37 -1
- atomicshop/wrappers/psutilw/psutil_networks.py +85 -0
- atomicshop/wrappers/pyopensslw.py +9 -2
- atomicshop/wrappers/pywin32w/cert_store.py +116 -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/msft_netipaddress.py +113 -0
- atomicshop/wrappers/pywin32w/wmis/win32_networkadapterconfiguration.py +259 -0
- atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +112 -0
- atomicshop/wrappers/pywin32w/wmis/wmi_helpers.py +236 -0
- atomicshop/wrappers/socketw/accepter.py +21 -7
- atomicshop/wrappers/socketw/certificator.py +216 -150
- atomicshop/wrappers/socketw/creator.py +190 -50
- atomicshop/wrappers/socketw/dns_server.py +491 -182
- atomicshop/wrappers/socketw/exception_wrapper.py +45 -52
- atomicshop/wrappers/socketw/process_getter.py +86 -0
- atomicshop/wrappers/socketw/receiver.py +144 -102
- atomicshop/wrappers/socketw/sender.py +65 -35
- atomicshop/wrappers/socketw/sni.py +334 -165
- atomicshop/wrappers/socketw/socket_base.py +134 -0
- atomicshop/wrappers/socketw/socket_client.py +137 -95
- atomicshop/wrappers/socketw/socket_server_tester.py +11 -7
- atomicshop/wrappers/socketw/socket_wrapper.py +717 -116
- atomicshop/wrappers/socketw/ssl_base.py +15 -14
- atomicshop/wrappers/socketw/statistics_csv.py +148 -17
- atomicshop/wrappers/sysmonw.py +1 -1
- atomicshop/wrappers/ubuntu_terminal.py +65 -26
- atomicshop/wrappers/win_auditw.py +189 -0
- atomicshop/wrappers/winregw/__init__.py +0 -0
- atomicshop/wrappers/winregw/winreg_installed_software.py +58 -0
- atomicshop/wrappers/winregw/winreg_network.py +232 -0
- {atomicshop-2.15.11.dist-info → atomicshop-3.10.5.dist-info}/METADATA +31 -51
- atomicshop-3.10.5.dist-info/RECORD +306 -0
- {atomicshop-2.15.11.dist-info → atomicshop-3.10.5.dist-info}/WHEEL +1 -1
- atomicshop/_basics_temp.py +0 -101
- atomicshop/a_installs/win/fibratus.py +0 -9
- atomicshop/a_installs/win/mongodb.py +0 -9
- atomicshop/a_installs/win/pycharm.py +0 -9
- atomicshop/addons/a_setup_scripts/install_psycopg2_ubuntu.sh +0 -3
- atomicshop/addons/a_setup_scripts/install_pywintrace_0.3.cmd +0 -2
- atomicshop/addons/mains/__pycache__/install_fibratus_windows.cpython-312.pyc +0 -0
- atomicshop/addons/mains/__pycache__/msi_unpacker.cpython-312.pyc +0 -0
- atomicshop/addons/mains/install_docker_rootless_ubuntu.py +0 -11
- atomicshop/addons/mains/install_docker_ubuntu_main_sudo.py +0 -11
- atomicshop/addons/mains/install_elastic_search_and_kibana_ubuntu.py +0 -10
- atomicshop/addons/mains/install_wsl_ubuntu_lts_admin.py +0 -9
- 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/_search_in_zip.py +0 -189
- atomicshop/archiver/archiver.py +0 -34
- atomicshop/archiver/search_in_archive.py +0 -250
- atomicshop/archiver/sevenz_app_w.py +0 -86
- atomicshop/archiver/sevenzs.py +0 -44
- atomicshop/archiver/zips.py +0 -293
- atomicshop/file_types.py +0 -24
- atomicshop/mitm/config_editor.py +0 -37
- atomicshop/mitm/engines/create_module_template_example.py +0 -13
- atomicshop/mitm/initialize_mitm_server.py +0 -268
- atomicshop/pbtkmultifile_argparse.py +0 -88
- atomicshop/permissions.py +0 -151
- atomicshop/script_as_string_processor.py +0 -38
- 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 -209
- atomicshop/wrappers/elasticsearchw/infrastructure.py +0 -265
- atomicshop/wrappers/elasticsearchw/install_elastic.py +0 -232
- atomicshop/wrappers/ffmpegw.py +0 -125
- atomicshop/wrappers/fibratusw/install.py +0 -81
- atomicshop/wrappers/mongodbw/infrastructure.py +0 -53
- atomicshop/wrappers/mongodbw/install_mongodb.py +0 -190
- atomicshop/wrappers/msiw.py +0 -149
- atomicshop/wrappers/nodejsw/install_nodejs.py +0 -139
- atomicshop/wrappers/process_wrapper_pbtk.py +0 -16
- atomicshop/wrappers/psutilw/networks.py +0 -45
- atomicshop/wrappers/pycharmw.py +0 -81
- atomicshop/wrappers/socketw/base.py +0 -59
- atomicshop/wrappers/socketw/get_process.py +0 -107
- atomicshop/wrappers/wslw.py +0 -191
- atomicshop-2.15.11.dist-info/RECORD +0 -302
- /atomicshop/{addons/mains → a_mains}/FACT/factw_fact_extractor_docker_image_main_sudo.py +0 -0
- /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/{archiver → permissions}/__init__.py +0 -0
- /atomicshop/{wrappers/fibratusw → web_apis}/__init__.py +0 -0
- /atomicshop/wrappers/{nodejsw → pywin32w/wmis}/__init__.py +0 -0
- /atomicshop/wrappers/pywin32w/{wmi_win32process.py → wmis/win32process.py} +0 -0
- {atomicshop-2.15.11.dist-info → atomicshop-3.10.5.dist-info/licenses}/LICENSE.txt +0 -0
- {atomicshop-2.15.11.dist-info → atomicshop-3.10.5.dist-info}/top_level.txt +0 -0
atomicshop/certificates.py
CHANGED
|
@@ -5,9 +5,10 @@ https://oidref.com/1.3.6.1.5.5.7.3.1
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
import ssl
|
|
8
|
+
from typing import Literal, Any
|
|
8
9
|
|
|
9
10
|
from .wrappers import cryptographyw
|
|
10
|
-
from .
|
|
11
|
+
from .wrappers.pywin32w import cert_store
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
# Valid for 3 years from now
|
|
@@ -16,72 +17,172 @@ from .print_api import print_api
|
|
|
16
17
|
SECONDS_NOT_AFTER_3_YEARS = 3 * 365 * 24 * 60 * 60
|
|
17
18
|
|
|
18
19
|
|
|
19
|
-
def
|
|
20
|
+
def get_pem_certificate_from_string(certificate: str) -> str:
|
|
20
21
|
"""
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
:param certificate:
|
|
24
|
-
:
|
|
25
|
-
The problem that the issuer common name is not unique, so it can be installed multiple times.
|
|
26
|
-
:param thumbprint_only: bool, if True, will check only by the certificate thumbprint is installed in the store.
|
|
27
|
-
The problem that searching by the thumbprint will not tell you if there are multiple certificates with the same
|
|
28
|
-
issuer name.
|
|
29
|
-
:return: bool, True if certificate is installed, False if not.
|
|
22
|
+
Some PEM certificates can contain a private key. This function will return only the certificate part.
|
|
23
|
+
|
|
24
|
+
:param certificate: string, PEM certificate.
|
|
25
|
+
:return: string, certificate part.
|
|
30
26
|
"""
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
28
|
+
certificate_lines = certificate.split('\n')
|
|
29
|
+
certificate_part = ''
|
|
30
|
+
start = False
|
|
31
|
+
for line in certificate_lines:
|
|
32
|
+
if 'BEGIN CERTIFICATE' in line:
|
|
33
|
+
start = True
|
|
34
|
+
if start:
|
|
35
|
+
certificate_part += line + '\n'
|
|
36
|
+
if 'END CERTIFICATE' in line:
|
|
37
|
+
break
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
for cert, encoding, trust in ssl.enum_certificates("ROOT"):
|
|
40
|
-
store_certificate = cryptographyw.convert_object_to_x509(cert)
|
|
41
|
-
store_issuer_common_name: str = cryptographyw.get_issuer_common_name_from_x509(store_certificate)
|
|
42
|
-
store_thumbprint = cryptographyw.get_sha1_thumbprint_from_x509(store_certificate)
|
|
43
|
-
|
|
44
|
-
if issuer_only:
|
|
45
|
-
if store_issuer_common_name == issuer_common_name:
|
|
46
|
-
return True, certificate
|
|
47
|
-
elif thumbprint_only:
|
|
48
|
-
if store_thumbprint == thumbprint:
|
|
49
|
-
return True, certificate
|
|
50
|
-
elif not issuer_only and not thumbprint_only:
|
|
51
|
-
if store_thumbprint == thumbprint and store_issuer_common_name == issuer_common_name:
|
|
52
|
-
return True, certificate
|
|
39
|
+
return certificate_part
|
|
53
40
|
|
|
54
41
|
|
|
55
|
-
def
|
|
42
|
+
def write_crt_certificate_file_in_pem_format_from_pem_file(
|
|
43
|
+
pem_file_path: str,
|
|
44
|
+
crt_file_path: str
|
|
45
|
+
):
|
|
56
46
|
"""
|
|
57
|
-
The function will
|
|
47
|
+
The function will read the PEM certificate file and write it to the CRT file in PEM format.
|
|
48
|
+
The function is used to convert the PEM certificate file to the CRT file.
|
|
58
49
|
|
|
59
|
-
|
|
60
|
-
|
|
50
|
+
Basically the point here is that the CRT file is the same as the PEM file, but the extension is different,
|
|
51
|
+
and it doesn't support integrated private key.
|
|
61
52
|
|
|
62
|
-
:
|
|
53
|
+
:param pem_file_path: string, path to the PEM certificate file.
|
|
54
|
+
:param crt_file_path: string, path to the CRT certificate file.
|
|
63
55
|
"""
|
|
64
56
|
|
|
65
|
-
|
|
66
|
-
|
|
57
|
+
with open(pem_file_path, 'r') as f:
|
|
58
|
+
certificate_string = f.read()
|
|
67
59
|
|
|
68
|
-
|
|
60
|
+
certificate_pem = get_pem_certificate_from_string(certificate_string)
|
|
61
|
+
|
|
62
|
+
with open(crt_file_path, 'w') as f:
|
|
63
|
+
f.write(certificate_pem)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def is_certificate_in_store(
|
|
67
|
+
certificate: Any = None,
|
|
68
|
+
by_cert_issuer: bool = True,
|
|
69
|
+
by_cert_thumbprint: bool = True,
|
|
70
|
+
issuer_name: str = None,
|
|
71
|
+
store_location: str = "ROOT",
|
|
72
|
+
print_kwargs: dict = None
|
|
73
|
+
) -> tuple[bool, list]:
|
|
74
|
+
"""
|
|
75
|
+
The function will check if the CA certificate is installed in the Windows certificate Trusted Root store.
|
|
76
|
+
NO ADMIN RIGHTS NEEDED.
|
|
77
|
+
|
|
78
|
+
:param certificate: x509 object, certificate to check. You can search by certificate or by issuer name.
|
|
79
|
+
Supported types:
|
|
80
|
+
string that is path to file will be imported as bytes object abd converted to x509.Certificate
|
|
81
|
+
After check if it's PEM or DER format.
|
|
82
|
+
string that is PEM certificate will be converted to bytes, then x509.Certificate
|
|
83
|
+
bytes of PEM or DER will be converted to x509.Certificate.
|
|
84
|
+
x509.Certificate will be returned as is.
|
|
85
|
+
:param by_cert_issuer: bool, if True, will check only by the certificate issuer common name is installed in the store.
|
|
86
|
+
The problem if the search will be by issuer alone, that the issuer common name is not unique,
|
|
87
|
+
so it can be installed multiple times.
|
|
88
|
+
:param by_cert_thumbprint: bool, if True, will check only by the certificate thumbprint is installed in the store.
|
|
89
|
+
The problem that searching by the thumbprint alone will not tell you if there are multiple
|
|
90
|
+
certificates with the same issuer name.
|
|
91
|
+
:param issuer_name: string, issuer name to search for. You can search by certificate or by issuer name.
|
|
92
|
+
:param store_location: string, store location to search in. Default is "ROOT".
|
|
93
|
+
:param print_kwargs: dict, print_api kwargs.
|
|
94
|
+
:return: tuple(bool - True if certificate is installed and False if not, list of certificates found)
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
if not by_cert_issuer and not by_cert_thumbprint:
|
|
98
|
+
raise ValueError('At least one of the parameters "by_issuer" or "by_thumbprint" must be True.')
|
|
99
|
+
|
|
100
|
+
if not certificate and not issuer_name:
|
|
101
|
+
raise ValueError('At least one of the parameters "certificate" or "issuer_name" must be provided.')
|
|
102
|
+
elif certificate and issuer_name:
|
|
103
|
+
raise ValueError('Only one of the parameters "certificate" or "issuer_name" must be provided.')
|
|
104
|
+
|
|
105
|
+
if certificate:
|
|
106
|
+
# Make sure the certificate is x509.Certificate object.
|
|
107
|
+
certificate_x509 = cryptographyw.convert_object_to_x509(certificate, print_kwargs=print_kwargs)
|
|
108
|
+
# Get the certificate thumbprint.
|
|
109
|
+
provided_thumbprint = cryptographyw.get_sha1_thumbprint_from_x509(certificate_x509)
|
|
110
|
+
provided_issuer_common_name: str = cryptographyw.get_issuer_common_name_from_x509(certificate_x509)
|
|
111
|
+
elif issuer_name:
|
|
112
|
+
provided_thumbprint = None
|
|
113
|
+
provided_issuer_common_name = issuer_name
|
|
114
|
+
else:
|
|
115
|
+
raise ValueError('At least one of the parameters "certificate" or "issuer_name" must be provided.')
|
|
69
116
|
|
|
70
|
-
|
|
117
|
+
# Iterate over all certificates in the store specifically in the ROOT.
|
|
118
|
+
# for store in ["CA", "ROOT", "MY"]:
|
|
119
|
+
result_found_list: list = []
|
|
120
|
+
found: bool = False
|
|
121
|
+
for cert, encoding, trust in ssl.enum_certificates(store_location):
|
|
122
|
+
# Some certificates in the store can have zero or negative serial number.
|
|
123
|
+
# We will skip them, since they're deprecated by the cryptography library.
|
|
71
124
|
store_certificate = cryptographyw.convert_object_to_x509(cert)
|
|
125
|
+
if not store_certificate:
|
|
126
|
+
continue
|
|
127
|
+
|
|
72
128
|
store_issuer_common_name: str = cryptographyw.get_issuer_common_name_from_x509(store_certificate)
|
|
129
|
+
store_thumbprint = cryptographyw.get_sha1_thumbprint_from_x509(store_certificate)
|
|
73
130
|
|
|
74
|
-
if
|
|
75
|
-
|
|
131
|
+
if certificate:
|
|
132
|
+
if by_cert_issuer and not by_cert_thumbprint:
|
|
133
|
+
if store_issuer_common_name == provided_issuer_common_name:
|
|
134
|
+
result_found_list.append(store_certificate)
|
|
135
|
+
found = True
|
|
136
|
+
elif by_cert_thumbprint and not by_cert_issuer:
|
|
137
|
+
if store_thumbprint == provided_thumbprint:
|
|
138
|
+
result_found_list.append(store_certificate)
|
|
139
|
+
found = True
|
|
140
|
+
elif by_cert_issuer and by_cert_thumbprint:
|
|
141
|
+
if store_thumbprint == provided_thumbprint and store_issuer_common_name == provided_issuer_common_name:
|
|
142
|
+
result_found_list.append(store_certificate)
|
|
143
|
+
found = True
|
|
144
|
+
elif issuer_name:
|
|
145
|
+
if store_issuer_common_name == provided_issuer_common_name:
|
|
146
|
+
result_found_list.append(store_certificate)
|
|
147
|
+
found = True
|
|
148
|
+
|
|
149
|
+
return found, result_found_list
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def delete_certificate_by_issuer_name(
|
|
153
|
+
issuer_name: str,
|
|
154
|
+
store_location: Literal[
|
|
155
|
+
"ROOT",
|
|
156
|
+
"CA",
|
|
157
|
+
"MY"] = "ROOT",
|
|
158
|
+
print_kwargs: dict = None
|
|
159
|
+
):
|
|
160
|
+
"""
|
|
161
|
+
NEED ADMIN RIGHTS.
|
|
162
|
+
The function will remove all certificates with the specified issuer name.
|
|
163
|
+
There can be several certificates with this name.
|
|
76
164
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
165
|
+
:param issuer_name: string, issuer name to search for.
|
|
166
|
+
:param store_location: string, store location to search in. Default is "ROOT".
|
|
167
|
+
:param print_kwargs: dict, print_api kwargs.
|
|
168
|
+
"""
|
|
169
|
+
|
|
170
|
+
cert_store.delete_certificate_by_issuer_name(issuer_name, store_location, print_kwargs)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def install_certificate_file(
|
|
174
|
+
file_path: str,
|
|
175
|
+
store_location: Literal[
|
|
176
|
+
"ROOT", "CA", "MY"] = "ROOT",
|
|
177
|
+
print_kwargs: dict = None
|
|
178
|
+
):
|
|
179
|
+
"""
|
|
180
|
+
The function will install the certificate from the file to the specified store location.
|
|
181
|
+
NEED ADMIN RIGHTS.
|
|
182
|
+
|
|
183
|
+
:param file_path: string, full file path to the certificate file.
|
|
184
|
+
:param store_location: string, store location to install the certificate. Default is "ROOT".
|
|
185
|
+
:param print_kwargs: dict, print_api kwargs.
|
|
186
|
+
"""
|
|
86
187
|
|
|
87
|
-
|
|
188
|
+
cert_store.install_certificate_file(file_path, store_location, print_kwargs)
|
atomicshop/config_init.py
CHANGED
|
@@ -2,13 +2,17 @@ import os
|
|
|
2
2
|
|
|
3
3
|
from .file_io import tomls
|
|
4
4
|
from . import filesystem
|
|
5
|
-
from .
|
|
5
|
+
from . import print_api
|
|
6
6
|
|
|
7
7
|
CONFIG_FILE_NAME = 'config.toml'
|
|
8
8
|
CONFIG: dict = dict()
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
def get_config(
|
|
11
|
+
def get_config(
|
|
12
|
+
script_directory: str = None,
|
|
13
|
+
config_file_name: str = CONFIG_FILE_NAME,
|
|
14
|
+
print_kwargs: dict = None
|
|
15
|
+
) -> dict:
|
|
12
16
|
"""
|
|
13
17
|
Get the config file content.
|
|
14
18
|
|
|
@@ -16,6 +20,7 @@ def get_config(script_directory: str = None, config_file_name: str = CONFIG_FILE
|
|
|
16
20
|
get the working directory instead.
|
|
17
21
|
:param config_file_name: string, name of the config file. Default is 'config.toml' as specified in the constant:
|
|
18
22
|
'CONFIG_FILE_NAME'.
|
|
23
|
+
:param print_kwargs: dict, additional arguments to pass to the print function. Default is None.
|
|
19
24
|
:return: dict.
|
|
20
25
|
"""
|
|
21
26
|
|
|
@@ -25,7 +30,7 @@ def get_config(script_directory: str = None, config_file_name: str = CONFIG_FILE
|
|
|
25
30
|
if not script_directory:
|
|
26
31
|
script_directory = filesystem.get_working_directory()
|
|
27
32
|
|
|
28
|
-
CONFIG = tomls.read_toml_file(f'{script_directory}{os.sep}{config_file_name}')
|
|
33
|
+
CONFIG = tomls.read_toml_file(f'{script_directory}{os.sep}{config_file_name}', **(print_kwargs or {}))
|
|
29
34
|
return CONFIG
|
|
30
35
|
|
|
31
36
|
|
|
@@ -45,7 +50,7 @@ def write_config(
|
|
|
45
50
|
'CONFIG_FILE_NAME'.
|
|
46
51
|
:param print_message: boolean, if True, the function will print the message about the created config file.
|
|
47
52
|
Also, it will wait for the user to press Enter to exit the script.
|
|
48
|
-
If False, the function will not print anything and will not exit
|
|
53
|
+
If False, the function will not print anything and will not exit.
|
|
49
54
|
:return:
|
|
50
55
|
"""
|
|
51
56
|
|
|
@@ -62,7 +67,7 @@ def write_config(
|
|
|
62
67
|
tomls.write_toml_file(config, f'{script_directory}{os.sep}{config_file_name}')
|
|
63
68
|
|
|
64
69
|
if print_message:
|
|
65
|
-
print_api(f"Created config file: {config_file_path}", color="yellow")
|
|
66
|
-
print_api(f"You need to fill it with details.", color="yellow")
|
|
70
|
+
print_api.print_api(f"Created config file: {config_file_path}", color="yellow")
|
|
71
|
+
print_api.print_api(f"You need to fill it with details.", color="yellow")
|
|
67
72
|
input("Press Enter to exit.")
|
|
68
73
|
exit()
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
# v1.0.2 - 26.03.2023 20:40
|
|
2
1
|
import sys
|
|
3
2
|
|
|
4
3
|
|
|
5
|
-
def query_positive_negative(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
def query_positive_negative(
|
|
5
|
+
question_string: str,
|
|
6
|
+
add_first_values_to_question: bool = True,
|
|
7
|
+
positive_answers: list = None,
|
|
8
|
+
negative_answers: list = None
|
|
9
|
+
) -> bool:
|
|
9
10
|
"""
|
|
10
11
|
Ask for "yes" / "no" input to a question that is passed as a "question_string".
|
|
11
12
|
Returns 'True' for 'positive' answers and 'False' for 'negative' answers.
|
|
@@ -31,10 +32,8 @@ def query_positive_negative(question_string: str,
|
|
|
31
32
|
if add_first_values_to_question:
|
|
32
33
|
question_string = f'{question_string} [{positive_answers[0]}/{negative_answers[0]}]'
|
|
33
34
|
|
|
34
|
-
# Defining variable as False for While loop to run
|
|
35
|
-
right_answer = False
|
|
36
35
|
# As long as "right_answer" is False the loop will execute again
|
|
37
|
-
while
|
|
36
|
+
while True:
|
|
38
37
|
# Print the passed question
|
|
39
38
|
print(question_string)
|
|
40
39
|
# Get the input from the console in lowercase
|
|
@@ -42,22 +41,16 @@ def query_positive_negative(question_string: str,
|
|
|
42
41
|
|
|
43
42
|
# If the gathered value is in "Yes" answers array
|
|
44
43
|
if choice in positive_answers:
|
|
45
|
-
# "right_answer" variable is True, so the loop will not execute again
|
|
46
|
-
right_answer = True
|
|
47
44
|
# Function will return True
|
|
48
45
|
return True
|
|
49
46
|
# Else If the gathered value is in "No" answers array
|
|
50
47
|
elif choice in negative_answers:
|
|
51
|
-
# "right_answer" variable is True, so the loop will not execute again
|
|
52
|
-
right_answer = True
|
|
53
48
|
# Function will return False
|
|
54
49
|
return False
|
|
55
50
|
# If the gathered input is not in the arrays
|
|
56
51
|
else:
|
|
57
52
|
# Then output to console the message
|
|
58
53
|
print("Please respond with either:", positive_answers, negative_answers)
|
|
59
|
-
# "right_answer" variable stays False, so the loop will execute again
|
|
60
|
-
right_answer = False
|
|
61
54
|
|
|
62
55
|
|
|
63
56
|
def do_you_want_to_continue_yn(message: str) -> None:
|
atomicshop/consoles.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import msvcrt
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
# === WINDOWS ONLY FUNCTIONS ===========================================================================================
|
|
5
|
+
def wait_any_key(prompt="Press any key to continue..."):
|
|
6
|
+
print(prompt, end="", flush=True)
|
|
7
|
+
msvcrt.getch() # waits for one key press (no Enter needed)
|
|
8
|
+
print() # move to next line
|
|
9
|
+
# === EOF WINDOWS ONLY FUNCTIONS =======================================================================================
|
atomicshop/datetimes.py
CHANGED
atomicshop/diff_check.py
CHANGED
|
@@ -54,9 +54,9 @@ class DiffChecker:
|
|
|
54
54
|
function input for that object. So, not always you know what your object type during class initialization.
|
|
55
55
|
:param check_object_display_name: string, name of the object to display in the message.
|
|
56
56
|
If not specified, the provided 'check_object' will be displayed.
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
#:param aggregation: boolean, if True, the object will be aggregated with other objects in the list of objects.
|
|
58
|
+
# Meaning, that the object will be checked against the existing objects in the list, and if it is not
|
|
59
|
+
# in the list, it will be added to the list. If it is in the list, it will be ignored.
|
|
60
60
|
:param input_file_path: string, full file path for storing input file for current state of objects,
|
|
61
61
|
to check later if this state isn't updated. If this variable is left empty, all the content will be saved
|
|
62
62
|
in memory and input file will not be used.
|
atomicshop/dns.py
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
import socket
|
|
2
|
+
import argparse
|
|
3
|
+
|
|
4
|
+
# noinspection PyPackageRequirements
|
|
1
5
|
import dns.resolver
|
|
2
6
|
|
|
3
|
-
from .
|
|
7
|
+
from . import print_api
|
|
8
|
+
from . import networks
|
|
9
|
+
from .permissions import permissions
|
|
10
|
+
from .wrappers.pywin32w.wmis import win32networkadapter
|
|
11
|
+
from .wrappers import netshw
|
|
4
12
|
|
|
5
13
|
|
|
6
14
|
# Defining Dictionary of Numeric to String DNS Query Types.
|
|
@@ -52,10 +60,127 @@ def resolve_dns_localhost(domain_name: str, dns_servers_list: list = None, print
|
|
|
52
60
|
# Get only the first entry of the list of IPs [0]
|
|
53
61
|
connection_ip = function_server_address[0].to_text()
|
|
54
62
|
message = f"Resolved to [{connection_ip}]"
|
|
55
|
-
print_api(message, **print_kwargs)
|
|
63
|
+
print_api.print_api(message, **print_kwargs)
|
|
56
64
|
except dns.resolver.NXDOMAIN:
|
|
57
65
|
message = f"Domain {domain_name} doesn't exist - Couldn't resolve with {dns_servers_list}."
|
|
58
|
-
print_api(message, **print_kwargs, error_type=True, logger_method='error')
|
|
66
|
+
print_api.print_api(message, **print_kwargs, error_type=True, logger_method='error')
|
|
59
67
|
pass
|
|
60
68
|
|
|
61
69
|
return connection_ip
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def get_default_dns_gateway() -> tuple[bool, list[str]]:
|
|
73
|
+
"""
|
|
74
|
+
Get the default DNS gateway from the system.
|
|
75
|
+
:return: tuple(is dynamic boolean, list of DNS server IPv4s).
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
interfaces_with_dns_settings: list[dict] = netshw.get_netsh_ipv4()
|
|
79
|
+
|
|
80
|
+
default_interface_ipv4 = socket.gethostbyname(socket.gethostname())
|
|
81
|
+
is_dynamic, dns_servers = None, None
|
|
82
|
+
for interface in interfaces_with_dns_settings:
|
|
83
|
+
if default_interface_ipv4 in interface['ip_addresses']:
|
|
84
|
+
is_dynamic = interface['dns_mode']
|
|
85
|
+
dns_servers = interface['dns_servers']
|
|
86
|
+
break
|
|
87
|
+
|
|
88
|
+
return is_dynamic, dns_servers
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def get_default_dns_gateway_with_dns_resolver() -> list[str]:
|
|
92
|
+
"""
|
|
93
|
+
Get the default DNS gateway from the system using dns.resolver.
|
|
94
|
+
:return: tuple(is dynamic boolean, list of DNS server IPv4s).
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
resolver = dns.resolver.Resolver()
|
|
98
|
+
dns_servers = list(resolver.nameservers)
|
|
99
|
+
return dns_servers
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def set_interface_dns_gateway_static(
|
|
103
|
+
interface_name: str,
|
|
104
|
+
dns_servers: list[str]
|
|
105
|
+
) -> None:
|
|
106
|
+
"""
|
|
107
|
+
Set the DNS servers for a network adapter.
|
|
108
|
+
:param interface_name: string, adapter name as shown in the network settings.
|
|
109
|
+
:param dns_servers: list of strings, DNS server IPv4 addresses.
|
|
110
|
+
:return: None
|
|
111
|
+
"""
|
|
112
|
+
|
|
113
|
+
win32networkadapter.set_dns_server(interface_name=interface_name, dns_servers=dns_servers)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def set_interface_dns_gateway_dynamic(
|
|
117
|
+
interface_name: str = None
|
|
118
|
+
) -> None:
|
|
119
|
+
"""
|
|
120
|
+
Set the DNS servers for a network adapter to obtain them automatically from DHCP.
|
|
121
|
+
:param interface_name: string, adapter name as shown in the network settings.
|
|
122
|
+
:return: None
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
win32networkadapter.set_dns_server(
|
|
126
|
+
interface_name=interface_name, dns_servers=None)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def default_dns_gateway_main() -> int:
|
|
130
|
+
"""
|
|
131
|
+
Main function for the default DNS gateway manipulations.
|
|
132
|
+
:return: None
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
argparse_obj = argparse.ArgumentParser(description="Get/Set the DNS gateway for the network adapter.")
|
|
136
|
+
arg_action_group = argparse_obj.add_mutually_exclusive_group(required=True)
|
|
137
|
+
arg_action_group.add_argument(
|
|
138
|
+
'-g', '--get', action='store_true', help='Get the default DNS gateway for the system.')
|
|
139
|
+
arg_action_group.add_argument(
|
|
140
|
+
'-s', '--set', type=str, nargs='+',
|
|
141
|
+
help='Set static DNS gateway for the system, provide values with spaces between each value.\n'
|
|
142
|
+
' Example: -s 8.8.8.8 1.1.1.1.')
|
|
143
|
+
arg_action_group.add_argument(
|
|
144
|
+
'-d', '--dynamic', action='store_true',
|
|
145
|
+
help='Set the DNS gateway to obtain automatically from DHCP.')
|
|
146
|
+
|
|
147
|
+
arg_interface_group = argparse_obj.add_mutually_exclusive_group()
|
|
148
|
+
arg_interface_group.add_argument(
|
|
149
|
+
'-in', '--interface_name', type=str, help='Network Interface name as shown in the network settings.')
|
|
150
|
+
arg_interface_group.add_argument(
|
|
151
|
+
'-id', '--interface_default', action='store_true', help='Use the default network interface.')
|
|
152
|
+
|
|
153
|
+
args = argparse_obj.parse_args()
|
|
154
|
+
|
|
155
|
+
if (args.set or args.dynamic) and not (args.interface_name or args.interface_default):
|
|
156
|
+
print_api.print_api(
|
|
157
|
+
"Please provide the interface name [-in] or use the default interface [-id].", color='red')
|
|
158
|
+
return 1
|
|
159
|
+
|
|
160
|
+
if args.set or args.dynamic:
|
|
161
|
+
if not permissions.is_admin():
|
|
162
|
+
print_api.print_api("You need to run this script as an administrator", color='red')
|
|
163
|
+
return 1
|
|
164
|
+
|
|
165
|
+
def get_interface_name() -> str:
|
|
166
|
+
if args.interface_default:
|
|
167
|
+
return networks.get_default_interface_name()
|
|
168
|
+
else:
|
|
169
|
+
return args.interface_name
|
|
170
|
+
|
|
171
|
+
if args.get:
|
|
172
|
+
is_dynamic, dns_servers = get_default_dns_gateway()
|
|
173
|
+
|
|
174
|
+
if is_dynamic:
|
|
175
|
+
is_dynamic_string = 'Dynamic'
|
|
176
|
+
else:
|
|
177
|
+
is_dynamic_string = 'Static'
|
|
178
|
+
print_api.print_api(f'DNS Gateway: {is_dynamic_string} - {dns_servers}', color='blue')
|
|
179
|
+
elif args.set:
|
|
180
|
+
# dns_servers_list: list = args.dns_servers.split(',')
|
|
181
|
+
set_interface_dns_gateway_static(
|
|
182
|
+
dns_servers=args.set, interface_name=get_interface_name())
|
|
183
|
+
elif args.dynamic:
|
|
184
|
+
set_interface_dns_gateway_dynamic(interface_name=get_interface_name())
|
|
185
|
+
|
|
186
|
+
return 0
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Need to fix the
|
|
3
|
+
etw.etw
|
|
4
|
+
file, in the
|
|
5
|
+
EventConsumer._unpackSimpleType
|
|
6
|
+
function.
|
|
7
|
+
"""
|
|
8
|
+
"""
|
|
9
|
+
data = formatted_data.value
|
|
10
|
+
# Convert the formatted data if necessary
|
|
11
|
+
if isinstance(data, str):
|
|
12
|
+
if data.endswith(' '):
|
|
13
|
+
data = data[:-1]
|
|
14
|
+
else:
|
|
15
|
+
if out_type in tdh.TDH_CONVERTER_LOOKUP and type(data) != tdh.TDH_CONVERTER_LOOKUP[out_type]:
|
|
16
|
+
data = tdh.TDH_CONVERTER_LOOKUP[out_type](data)
|
|
17
|
+
"""
|