atomicshop 2.15.13__py3-none-any.whl → 2.16.1__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_installs/ubuntu/pycharm.py +7 -0
- atomicshop/a_installs/win/pycharm.py +2 -2
- atomicshop/{addons/mains/install_wsl_ubuntu_lts_admin.py → a_installs/win/wsl_ubuntu_lts.py} +1 -0
- atomicshop/{addons/mains → a_mains}/FACT/update_extract.py +3 -2
- atomicshop/a_mains/dns_gateway_setting.py +11 -0
- atomicshop/basics/booleans.py +14 -5
- atomicshop/dns.py +104 -0
- atomicshop/file_io/docxs.py +8 -0
- atomicshop/file_io/tomls.py +133 -0
- atomicshop/filesystem.py +5 -4
- atomicshop/get_process_list.py +3 -3
- atomicshop/mitm/config_static.py +195 -0
- atomicshop/mitm/config_toml_editor.py +55 -0
- atomicshop/mitm/connection_thread_worker.py +54 -90
- atomicshop/mitm/import_config.py +148 -139
- atomicshop/mitm/initialize_engines.py +7 -2
- atomicshop/mitm/initialize_mitm_server.py +162 -107
- atomicshop/mitm/shared_functions.py +0 -1
- atomicshop/mitm/statistic_analyzer.py +13 -1
- atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py +54 -14
- atomicshop/permissions/__init__.py +0 -0
- atomicshop/permissions/permissions.py +22 -0
- atomicshop/{permissions.py → permissions/ubuntu_permissions.py} +4 -54
- atomicshop/permissions/win_permissions.py +33 -0
- atomicshop/script_as_string_processor.py +5 -1
- atomicshop/wrappers/cryptographyw.py +3 -3
- atomicshop/wrappers/dockerw/install_docker.py +6 -5
- atomicshop/wrappers/elasticsearchw/install_elastic.py +2 -1
- atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py +5 -4
- atomicshop/wrappers/mongodbw/install_mongodb.py +2 -1
- atomicshop/wrappers/msiw.py +2 -3
- atomicshop/wrappers/psutilw/networks.py +25 -1
- atomicshop/wrappers/pycharmw/__init__.py +0 -0
- atomicshop/wrappers/pycharmw/ubuntu.py +38 -0
- atomicshop/wrappers/{pycharmw.py → pycharmw/win.py} +2 -2
- atomicshop/wrappers/pywin32w/wmis/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/wmis/helpers.py +127 -0
- atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +167 -0
- atomicshop/wrappers/socketw/accepter.py +8 -8
- atomicshop/wrappers/socketw/base.py +13 -0
- atomicshop/wrappers/socketw/certificator.py +202 -149
- atomicshop/wrappers/socketw/creator.py +15 -35
- atomicshop/wrappers/socketw/dns_server.py +155 -102
- atomicshop/wrappers/socketw/exception_wrapper.py +8 -27
- atomicshop/wrappers/socketw/get_process.py +115 -95
- atomicshop/wrappers/socketw/sni.py +298 -164
- atomicshop/wrappers/socketw/socket_client.py +5 -12
- atomicshop/wrappers/socketw/socket_server_tester.py +1 -1
- atomicshop/wrappers/socketw/socket_wrapper.py +328 -72
- atomicshop/wrappers/socketw/statistics_csv.py +94 -16
- atomicshop/wrappers/ubuntu_terminal.py +6 -6
- atomicshop/wrappers/wslw.py +1 -0
- {atomicshop-2.15.13.dist-info → atomicshop-2.16.1.dist-info}/METADATA +1 -1
- {atomicshop-2.15.13.dist-info → atomicshop-2.16.1.dist-info}/RECORD +63 -54
- atomicshop/addons/mains/__pycache__/install_fibratus_windows.cpython-312.pyc +0 -0
- atomicshop/addons/mains/__pycache__/msi_unpacker.cpython-312.pyc +0 -0
- atomicshop/mitm/config_editor.py +0 -37
- /atomicshop/{addons/mains/install_docker_rootless_ubuntu.py → a_installs/ubuntu/docker_rootless.py} +0 -0
- /atomicshop/{addons/mains/install_docker_ubuntu_main_sudo.py → a_installs/ubuntu/docker_sudo.py} +0 -0
- /atomicshop/{addons/mains/install_elastic_search_and_kibana_ubuntu.py → a_installs/ubuntu/elastic_search_and_kibana.py} +0 -0
- /atomicshop/{addons/mains → a_mains}/FACT/factw_fact_extractor_docker_image_main_sudo.py +0 -0
- /atomicshop/wrappers/pywin32w/{wmi_win32process.py → wmis/win32process.py} +0 -0
- {atomicshop-2.15.13.dist-info → atomicshop-2.16.1.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.15.13.dist-info → atomicshop-2.16.1.dist-info}/WHEEL +0 -0
- {atomicshop-2.15.13.dist-info → atomicshop-2.16.1.dist-info}/top_level.txt +0 -0
atomicshop/__init__.py
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import os
|
|
2
2
|
|
|
3
|
+
from atomicshop import filesystem
|
|
3
4
|
from atomicshop.wrappers.factw.fact_extractor import get_extractor
|
|
4
5
|
from atomicshop.wrappers.factw import config_install
|
|
5
|
-
from atomicshop import
|
|
6
|
+
from atomicshop.permissions import ubuntu_permissions
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
def main():
|
|
9
10
|
get_extractor.get_extractor_script()
|
|
10
11
|
fact_extractor_executable_path: str = (
|
|
11
12
|
filesystem.get_working_directory() + os.sep + config_install.FACT_EXTRACTOR_FILE_NAME)
|
|
12
|
-
|
|
13
|
+
ubuntu_permissions.set_executable(fact_extractor_executable_path)
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
if __name__ == '__main__':
|
atomicshop/basics/booleans.py
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
def check_3_booleans_when_only_1_can_be_true(
|
|
1
|
+
def check_3_booleans_when_only_1_can_be_true(
|
|
2
|
+
boolean1: tuple,
|
|
3
|
+
boolean2: tuple,
|
|
4
|
+
boolean3: tuple
|
|
5
|
+
) -> None:
|
|
2
6
|
"""
|
|
7
|
+
Check if only one boolean can be 'True' from 3 booleans
|
|
8
|
+
|
|
9
|
+
:param boolean1: tuple, (value, string name of the setting you want to print to the user to be aware of).
|
|
10
|
+
:param boolean2: tuple, (value, string name of the setting you want to print to the user to be aware of).
|
|
11
|
+
:param boolean3: tuple, (value, string name of the setting you want to print to the user to be aware of).
|
|
12
|
+
:return:
|
|
13
|
+
|
|
14
|
+
------------------------------------------------
|
|
15
|
+
|
|
3
16
|
Example:
|
|
4
17
|
check_3_booleans_when_only_1_can_be_true(
|
|
5
18
|
(self.config['section']['default_usage'], 'default_usage'),
|
|
6
19
|
(self.config['section']['create_usage'], 'create_usage'),
|
|
7
20
|
(self.config['section']['custom_usage'], 'custom_usage'))
|
|
8
|
-
:param boolean1: tuple, (value, string name of the setting you want to print to the user to be aware of).
|
|
9
|
-
:param boolean2: tuple, (value, string name of the setting you want to print to the user to be aware of).
|
|
10
|
-
:param boolean3: tuple, (value, string name of the setting you want to print to the user to be aware of).
|
|
11
|
-
:return:
|
|
12
21
|
"""
|
|
13
22
|
|
|
14
23
|
check_if_3_booleans_are_false(boolean1, boolean2, boolean3)
|
atomicshop/dns.py
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
|
|
1
3
|
import dns.resolver
|
|
2
4
|
|
|
3
5
|
from .print_api import print_api
|
|
6
|
+
from .permissions import permissions
|
|
7
|
+
from .wrappers.pywin32w.wmis import win32networkadapter
|
|
4
8
|
|
|
5
9
|
|
|
6
10
|
# Defining Dictionary of Numeric to String DNS Query Types.
|
|
@@ -59,3 +63,103 @@ def resolve_dns_localhost(domain_name: str, dns_servers_list: list = None, print
|
|
|
59
63
|
pass
|
|
60
64
|
|
|
61
65
|
return connection_ip
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_default_dns_gateway() -> tuple[bool, list[str]]:
|
|
69
|
+
"""
|
|
70
|
+
Get the default DNS gateway from the system.
|
|
71
|
+
:return: tuple(is dynamic boolean, list of DNS server IPv4s).
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
resolver = dns.resolver.Resolver()
|
|
75
|
+
dns_servers = list(resolver.nameservers)
|
|
76
|
+
|
|
77
|
+
is_dynamic = win32networkadapter.is_adapter_dns_gateway_from_dhcp(use_default_interface=True)
|
|
78
|
+
return is_dynamic, dns_servers
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def set_connection_dns_gateway_static(
|
|
82
|
+
dns_servers: list[str],
|
|
83
|
+
connection_name: str = None,
|
|
84
|
+
use_default_connection: bool = False
|
|
85
|
+
) -> None:
|
|
86
|
+
"""
|
|
87
|
+
Set the DNS servers for a network adapter.
|
|
88
|
+
:param connection_name: string, adapter name as shown in the network settings.
|
|
89
|
+
:param dns_servers: list of strings, DNS server IPv4 addresses.
|
|
90
|
+
:param use_default_connection: bool, if True, the default network interface will be used. This is the connection
|
|
91
|
+
that you internet is being used from.
|
|
92
|
+
:return: None
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
win32networkadapter.set_dns_server(
|
|
96
|
+
connection_name=connection_name, dns_servers=dns_servers, use_default_interface=use_default_connection)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def set_connection_dns_gateway_dynamic(
|
|
100
|
+
connection_name: str = None,
|
|
101
|
+
use_default_connection: bool = False
|
|
102
|
+
) -> None:
|
|
103
|
+
"""
|
|
104
|
+
Set the DNS servers for a network adapter to obtain them automatically from DHCP.
|
|
105
|
+
:param connection_name: string, adapter name as shown in the network settings.
|
|
106
|
+
:param use_default_connection: bool, if True, the default network interface will be used. This is the connection
|
|
107
|
+
that you internet is being used from.
|
|
108
|
+
:return: None
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
win32networkadapter.set_dns_server(
|
|
112
|
+
connection_name=connection_name, dns_servers=None, use_default_interface=use_default_connection)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def default_dns_gateway_main() -> int:
|
|
116
|
+
"""
|
|
117
|
+
Main function for the default DNS gateway manipulations.
|
|
118
|
+
:return: None
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
argparse_obj = argparse.ArgumentParser(description="Get/Set the DNS gateway for the network adapter.")
|
|
122
|
+
arg_action_group = argparse_obj.add_mutually_exclusive_group(required=True)
|
|
123
|
+
arg_action_group.add_argument(
|
|
124
|
+
'-g', '--get', action='store_true', help='Get the default DNS gateway for the system.')
|
|
125
|
+
arg_action_group.add_argument(
|
|
126
|
+
'-s', '--set', type=str, nargs='+',
|
|
127
|
+
help='Set static DNS gateway for the system, provide values with spaces between each value.\n'
|
|
128
|
+
' Example: -s 8.8.8.8 1.1.1.1.')
|
|
129
|
+
arg_action_group.add_argument(
|
|
130
|
+
'-d', '--dynamic', action='store_true',
|
|
131
|
+
help='Set the DNS gateway to obtain automatically from DHCP.')
|
|
132
|
+
|
|
133
|
+
arg_connection_group = argparse_obj.add_mutually_exclusive_group()
|
|
134
|
+
arg_connection_group.add_argument(
|
|
135
|
+
'-cn', '--connection_name', type=str, help='Connection name as shown in the network settings.')
|
|
136
|
+
arg_connection_group.add_argument(
|
|
137
|
+
'-cd', '--connection_default', action='store_true', help='Use the default connection.')
|
|
138
|
+
|
|
139
|
+
args = argparse_obj.parse_args()
|
|
140
|
+
|
|
141
|
+
if (args.set or args.dynamic) and not (args.connection_name or args.connection_default):
|
|
142
|
+
print_api("Please provide the connection name [-cn] or use the default connection [-cd].", color='red')
|
|
143
|
+
return 1
|
|
144
|
+
|
|
145
|
+
if args.set or args.dynamic:
|
|
146
|
+
if not permissions.is_admin():
|
|
147
|
+
print_api("You need to run this script as an administrator", color='red')
|
|
148
|
+
return 1
|
|
149
|
+
|
|
150
|
+
if args.get:
|
|
151
|
+
is_dynamic, dns_servers = get_default_dns_gateway()
|
|
152
|
+
|
|
153
|
+
if is_dynamic:
|
|
154
|
+
is_dynamic_string = 'Dynamic'
|
|
155
|
+
else:
|
|
156
|
+
is_dynamic_string = 'Static'
|
|
157
|
+
print_api(f'DNS Gateway: {is_dynamic_string} - {dns_servers}', color='blue')
|
|
158
|
+
elif args.set:
|
|
159
|
+
# dns_servers_list: list = args.dns_servers.split(',')
|
|
160
|
+
set_connection_dns_gateway_static(
|
|
161
|
+
dns_servers=args.set, connection_name=args.connection_name,
|
|
162
|
+
use_default_connection=args.connection_default)
|
|
163
|
+
elif args.dynamic:
|
|
164
|
+
set_connection_dns_gateway_dynamic(
|
|
165
|
+
connection_name=args.connection_name, use_default_connection=args.connection_default)
|
atomicshop/file_io/docxs.py
CHANGED
|
@@ -26,6 +26,14 @@ def get_hyperlinks(docx_path):
|
|
|
26
26
|
if not paragraph.hyperlinks:
|
|
27
27
|
continue
|
|
28
28
|
for hyperlink in paragraph.hyperlinks:
|
|
29
|
+
# Hyperlinks are stored in docx (document.xml) without the fragment part.
|
|
30
|
+
# Fragment is the anchor of the link, for example: 'https://www.example.com#anchor'.
|
|
31
|
+
# So the hyperlink.address is stored as 'https://www.example.com'.
|
|
32
|
+
# And the fragment is stored in the hyperlink.fragment as 'anchor'.
|
|
33
|
+
# For the full hyperlink, we need to concatenate the address and the fragment.
|
|
34
|
+
# If there is no anchor in the link the fragment will be empty string ('').
|
|
35
|
+
if hyperlink.fragment:
|
|
36
|
+
hyperlinks.append(hyperlink.address + "#" + hyperlink.fragment)
|
|
29
37
|
hyperlinks.append(hyperlink.address)
|
|
30
38
|
|
|
31
39
|
return hyperlinks
|
atomicshop/file_io/tomls.py
CHANGED
|
@@ -10,6 +10,10 @@ except ModuleNotFoundError:
|
|
|
10
10
|
from . import file_io
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
class TomlValueNotImplementedError(Exception):
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
|
|
13
17
|
@file_io.read_file_decorator
|
|
14
18
|
def read_toml_file(file_path: str,
|
|
15
19
|
file_mode: str = 'rb',
|
|
@@ -84,3 +88,132 @@ def dumps(toml_dict: dict):
|
|
|
84
88
|
toml_string += process_item(key, value)
|
|
85
89
|
|
|
86
90
|
return toml_string
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def update_toml_file_with_new_config(
|
|
94
|
+
main_config_file_path: str,
|
|
95
|
+
changes_config_file_path: str = None,
|
|
96
|
+
changes_dict: dict = None,
|
|
97
|
+
new_config_file_path: str = None
|
|
98
|
+
) -> None:
|
|
99
|
+
"""
|
|
100
|
+
Update the old toml config file with the new values from the new toml config file.
|
|
101
|
+
This will update only the changed values.
|
|
102
|
+
If the values from the changes file aren't present in the main config file, they will not be added.
|
|
103
|
+
|
|
104
|
+
:param main_config_file_path: string, path to the main config file that you want to use as the main reference.
|
|
105
|
+
If you provide the 'new_config_file_path', then changes to the 'main_config_file_path' will be written there.
|
|
106
|
+
:param changes_config_file_path: string, the config file path that have the changes.
|
|
107
|
+
Only changed values will be updated to the 'main_config_file_path'.
|
|
108
|
+
:param changes_dict: dict, the dictionary with the changes.
|
|
109
|
+
Instead of providing the 'changes_config_file_path', you can provide only the dictionary with the changes.
|
|
110
|
+
:param new_config_file_path: string, path to the new config file.
|
|
111
|
+
If provided, the changes will be written to this file.
|
|
112
|
+
If not, the changes will be written to the 'main_config_file_path'.
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
# Sync the config files.
|
|
116
|
+
with open(main_config_file_path, 'r') as file:
|
|
117
|
+
main_config_file_text_lines: list = file.readlines()
|
|
118
|
+
|
|
119
|
+
main_config_file_text_lines_backup: list = list(main_config_file_text_lines)
|
|
120
|
+
|
|
121
|
+
# Read the new config file.
|
|
122
|
+
main_config_file_dict: dict = read_toml_file(main_config_file_path)
|
|
123
|
+
|
|
124
|
+
if changes_dict:
|
|
125
|
+
changes_config_file_dict = changes_dict
|
|
126
|
+
else:
|
|
127
|
+
changes_config_file_dict: dict = read_toml_file(changes_config_file_path)
|
|
128
|
+
|
|
129
|
+
# Update the config text lines.
|
|
130
|
+
for category, settings in main_config_file_dict.items():
|
|
131
|
+
if category not in changes_config_file_dict:
|
|
132
|
+
continue
|
|
133
|
+
|
|
134
|
+
for key, value in settings.items():
|
|
135
|
+
# If the key is in the old config file, use the old value.
|
|
136
|
+
if key not in changes_config_file_dict[category]:
|
|
137
|
+
continue
|
|
138
|
+
|
|
139
|
+
if main_config_file_dict[category][key] != changes_config_file_dict[category][key]:
|
|
140
|
+
# Get the line of the current category line.
|
|
141
|
+
current_category_line_index_in_text = None
|
|
142
|
+
for current_category_line_index_in_text, line in enumerate(main_config_file_text_lines):
|
|
143
|
+
if f"[{category}]" in line:
|
|
144
|
+
break
|
|
145
|
+
|
|
146
|
+
# current_category_line_index_in_text = main_config_file_text_lines.index(f"[{category}]\n")
|
|
147
|
+
current_category_index_in_main_config_dict = list(main_config_file_dict.keys()).index(category)
|
|
148
|
+
|
|
149
|
+
try:
|
|
150
|
+
next_category_name = list(
|
|
151
|
+
main_config_file_dict.keys())[current_category_index_in_main_config_dict + 1]
|
|
152
|
+
except IndexError:
|
|
153
|
+
next_category_name = list(main_config_file_dict.keys())[-1]
|
|
154
|
+
|
|
155
|
+
next_category_line_index_in_text = None
|
|
156
|
+
for next_category_line_index_in_text, line in enumerate(main_config_file_text_lines):
|
|
157
|
+
if f"[{next_category_name}]" in line:
|
|
158
|
+
break
|
|
159
|
+
|
|
160
|
+
# In case the current and the next categories are the same and the last in the file.
|
|
161
|
+
if next_category_line_index_in_text == current_category_line_index_in_text:
|
|
162
|
+
next_category_line_index_in_text = len(main_config_file_text_lines)
|
|
163
|
+
|
|
164
|
+
string_to_check_list: list = list()
|
|
165
|
+
if isinstance(value, bool):
|
|
166
|
+
string_to_check_list.append(f"{key} = {str(value).lower()}")
|
|
167
|
+
elif isinstance(value, int):
|
|
168
|
+
string_to_check_list.append(f"{key} = {value}")
|
|
169
|
+
elif isinstance(value, str):
|
|
170
|
+
string_to_check_list.append(f"{key} = '{value}'")
|
|
171
|
+
string_to_check_list.append(f'{key} = "{value}"')
|
|
172
|
+
else:
|
|
173
|
+
raise TomlValueNotImplementedError(f"Value type '{type(value)}' not implemented.")
|
|
174
|
+
|
|
175
|
+
# next_category_line_index_in_text = main_config_file_text_lines.index(f"[{next_category_name}]\n")
|
|
176
|
+
# Find the index of this line in the text file between current category line and
|
|
177
|
+
# the next category line.
|
|
178
|
+
line_index = None
|
|
179
|
+
found_line = False
|
|
180
|
+
for line_index in range(current_category_line_index_in_text, next_category_line_index_in_text):
|
|
181
|
+
if found_line:
|
|
182
|
+
line_index = line_index - 1
|
|
183
|
+
break
|
|
184
|
+
for string_to_check in string_to_check_list:
|
|
185
|
+
if string_to_check in main_config_file_text_lines[line_index]:
|
|
186
|
+
found_line = True
|
|
187
|
+
break
|
|
188
|
+
|
|
189
|
+
if found_line:
|
|
190
|
+
# If there are comments, get only them from the line. Comment will also get the '\n' character.
|
|
191
|
+
# noinspection PyUnboundLocalVariable
|
|
192
|
+
comment = main_config_file_text_lines[line_index].replace(string_to_check, '')
|
|
193
|
+
|
|
194
|
+
object_type = type(changes_config_file_dict[category][key])
|
|
195
|
+
if object_type == bool:
|
|
196
|
+
value_string_to_set = str(changes_config_file_dict[category][key]).lower()
|
|
197
|
+
elif object_type == str:
|
|
198
|
+
value_string_to_set = f"'{changes_config_file_dict[category][key]}'"
|
|
199
|
+
elif object_type == int:
|
|
200
|
+
value_string_to_set = str(changes_config_file_dict[category][key])
|
|
201
|
+
|
|
202
|
+
# noinspection PyUnboundLocalVariable
|
|
203
|
+
line_to_set = f"{key} = {value_string_to_set}{comment}"
|
|
204
|
+
# Replace the line with the old value.
|
|
205
|
+
main_config_file_text_lines[line_index] = line_to_set
|
|
206
|
+
|
|
207
|
+
main_config_file_dict[category][key] = changes_config_file_dict[category][key]
|
|
208
|
+
|
|
209
|
+
if new_config_file_path:
|
|
210
|
+
file_path_to_write = new_config_file_path
|
|
211
|
+
else:
|
|
212
|
+
file_path_to_write = main_config_file_path
|
|
213
|
+
|
|
214
|
+
if not main_config_file_text_lines == main_config_file_text_lines_backup:
|
|
215
|
+
# Write the final config file.
|
|
216
|
+
with open(file_path_to_write, 'w') as file:
|
|
217
|
+
file.writelines(main_config_file_text_lines)
|
|
218
|
+
else:
|
|
219
|
+
print("No changes to the config file.")
|
atomicshop/filesystem.py
CHANGED
|
@@ -240,7 +240,7 @@ def check_absolute_path___add_full(filesystem_path: str, full_path_to_add: str)
|
|
|
240
240
|
"""
|
|
241
241
|
|
|
242
242
|
if not check_absolute_path(filesystem_path):
|
|
243
|
-
return f'{full_path_to_add}{os.sep}{
|
|
243
|
+
return f'{full_path_to_add}{os.sep}{remove_last_separator(filesystem_path)}'
|
|
244
244
|
else:
|
|
245
245
|
return filesystem_path
|
|
246
246
|
|
|
@@ -815,10 +815,11 @@ def remove_last_separator(directory_path: str) -> str:
|
|
|
815
815
|
return directory_path.removesuffix(os.sep)
|
|
816
816
|
|
|
817
817
|
|
|
818
|
-
def
|
|
818
|
+
def remove_last_separator(filesystem_path: str) -> str:
|
|
819
819
|
"""
|
|
820
|
-
The function removes the
|
|
821
|
-
|
|
820
|
+
The function removes the last character in 'filesystem_path' if it is a system separator ('/' or '\')
|
|
821
|
+
returning the processed string.
|
|
822
|
+
If the character is not a separator, nothing happens.
|
|
822
823
|
|
|
823
824
|
:param filesystem_path:
|
|
824
825
|
:return:
|
atomicshop/get_process_list.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import Union, Literal
|
|
2
2
|
|
|
3
|
-
from .wrappers.pywin32w import
|
|
3
|
+
from .wrappers.pywin32w.wmis import win32process
|
|
4
4
|
from .wrappers.psutilw import psutilw
|
|
5
5
|
from .basics import dicts
|
|
6
6
|
from . import get_process_name_cmd_dll
|
|
@@ -36,7 +36,7 @@ class GetProcessList:
|
|
|
36
36
|
self.process_polling_instance = psutilw.PsutilProcesses()
|
|
37
37
|
self.connected = True
|
|
38
38
|
elif self.get_method == 'pywin32':
|
|
39
|
-
self.process_polling_instance =
|
|
39
|
+
self.process_polling_instance = win32process.Pywin32Processes()
|
|
40
40
|
elif self.get_method == 'process_dll':
|
|
41
41
|
self.process_polling_instance = get_process_name_cmd_dll.ProcessNameCmdline()
|
|
42
42
|
|
|
@@ -130,4 +130,4 @@ test = get_process_list.get_processes()
|
|
|
130
130
|
|
|
131
131
|
# globals need to be specified, otherwise the setup_code won't work with passed variables.
|
|
132
132
|
times = timeit.timeit(setup=setup_code, stmt=test_code, number=times_to_test, globals=locals())
|
|
133
|
-
print(f'Execution time: {times}')
|
|
133
|
+
print(f'Execution time: {times}')
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
|
|
4
|
+
from . import import_config
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
SCRIPT_VERSION: str = '1.7.0'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# CONFIG = None
|
|
11
|
+
LIST_OF_BOOLEANS: list = [
|
|
12
|
+
('dns', 'enable'),
|
|
13
|
+
('dns', 'offline_mode'),
|
|
14
|
+
('dns', 'resolve_to_tcp_server_only_engine_domains'),
|
|
15
|
+
('dns', 'resolve_to_tcp_server_all_domains'),
|
|
16
|
+
('dns', 'resolve_regular'),
|
|
17
|
+
('dns', 'set_default_dns_gateway_to_localhost'),
|
|
18
|
+
('dns', 'set_default_dns_gateway_to_default_interface_ipv4'),
|
|
19
|
+
('tcp', 'enable'),
|
|
20
|
+
('tcp', 'engines_usage'),
|
|
21
|
+
('tcp', 'server_response_mode'),
|
|
22
|
+
('certificates', 'default_server_certificate_usage'),
|
|
23
|
+
('certificates', 'sni_add_new_domains_to_default_server_certificate'),
|
|
24
|
+
('certificates', 'custom_server_certificate_usage'),
|
|
25
|
+
('certificates', 'sni_create_server_certificate_for_each_domain'),
|
|
26
|
+
('certificates', 'sni_get_server_certificate_from_server_socket'),
|
|
27
|
+
('skip_extensions', 'tls_web_client_authentication'),
|
|
28
|
+
('skip_extensions', 'crl_distribution_points'),
|
|
29
|
+
('skip_extensions', 'authority_information_access'),
|
|
30
|
+
('process_name', 'get_process_name')
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
TOML_TO_STATIC_CATEGORIES: dict = {
|
|
35
|
+
'dns': 'DNSServer',
|
|
36
|
+
'tcp': 'TCPServer',
|
|
37
|
+
'log': 'Log',
|
|
38
|
+
'recorder': 'Recorder',
|
|
39
|
+
'certificates': 'Certificates',
|
|
40
|
+
'skip_extensions': 'SkipExtensions',
|
|
41
|
+
'process_name': 'ProcessName'
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class MainConfig:
|
|
46
|
+
SCRIPT_DIRECTORY: str = None
|
|
47
|
+
|
|
48
|
+
ENGINES_DIRECTORY_PATH: str = None
|
|
49
|
+
ENGINES_DIRECTORY_NAME: str = "engines"
|
|
50
|
+
ENGINE_CONFIG_FILE_NAME: str = "engine_config.toml"
|
|
51
|
+
|
|
52
|
+
# Certificates.
|
|
53
|
+
default_server_certificate_name: str = 'default'
|
|
54
|
+
ca_certificate_name: str = 'ElaborateCA'
|
|
55
|
+
# CA Certificate name and file name without extension.
|
|
56
|
+
ca_certificate_filepath: str = None
|
|
57
|
+
# Default server certificate file name and path.
|
|
58
|
+
default_server_certificate_filename = f'{default_server_certificate_name}.pem'
|
|
59
|
+
default_server_certificate_filepath: str = None
|
|
60
|
+
|
|
61
|
+
@classmethod
|
|
62
|
+
def update(cls):
|
|
63
|
+
# This runs after the dataclass is initialized
|
|
64
|
+
cls.ENGINES_DIRECTORY_PATH = cls.SCRIPT_DIRECTORY + os.sep + cls.ENGINES_DIRECTORY_NAME
|
|
65
|
+
cls.ca_certificate_filepath = f'{cls.SCRIPT_DIRECTORY}{os.sep}{cls.ca_certificate_name}.pem'
|
|
66
|
+
cls.default_server_certificate_filepath = \
|
|
67
|
+
f'{cls.SCRIPT_DIRECTORY}{os.sep}{cls.default_server_certificate_filename}'
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@dataclass
|
|
71
|
+
class DNSServer:
|
|
72
|
+
enable: bool
|
|
73
|
+
offline_mode: bool
|
|
74
|
+
|
|
75
|
+
listening_interface: str
|
|
76
|
+
listening_port: int
|
|
77
|
+
forwarding_dns_service_ipv4: str
|
|
78
|
+
cache_timeout_minutes: int
|
|
79
|
+
|
|
80
|
+
resolve_to_tcp_server_only_engine_domains: bool
|
|
81
|
+
resolve_to_tcp_server_all_domains: bool
|
|
82
|
+
resolve_regular: bool
|
|
83
|
+
target_tcp_server_ipv4: str
|
|
84
|
+
|
|
85
|
+
set_default_dns_gateway: str
|
|
86
|
+
set_default_dns_gateway_to_localhost: bool
|
|
87
|
+
set_default_dns_gateway_to_default_interface_ipv4: bool
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@dataclass
|
|
91
|
+
class TCPServer:
|
|
92
|
+
enable: bool
|
|
93
|
+
|
|
94
|
+
engines_usage: bool
|
|
95
|
+
server_response_mode: bool
|
|
96
|
+
|
|
97
|
+
listening_interface: str
|
|
98
|
+
listening_port_list: list[int]
|
|
99
|
+
|
|
100
|
+
forwarding_dns_service_ipv4_list___only_for_localhost: list[str]
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@dataclass
|
|
104
|
+
class Log:
|
|
105
|
+
logs_path: str
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@dataclass
|
|
109
|
+
class Recorder:
|
|
110
|
+
recordings_path: str
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@dataclass
|
|
114
|
+
class Certificates:
|
|
115
|
+
default_server_certificate_usage: bool
|
|
116
|
+
sni_add_new_domains_to_default_server_certificate: bool
|
|
117
|
+
|
|
118
|
+
custom_server_certificate_usage: bool
|
|
119
|
+
custom_server_certificate_path: str
|
|
120
|
+
custom_private_key_path: str
|
|
121
|
+
|
|
122
|
+
sni_create_server_certificate_for_each_domain: bool
|
|
123
|
+
sni_server_certificates_cache_directory: str
|
|
124
|
+
sni_get_server_certificate_from_server_socket: bool
|
|
125
|
+
sni_server_certificate_from_server_socket_download_directory: str
|
|
126
|
+
|
|
127
|
+
domains_all_times: list[str]
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@dataclass
|
|
131
|
+
class SkipExtensions:
|
|
132
|
+
tls_web_client_authentication: bool
|
|
133
|
+
crl_distribution_points: bool
|
|
134
|
+
authority_information_access: bool
|
|
135
|
+
|
|
136
|
+
SKIP_EXTENSION_ID_LIST: list
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@dataclass
|
|
140
|
+
class ProcessName:
|
|
141
|
+
get_process_name: bool
|
|
142
|
+
ssh_user: str
|
|
143
|
+
ssh_pass: str
|
|
144
|
+
|
|
145
|
+
ssh_script_to_execute = 'process_from_port'
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def load_config(config_toml_file_path: str):
|
|
149
|
+
# global CONFIG
|
|
150
|
+
|
|
151
|
+
script_path = os.path.dirname(config_toml_file_path)
|
|
152
|
+
MainConfig.SCRIPT_DIRECTORY = script_path
|
|
153
|
+
MainConfig.update()
|
|
154
|
+
|
|
155
|
+
# Load the configuration file.
|
|
156
|
+
result = import_config.import_config_file(config_toml_file_path)
|
|
157
|
+
return result
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
# ============ Server Tester Specific ===============
|
|
161
|
+
CONFIG_INI_TESTER_FILE_NAME: str = 'config_tester.ini'
|
|
162
|
+
|
|
163
|
+
"""
|
|
164
|
+
config.ini:
|
|
165
|
+
target_domain_or_ip: the domain or ip that the requests will be sent to. Better use domains, for better testing
|
|
166
|
+
simulation.
|
|
167
|
+
target_port: the port that requests will be sent to.
|
|
168
|
+
request_type: type of each request: json / string / binary.
|
|
169
|
+
json format that contain a key with hex string of the request that will be converted to bytes.
|
|
170
|
+
string that will contain a request and will be converted to bytes.
|
|
171
|
+
binary file that will contain all request data - will be converted to bytes.
|
|
172
|
+
request_json_hex_key_list: this key stores raw request in hex format, since there can be characters that can't be
|
|
173
|
+
decoded to string / unicode.
|
|
174
|
+
'request_raw_hex' key is the default key in recorded files from mitm server, you may add keys for your custom
|
|
175
|
+
JSON files.
|
|
176
|
+
requests_directory: the directory that requests are will be taken from. Can be relative folder that will be in
|
|
177
|
+
current working directory.
|
|
178
|
+
|
|
179
|
+
parallel_connections_bool: boolean, sets if sockets should be initialized in threads (in parallel) or one after another.
|
|
180
|
+
Use all the connections / cycles in parallel when 'True'. New sockets will be created for each request.
|
|
181
|
+
Reuse the same socket / connection for all the requests when 'False'.
|
|
182
|
+
interval_between_requests_defaults_seconds: default interval in seconds between request sends.
|
|
183
|
+
interval_between_request_custom_list_seconds: list of intervals in seconds. If this configuration will not be empty,
|
|
184
|
+
this should be a list. Each interval in the list will follow the interval between requests and
|
|
185
|
+
'interval_between_requests_defaults_seconds' will not be used. It will be used only if number of requests
|
|
186
|
+
is less than then number of intervals in 'interval_between_request_custom_list_seconds'. The missing intervals
|
|
187
|
+
will be filled by default values from 'interval_between_requests_defaults_seconds'.
|
|
188
|
+
Example: you have 10 requests.
|
|
189
|
+
interval_between_requests_defaults_seconds = 5
|
|
190
|
+
interval_between_request_custom_list_seconds = 7, 10, 8, 4, 15
|
|
191
|
+
The rest will be filled from defaults: 7, 10, 8, 4, 15, 5, 5, 5, 5
|
|
192
|
+
send_request_batch_cycles: how many batch cycles to send of the same 10 requests (or any other number of requests that
|
|
193
|
+
you might have in the requests folder.
|
|
194
|
+
interval_between_batch_cycles_seconds: interval in seconds between each batch.
|
|
195
|
+
"""
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from ..file_io import tomls
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class CategoryNotFoundInConfigError(Exception):
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class PropertyUpdate:
|
|
12
|
+
"""
|
|
13
|
+
:param category: str, Category in the config file.
|
|
14
|
+
:param category_property: str, Property in the category.
|
|
15
|
+
:param value: str, Value to set to the property.
|
|
16
|
+
"""
|
|
17
|
+
category: str
|
|
18
|
+
category_property: str
|
|
19
|
+
value: any
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def update_properties(
|
|
23
|
+
property_update_list: list[PropertyUpdate],
|
|
24
|
+
config_file_path: str
|
|
25
|
+
) -> None:
|
|
26
|
+
"""
|
|
27
|
+
Edit a property in the config file.
|
|
28
|
+
|
|
29
|
+
:param property_update_list: list of PropertyUpdate objects.
|
|
30
|
+
:param config_file_path: str, Path to the config file.
|
|
31
|
+
|
|
32
|
+
-----------
|
|
33
|
+
|
|
34
|
+
Config Example:
|
|
35
|
+
[category]
|
|
36
|
+
category_property = value
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
toml_config = tomls.read_toml_file(config_file_path)
|
|
40
|
+
|
|
41
|
+
for property_update in property_update_list:
|
|
42
|
+
if property_update.category not in toml_config:
|
|
43
|
+
raise CategoryNotFoundInConfigError(f"Category '{property_update.category}' not found in the config file.")
|
|
44
|
+
|
|
45
|
+
changes_dict: dict = dict()
|
|
46
|
+
for property_update in property_update_list:
|
|
47
|
+
if property_update.category in changes_dict:
|
|
48
|
+
changes_dict[property_update.category].update({property_update.category_property: property_update.value})
|
|
49
|
+
else:
|
|
50
|
+
changes_dict[property_update.category] = {property_update.category_property: property_update.value}
|
|
51
|
+
|
|
52
|
+
tomls.update_toml_file_with_new_config(
|
|
53
|
+
main_config_file_path=config_file_path,
|
|
54
|
+
changes_dict=changes_dict
|
|
55
|
+
)
|