atomicshop 2.15.13__py3-none-any.whl → 2.16.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.

Files changed (42) hide show
  1. atomicshop/__init__.py +1 -1
  2. atomicshop/a_mains/dns_gateway_setting.py +11 -0
  3. atomicshop/basics/booleans.py +14 -5
  4. atomicshop/dns.py +104 -0
  5. atomicshop/file_io/docxs.py +8 -0
  6. atomicshop/file_io/tomls.py +133 -0
  7. atomicshop/filesystem.py +5 -4
  8. atomicshop/get_process_list.py +3 -3
  9. atomicshop/mitm/config_static.py +195 -0
  10. atomicshop/mitm/config_toml_editor.py +55 -0
  11. atomicshop/mitm/connection_thread_worker.py +54 -90
  12. atomicshop/mitm/import_config.py +147 -139
  13. atomicshop/mitm/initialize_engines.py +7 -2
  14. atomicshop/mitm/initialize_mitm_server.py +161 -107
  15. atomicshop/mitm/shared_functions.py +0 -1
  16. atomicshop/mitm/statistic_analyzer.py +13 -1
  17. atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py +54 -14
  18. atomicshop/script_as_string_processor.py +5 -1
  19. atomicshop/wrappers/cryptographyw.py +3 -3
  20. atomicshop/wrappers/psutilw/networks.py +25 -1
  21. atomicshop/wrappers/pywin32w/wmis/__init__.py +0 -0
  22. atomicshop/wrappers/pywin32w/wmis/helpers.py +127 -0
  23. atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +167 -0
  24. atomicshop/wrappers/socketw/accepter.py +8 -8
  25. atomicshop/wrappers/socketw/base.py +13 -0
  26. atomicshop/wrappers/socketw/certificator.py +202 -149
  27. atomicshop/wrappers/socketw/creator.py +15 -35
  28. atomicshop/wrappers/socketw/dns_server.py +155 -102
  29. atomicshop/wrappers/socketw/exception_wrapper.py +8 -27
  30. atomicshop/wrappers/socketw/get_process.py +115 -95
  31. atomicshop/wrappers/socketw/sni.py +298 -164
  32. atomicshop/wrappers/socketw/socket_client.py +5 -12
  33. atomicshop/wrappers/socketw/socket_server_tester.py +1 -1
  34. atomicshop/wrappers/socketw/socket_wrapper.py +328 -72
  35. atomicshop/wrappers/socketw/statistics_csv.py +94 -16
  36. {atomicshop-2.15.13.dist-info → atomicshop-2.16.0.dist-info}/METADATA +1 -1
  37. {atomicshop-2.15.13.dist-info → atomicshop-2.16.0.dist-info}/RECORD +41 -36
  38. atomicshop/mitm/config_editor.py +0 -37
  39. /atomicshop/wrappers/pywin32w/{wmi_win32process.py → wmis/win32process.py} +0 -0
  40. {atomicshop-2.15.13.dist-info → atomicshop-2.16.0.dist-info}/LICENSE.txt +0 -0
  41. {atomicshop-2.15.13.dist-info → atomicshop-2.16.0.dist-info}/WHEEL +0 -0
  42. {atomicshop-2.15.13.dist-info → atomicshop-2.16.0.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,7 @@
1
1
  """Loading resources using stdlib importlib.resources APIs (Python 3.7+)
2
2
  https://docs.python.org/3/library/importlib.html#module-importlib.resources"""
3
3
  import importlib.resources
4
+ from typing import Literal
4
5
 
5
6
  from .print_api import print_api
6
7
 
@@ -13,7 +14,10 @@ class ScriptAsStringProcessor:
13
14
  self.exchange_input_variable_string: str = "exchange_input_variable"
14
15
  self.script_string: str = str()
15
16
 
16
- def read_script_to_string(self, script_file_name: str):
17
+ def read_script_to_string(
18
+ self,
19
+ script_file_name: Literal['process_from_port', 'process_from_ipv4']
20
+ ):
17
21
  self.script_string = importlib.resources.read_text(
18
22
  f'{__package__}.{self.resources_directory_name}',
19
23
  f'{script_file_name}.py')
@@ -80,7 +80,7 @@ def convert_pem_to_x509_object(certificate: Union[str, bytes]) -> x509.Certifica
80
80
  return x509.load_pem_x509_certificate(certificate)
81
81
 
82
82
 
83
- def convert_der_to_x509_object(certificate: bytes):
83
+ def convert_der_to_x509_object(certificate: bytes) -> x509.Certificate:
84
84
  """Convert DER certificate from socket to x509 object.
85
85
 
86
86
  :param certificate: bytes, certificate to convert.
@@ -151,8 +151,8 @@ def copy_extensions_from_old_cert_to_new_cert(
151
151
  builder = x509.CertificateBuilder()
152
152
  builder = builder.subject_name(certificate.subject)
153
153
  builder = builder.issuer_name(certificate.issuer)
154
- builder = builder.not_valid_before(certificate.not_valid_before)
155
- builder = builder.not_valid_after(certificate.not_valid_after)
154
+ builder = builder.not_valid_before(certificate.not_valid_before_utc)
155
+ builder = builder.not_valid_after(certificate.not_valid_after_utc)
156
156
  builder = builder.serial_number(certificate.serial_number)
157
157
 
158
158
  # We're using the new private key that we will sign with the new certificate later.
@@ -1,5 +1,6 @@
1
1
  from typing import Union
2
2
  import shlex
3
+ import socket
3
4
 
4
5
  import psutil
5
6
 
@@ -14,7 +15,10 @@ def get_process_using_port(port: int) -> Union[dict, None]:
14
15
  try:
15
16
  connections = proc.connections(kind='inet')
16
17
  for conn in connections:
17
- if conn.laddr.port == port:
18
+ # if conn.laddr.port == port:
19
+ # Status LISTEN is for TCP sockets and NONE is for UDP sockets.
20
+ # Sometimes after socket close, the port will be in TIME_WAIT state.
21
+ if conn.laddr.port == port and (conn.status == 'LISTEN' or conn.status == 'NONE'):
18
22
  cmdline = proc.info['cmdline']
19
23
  if not cmdline:
20
24
  cmdline = '<EMPTY: TRY RUNNING AS ADMIN>'
@@ -43,3 +47,23 @@ def get_processes_using_port_list(ports: list) -> Union[dict, None]:
43
47
  port_process_map[port] = process_info
44
48
 
45
49
  return port_process_map
50
+
51
+
52
+ def get_default_connection_name() -> Union[dict, None]:
53
+ """
54
+ Function to get the default network interface.
55
+ :return: dict[interface_name: details] or None.
56
+ """
57
+ # Get all interfaces.
58
+ interfaces: dict = psutil.net_if_addrs()
59
+ default_ip_address: str = socket.gethostbyname(socket.gethostname())
60
+
61
+ for interface, details in interfaces.items():
62
+ for address in details:
63
+ # Check if the address is an IPv4 address (AF_INET) and not a loopback (127.0.0.1)
64
+ if address.family == socket.AF_INET and not address.address.startswith('127.'):
65
+ # Check if the address is the default IP address.
66
+ if address.address == default_ip_address:
67
+ return {interface: details}
68
+
69
+ return None
File without changes
@@ -0,0 +1,127 @@
1
+ import win32com.client
2
+
3
+
4
+ class WmiMethodExecutionError(Exception):
5
+ pass
6
+
7
+
8
+ class WmiMethodParameterError(Exception):
9
+ pass
10
+
11
+
12
+ class EmptyValue:
13
+ pass
14
+
15
+
16
+ def get_method(
17
+ wmi_object: win32com.client.CDispatch,
18
+ method_name: str
19
+ ):
20
+ """
21
+ Get the WMI method.
22
+
23
+ :param wmi_object: WMI object.
24
+ :param method_name: str, name of the method.
25
+ :return: WMI method object.
26
+ """
27
+
28
+ return wmi_object.Methods_(method_name)
29
+
30
+
31
+ def get_method_parameter_instance(
32
+ method: win32com.client.CDispatch
33
+ ):
34
+ """
35
+ Get the WMI method parameter.
36
+
37
+ :param method: WMI method object.
38
+ :return: WMI method parameter object.
39
+ """
40
+
41
+ return method.inParameters.SpawnInstance_()
42
+
43
+
44
+ def call_method(
45
+ wmi_object: win32com.client.CDispatch,
46
+ method_name: str,
47
+ value: any = EmptyValue
48
+ ):
49
+ """
50
+ Call the WMI method.
51
+
52
+ :param wmi_object: WMI object.
53
+ :param method_name: str, name of the method.
54
+ :param value: any, value to pass to the method.
55
+ Methods can receive a None value if they don't require any parameters.
56
+ If the method doesn't require any parameters, leave it as 'EmptyValue' class.
57
+ :return: WMI method object.
58
+ """
59
+
60
+ # Get the method instance out of the WMI object.
61
+ method = get_method(wmi_object, method_name)
62
+
63
+ # Check if the method requires any parameters.
64
+ if not method.InParameters and not isinstance(value, EmptyValue):
65
+ raise WmiMethodParameterError(f"Method '{method_name}' doesn't require any parameters.\nValue: {value}")
66
+ elif method.InParameters and isinstance(value, EmptyValue):
67
+ raise WmiMethodParameterError(f"Method '{method_name}' requires parameters.\nValue: {value}")
68
+
69
+ # If value was passed for the method to set.
70
+ if not isinstance(value, EmptyValue):
71
+ # Get the input parameters names that a method requires.
72
+ # The names are stored in a list of tuples where the first element is the name of the parameter and the second
73
+ # element is a boolean that indicates if the parameter is an array.
74
+ input_parameters_names = [
75
+ (input_parameter.Name, input_parameter.IsArray) for input_parameter in method.InParameters.Properties_]
76
+
77
+ # Check if the value and the input parameter is a list.
78
+ if not (isinstance(value, list) or value is None) and input_parameters_names[0][1]:
79
+ raise WmiMethodParameterError(f"Parameter '{input_parameters_names[0][0]}' must be a list.\nValue: {value}")
80
+ elif (isinstance(value, list) or value is None) and not input_parameters_names[0][1]:
81
+ raise WmiMethodParameterError(f"Parameter '{input_parameters_names[0][0]}' "
82
+ f"must be a single value.\nValue: {value}")
83
+
84
+ # Get generic parameter instance.
85
+ parameter_instance = get_method_parameter_instance(method)
86
+ # Set the attribute of the parameter name instance that we retrieved from above to the value.
87
+ # At this point only been using one parameter for a method, so maybe need to refactor this part if needed
88
+ # in the future for more than one parameter.
89
+ setattr(parameter_instance, input_parameters_names[0][0], value)
90
+
91
+ # Execute the method with the parameter instance.
92
+ result = wmi_object.ExecMethod_(method_name, parameter_instance)
93
+ else:
94
+ # Execute the method without any parameters.
95
+ result = wmi_object.ExecMethod_(method_name)
96
+
97
+ # Getting Result.
98
+ # Get the output parameters names that a method returns.
99
+ if method.OutParameters:
100
+ out_properties_names = [
101
+ (out_property.Name, out_property.IsArray) for out_property in method.OutParameters.Properties_]
102
+ else:
103
+ out_properties_names = []
104
+
105
+ # Get the results for each parameter the method returns.
106
+ results = []
107
+ for name, is_array in out_properties_names:
108
+ value = result.Properties_(name).Value
109
+ if is_array:
110
+ results.append(list(value or []))
111
+ else:
112
+ results.append(value)
113
+
114
+ # Check if the method executed successfully.
115
+ for result in results:
116
+ if result != 0:
117
+ raise WmiMethodExecutionError(f"Failed to execute method '{method_name}' with error code: {result}")
118
+
119
+
120
+ """
121
+ # Setting SeDebugPrivilege
122
+ import win32security, ntsecuritycon, win32con, win32api
123
+ privs = ((win32security.LookupPrivilegeValue('',ntsecuritycon.SE_DEBUG_NAME), win32con.SE_PRIVILEGE_ENABLED),)
124
+ hToken = win32security.OpenProcessToken(win32api.GetCurrentProcess(), win32security.TOKEN_ALL_ACCESS)
125
+ win32security.AdjustTokenPrivileges(hToken, False, privs)
126
+ win32api.CloseHandle(hToken)
127
+ """
@@ -0,0 +1,167 @@
1
+ from typing import Union
2
+
3
+ import win32com.client
4
+
5
+ from . import helpers
6
+ from ...psutilw import networks
7
+ from ....print_api import print_api
8
+
9
+
10
+ class NetworkAdapterNotFoundError(Exception):
11
+ pass
12
+
13
+
14
+ def list_network_adapters() -> list:
15
+ # Initialize the WMI client
16
+ wmi = win32com.client.Dispatch('WbemScripting.SWbemLocator')
17
+ wmi_service = wmi.ConnectServer('.', 'root\\cimv2')
18
+
19
+ # Query all network adapters
20
+ adapters = wmi_service.ExecQuery("SELECT * FROM Win32_NetworkAdapter")
21
+
22
+ # Print adapter descriptions
23
+ # for adapter in adapters:
24
+ # print(f"Description: {adapter.Description}, IPEnabled: {adapter.IPEnabled}")
25
+ return list(adapters)
26
+
27
+
28
+ def get_default_network_adapter():
29
+ """
30
+ Get the default network adapter.
31
+ :return:
32
+ """
33
+
34
+ default_connection_name_dict: dict = networks.get_default_connection_name()
35
+ # Get the first key from the dictionary.
36
+ default_connection_name: str = list(default_connection_name_dict.keys())[0]
37
+ adapters = list_network_adapters()
38
+
39
+ for adapter in adapters:
40
+ if default_connection_name == adapter.NetConnectionID:
41
+ return adapter
42
+
43
+ raise NetworkAdapterNotFoundError("Default network adapter not found.")
44
+
45
+
46
+ def get_wmi_network_configuration(
47
+ use_default_interface: bool = False,
48
+ connection_name: str = None,
49
+ mac_address: str = None
50
+ ) -> tuple:
51
+ """
52
+ Get the WMI network configuration for a network adapter.
53
+ :param use_default_interface: bool, if True, the default network interface will be used.
54
+ This is the adapter that your internet is being used from.
55
+ :param connection_name: string, adapter name as shown in the network settings.
56
+ :param mac_address: string, MAC address of the adapter. Format: '00:00:00:00:00:00'.
57
+ :return: tuple(Win32_NetworkAdapterConfiguration, Win32_NetworkAdapter)
58
+ """
59
+
60
+ if use_default_interface and connection_name:
61
+ raise ValueError("Only one of 'use_default_interface' or 'connection_name' must be provided.")
62
+ elif not use_default_interface and not connection_name:
63
+ raise ValueError("Either 'use_default_interface' or 'connection_name' must be provided.")
64
+
65
+ adapters = list_network_adapters()
66
+
67
+ current_adapter = None
68
+ if use_default_interface:
69
+ default_connection_name_dict: dict = networks.get_default_connection_name()
70
+ # Get the first key from the dictionary.
71
+ connection_name: str = list(default_connection_name_dict.keys())[0]
72
+
73
+ if connection_name is None and mac_address is None:
74
+ raise ValueError("Either 'connection_name' or 'mac_address' must be provided.")
75
+ elif connection_name and mac_address:
76
+ raise ValueError("Only one of 'connection_name' or 'mac_address' must be provided.")
77
+
78
+ if connection_name:
79
+ for adapter in adapters:
80
+ if connection_name == adapter.NetConnectionID:
81
+ current_adapter = adapter
82
+ break
83
+
84
+ if not current_adapter:
85
+ raise NetworkAdapterNotFoundError(f"Adapter with connection name '{connection_name}' not found.")
86
+ elif mac_address:
87
+ for adapter in adapters:
88
+ if mac_address == adapter.MACAddress:
89
+ current_adapter = adapter
90
+ break
91
+
92
+ if current_adapter is None:
93
+ raise NetworkAdapterNotFoundError(f"Adapter with MAC address '{mac_address}' not found.")
94
+
95
+ # Initialize the WMI client
96
+ wmi = win32com.client.Dispatch('WbemScripting.SWbemLocator')
97
+ wmi_service = wmi.ConnectServer('.', 'root\\cimv2')
98
+
99
+ # Query the network adapter configurations
100
+ query = f"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE Index='{current_adapter.DeviceID}'"
101
+ adapter_configs = wmi_service.ExecQuery(query)
102
+
103
+ # Check if the adapter exists
104
+ if len(adapter_configs) == 0:
105
+ raise NetworkAdapterNotFoundError(f"Adapter with connection name '{connection_name}' not found.")
106
+
107
+ return adapter_configs[0], current_adapter
108
+
109
+
110
+ def set_dns_server(
111
+ dns_servers: Union[list[str], None],
112
+ use_default_interface: bool = False,
113
+ connection_name: str = None,
114
+ mac_address: str = None
115
+ ):
116
+ """
117
+ Set the DNS servers for a network adapter.
118
+ :param dns_servers: list of strings, DNS server IPv4 addresses.
119
+ None, if you want to remove the DNS servers and make the interface to obtain them automatically from DHCP.
120
+ list[str], if you want to set the DNS servers manually to the list of strings.
121
+ :param use_default_interface: bool, if True, the default network interface will be used.
122
+ This is the adapter that your internet is being used from.
123
+ :param connection_name: string, adapter name as shown in the network settings.
124
+ :param mac_address: string, MAC address of the adapter. Format: '00:00:00:00:00:00'.
125
+ :return:
126
+ """
127
+
128
+ adapter_config, current_adapter = get_wmi_network_configuration(
129
+ use_default_interface=use_default_interface, connection_name=connection_name, mac_address=mac_address)
130
+
131
+ print_api(f"Adapter [{current_adapter.Description}], Connection name [{current_adapter.NetConnectionID}]\n"
132
+ f"Setting DNS servers to {dns_servers}", color='blue')
133
+
134
+ # Set DNS servers
135
+ helpers.call_method(adapter_config, 'SetDNSServerSearchOrder', dns_servers)
136
+
137
+
138
+ def is_adapter_dns_gateway_from_dhcp(
139
+ use_default_interface: bool = False,
140
+ connection_name: str = None,
141
+ mac_address: str = None
142
+ ) -> bool:
143
+ """
144
+ Check if the adapter is set to obtain the DNS servers automatically from DHCP.
145
+ :param use_default_interface: bool, if True, the default network interface will be used.
146
+ This is the adapter that your internet is being used from.
147
+ :param connection_name: string, adapter name as shown in the network settings.
148
+ :param mac_address: string, MAC address of the adapter. Format: '00:00:00:00:00:00'.
149
+ :return: bool, True if DHCP is enabled, False otherwise.
150
+ """
151
+
152
+ adapter_config, current_adapter = get_wmi_network_configuration(
153
+ use_default_interface=use_default_interface, connection_name=connection_name, mac_address=mac_address)
154
+
155
+ # If DHCP is not enabled.
156
+ if not adapter_config.DHCPEnabled:
157
+ # Then it is obvious that DNS Gateway is also Statis.
158
+ return False
159
+ # If DHCP is enabled.
160
+ else:
161
+ # Then we need to check if Default IP gateway is the same as DNS Gateway, if so.
162
+ if adapter_config.DefaultIPGateway == adapter_config.DNSServerSearchOrder:
163
+ # Then it is set dynamically from DHCP.
164
+ return True
165
+ else:
166
+ # If not, so it is static.
167
+ return False
@@ -2,17 +2,12 @@ from . import exception_wrapper
2
2
 
3
3
 
4
4
  @exception_wrapper.connection_exception_decorator
5
- def accept_connection(socket_object, dns_domain, print_kwargs: dict = None):
5
+ def accept_connection(socket_object, domain_from_dns_server, print_kwargs: dict = None):
6
6
  """
7
7
  Accept connection from client.
8
8
  This function is wrapped with exception wrapper.
9
9
  After you execute the function, you can get the error message if there was any with:
10
10
  error_message = accept_connection.message
11
-
12
- :param socket_object:
13
- :param dns_domain:
14
- :param print_kwargs:
15
- :return:
16
11
  """
17
12
 
18
13
  client_socket = None
@@ -33,8 +28,13 @@ def accept_connection(socket_object, dns_domain, print_kwargs: dict = None):
33
28
  return client_socket, client_address_tuple
34
29
 
35
30
 
36
- def accept_connection_with_error(socket_object, dns_domain, print_kwargs: dict = None):
37
- client_socket, client_address_tuple = accept_connection(socket_object, dns_domain, print_kwargs=print_kwargs)
31
+ def accept_connection_with_error(
32
+ socket_object,
33
+ domain_from_dns_server,
34
+ print_kwargs: dict = None
35
+ ):
36
+ client_socket, client_address_tuple = accept_connection(
37
+ socket_object, domain_from_dns_server, print_kwargs=print_kwargs)
38
38
  error_message = accept_connection.message
39
39
 
40
40
  return client_socket, client_address_tuple, error_message
@@ -1,6 +1,11 @@
1
1
  import socket
2
2
 
3
3
 
4
+ LOCALHOST_IPV4: str = '127.0.0.1'
5
+ DEFAULT_IPV4: str = socket.gethostbyname(socket.gethostname())
6
+ THIS_DEVICE_IP_LIST: list = [LOCALHOST_IPV4, DEFAULT_IPV4]
7
+
8
+
4
9
  def get_local_network_interfaces_ip_address(family_type: str = None, ip_only: bool = False) -> list:
5
10
  """
6
11
  Return list of IP addresses of local network interfaces.
@@ -57,3 +62,11 @@ def get_source_destination(socket_object):
57
62
  def set_socket_timeout(socket_object, seconds: int = 1):
58
63
  # Setting timeout on the socket before "accept()" drastically slows down connections.
59
64
  socket_object.settimeout(seconds)
65
+
66
+
67
+ def get_default_ip_address() -> str:
68
+ """
69
+ Get the default IP address of the system.
70
+ :return: string.
71
+ """
72
+ return socket.gethostbyname(socket.gethostname())