atomicshop 3.1.14__py3-none-any.whl → 3.2.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 CHANGED
@@ -1,4 +1,4 @@
1
1
  """Atomic Basic functions and classes to make developer life easier"""
2
2
 
3
3
  __author__ = "Den Kras"
4
- __version__ = '3.1.14'
4
+ __version__ = '3.2.0'
@@ -4,14 +4,13 @@ import queue
4
4
  import socket
5
5
 
6
6
  from ..wrappers.socketw import receiver, sender, socket_client, base
7
- from .. import websocket_parse
7
+ from .. import websocket_parse, ip_addresses
8
8
  from ..http_parse import HTTPRequestParse, HTTPResponseParse
9
9
  from ..basics import threads, tracebacks
10
10
  from ..print_api import print_api
11
11
 
12
12
  from .message import ClientMessage
13
- from .initialize_engines import assign_class_by_domain
14
- from . import config_static
13
+ from . import config_static, initialize_engines
15
14
 
16
15
 
17
16
  def thread_worker_main(
@@ -218,30 +217,45 @@ def thread_worker_main(
218
217
  custom_client_pem_certificate_path = pem_file_path
219
218
  break
220
219
 
221
- # If we're on localhost, then use external services list in order to resolve the domain:
222
- # config['tcp']['forwarding_dns_service_ipv4_list___only_for_localhost']
223
- if client_message.client_ip in base.THIS_DEVICE_IP_LIST:
220
+ # Check if the destination service is an ip address or a domain name.
221
+ if ip_addresses.is_ip_address(client_message.server_name, ip_type='ipv4'):
222
+ # If it's an ip address, connect to the ip address directly.
224
223
  service_client_instance = socket_client.SocketClient(
225
224
  service_name=client_message.server_name,
225
+ connection_ip=client_message.server_name,
226
226
  service_port=client_message.destination_port,
227
227
  tls=is_tls,
228
- dns_servers_list=[config_static.DNSServer.forwarding_dns_service_ipv4],
229
228
  logger=network_logger,
230
229
  custom_pem_client_certificate_file_path=custom_client_pem_certificate_path,
231
230
  enable_sslkeylogfile_env_to_client_ssl_context=(
232
231
  config_static.Certificates.enable_sslkeylogfile_env_to_client_ssl_context)
233
232
  )
234
- # If we're not on localhost, then connect to domain directly.
233
+ # If it's a domain name, then we'll use the DNS to resolve it.
235
234
  else:
236
- service_client_instance = socket_client.SocketClient(
237
- service_name=client_message.server_name,
238
- service_port=client_message.destination_port,
239
- tls=is_tls,
240
- logger=network_logger,
241
- custom_pem_client_certificate_file_path=custom_client_pem_certificate_path,
242
- enable_sslkeylogfile_env_to_client_ssl_context=(
243
- config_static.Certificates.enable_sslkeylogfile_env_to_client_ssl_context)
244
- )
235
+ # If we're on localhost, then use external services list in order to resolve the domain:
236
+ # config['tcp']['forwarding_dns_service_ipv4_list___only_for_localhost']
237
+ if client_message.client_ip in base.THIS_DEVICE_IP_LIST:
238
+ service_client_instance = socket_client.SocketClient(
239
+ service_name=client_message.server_name,
240
+ service_port=client_message.destination_port,
241
+ tls=is_tls,
242
+ dns_servers_list=[config_static.DNSServer.forwarding_dns_service_ipv4],
243
+ logger=network_logger,
244
+ custom_pem_client_certificate_file_path=custom_client_pem_certificate_path,
245
+ enable_sslkeylogfile_env_to_client_ssl_context=(
246
+ config_static.Certificates.enable_sslkeylogfile_env_to_client_ssl_context)
247
+ )
248
+ # If we're not on localhost, then connect to domain directly.
249
+ else:
250
+ service_client_instance = socket_client.SocketClient(
251
+ service_name=client_message.server_name,
252
+ service_port=client_message.destination_port,
253
+ tls=is_tls,
254
+ logger=network_logger,
255
+ custom_pem_client_certificate_file_path=custom_client_pem_certificate_path,
256
+ enable_sslkeylogfile_env_to_client_ssl_context=(
257
+ config_static.Certificates.enable_sslkeylogfile_env_to_client_ssl_context)
258
+ )
245
259
 
246
260
  return service_client_instance
247
261
 
@@ -336,6 +350,7 @@ def thread_worker_main(
336
350
  raise ValueError(f"Unknown side of the socket: {receiving_socket}")
337
351
 
338
352
  while True:
353
+ is_socket_closed: bool = False
339
354
  # pass the socket connect to responder.
340
355
  if side == 'Service' and client_connection_message:
341
356
  client_message = client_connection_message
@@ -343,6 +358,8 @@ def thread_worker_main(
343
358
  bytes_to_send_list: list[bytes] = create_responder_response(client_message)
344
359
  print_api(f"Got responses from connect responder, count: [{len(bytes_to_send_list)}]", logger=network_logger,
345
360
  logger_method='info')
361
+
362
+ received_raw_data = None
346
363
  else:
347
364
  client_message.reinitialize_dynamic_vars()
348
365
 
@@ -389,10 +406,10 @@ def thread_worker_main(
389
406
  # the close on the opposite socket.
390
407
  record_and_statistics_write(client_message)
391
408
 
392
- if is_socket_closed:
393
- exception_or_close_in_receiving_thread = True
394
- finish_thread()
395
- return
409
+ # if is_socket_closed:
410
+ # exception_or_close_in_receiving_thread = True
411
+ # finish_thread()
412
+ # return
396
413
 
397
414
  # Now send it to requester/responder.
398
415
  if side == 'Client':
@@ -404,7 +421,6 @@ def thread_worker_main(
404
421
  print_api("Offline Mode, sending to responder directly.", logger=network_logger,
405
422
  logger_method='info')
406
423
  process_client_raw_data(bytes_to_send_list[0], error_message, client_message)
407
- client_message.action = 'client_responder'
408
424
  bytes_to_send_list = create_responder_response(client_message)
409
425
  elif side == 'Service':
410
426
  bytes_to_send_list: list[bytes] = create_responder_response(client_message)
@@ -420,7 +436,8 @@ def thread_worker_main(
420
436
  client_connection_message = None
421
437
  continue
422
438
 
423
- is_socket_closed: bool = False
439
+ # is_socket_closed: bool = False
440
+ error_on_send: str = str()
424
441
  for bytes_to_send_single in bytes_to_send_list:
425
442
  client_message.reinitialize_dynamic_vars()
426
443
  client_message.timestamp = datetime.now()
@@ -430,7 +447,17 @@ def thread_worker_main(
430
447
  else:
431
448
  client_message.response_raw_bytes = bytes_to_send_single
432
449
 
433
- record_and_statistics_write(client_message)
450
+ # This records the requester or responder output, only if it is not the same as the original
451
+ # message.
452
+ if bytes_to_send_single != received_raw_data:
453
+ if side == 'Client':
454
+ client_message.action = 'client_requester'
455
+
456
+ if config_static.MainConfig.offline:
457
+ client_message.action = 'client_responder_offline'
458
+ elif side == 'Service':
459
+ client_message.action = 'service_responder'
460
+ record_and_statistics_write(client_message)
434
461
 
435
462
  # If we're in offline mode, it means we're in the client thread, and we'll send the
436
463
  # bytes back to the client socket.
@@ -454,11 +481,11 @@ def thread_worker_main(
454
481
 
455
482
  record_and_statistics_write(client_message)
456
483
 
457
- # If the socket was closed on message receive, then we'll break the loop only after send.
458
- if is_socket_closed or error_on_send:
459
- exception_or_close_in_receiving_thread = True
460
- finish_thread()
461
- return
484
+ # If the socket was closed on message receive, then we'll break the loop only after send.
485
+ if is_socket_closed or error_on_send:
486
+ exception_or_close_in_receiving_thread = True
487
+ finish_thread()
488
+ return
462
489
 
463
490
  # For next iteration to start in case this iteration was responsible to process connection message, we need to set it to None.
464
491
  client_connection_message = None
@@ -533,12 +560,9 @@ def thread_worker_main(
533
560
  # websocket_unmasked_frame_parser = websocket_parse.WebsocketFrameParser()
534
561
  websocket_frame_parser = websocket_parse.WebsocketFrameParser()
535
562
 
536
- # Offline queue between client and service threads.
537
- offline_client_service_queue: queue.Queue = queue.Queue()
538
-
539
563
  # Loading parser by domain, if there is no parser for current domain - general reference parser is loaded.
540
564
  # These should be outside any loop and initialized only once entering the thread.
541
- found_domain_module = assign_class_by_domain(
565
+ found_domain_module = initialize_engines.assign_class_by_domain(
542
566
  engines_list=engines_list,
543
567
  message_domain_name=server_name,
544
568
  reference_module=reference_module
@@ -565,8 +589,15 @@ def thread_worker_main(
565
589
  try:
566
590
  engine_name: str = recorder.engine_name
567
591
  client_ip, source_port = client_socket.getpeername()
568
- client_name = socket.gethostbyaddr(client_ip)[0]
569
- destination_port = client_socket.getsockname()[1]
592
+ client_name: str = socket.gethostbyaddr(client_ip)[0]
593
+ destination_port: int = client_socket.getsockname()[1]
594
+ destination_port_str: str = str(destination_port)
595
+
596
+ # If the destination port is in the on_port_connect dictionary, then we'll get the port from there.
597
+ if destination_port_str in found_domain_module.on_port_connect:
598
+ on_port_connect_value = found_domain_module.on_port_connect[destination_port_str]
599
+ _, destination_port_str = initialize_engines.get_ipv4_from_engine_on_connect_port(on_port_connect_value)
600
+ destination_port: int = int(destination_port_str)
570
601
 
571
602
  if config_static.MainConfig.offline:
572
603
  # If in offline mode, then we'll get the TCP server's input address.
@@ -81,9 +81,12 @@ class CreateModuleTemplate:
81
81
  config_lines_list.append('[engine]')
82
82
  config_lines_list.append(f'domains = [{", ".join(domains_with_quotes)}]')
83
83
  config_lines_list.append('localhost = 1\n')
84
- # config_lines_list.append(f'\n')
84
+ config_lines_list.append('[on_port_connect]')
85
+ config_lines_list.append('#5000 = "31.31.31.31"')
86
+ config_lines_list.append('#5000 = "C:\\test\\address.txt"\n')
85
87
  config_lines_list.append('[mtls]')
86
88
  config_lines_list.append('# "subdomain.domain.com" = "file_name_in_current_dir.pem"\n')
89
+ # config_lines_list.append(f'\n')
87
90
 
88
91
  config_file_path = self.new_engine_directory + os.sep + CONFIG_FILE_NAME
89
92
 
@@ -1,6 +1,7 @@
1
1
  import os
2
2
  from pathlib import Path
3
3
 
4
+ from .. import ip_addresses
4
5
  from ..file_io import tomls
5
6
  from ..basics.classes import import_first_class_name_from_file_path
6
7
  from .engines.__reference_general import parser___reference_general, requester___reference_general, \
@@ -14,7 +15,10 @@ class ModuleCategory:
14
15
 
15
16
  self.domain_list: list = list()
16
17
  self.domain_target_dict: dict = dict()
18
+ self.port_target_dict: dict = dict()
19
+
17
20
  self.is_localhost: bool = bool()
21
+ self.on_port_connect: dict = dict()
18
22
  self.mtls: dict = dict()
19
23
 
20
24
  self.parser_file_path: str = str()
@@ -48,6 +52,9 @@ class ModuleCategory:
48
52
  self.domain_list = configuration_data['engine']['domains']
49
53
  self.is_localhost = bool(configuration_data['engine']['localhost'])
50
54
 
55
+ if 'on_port_connect' in configuration_data:
56
+ self.on_port_connect = configuration_data['on_port_connect']
57
+
51
58
  if 'mtls' in configuration_data:
52
59
  self.mtls = configuration_data['mtls']
53
60
 
@@ -75,6 +82,9 @@ class ModuleCategory:
75
82
 
76
83
  self.domain_target_dict[domain] = {'ip': None, 'port': port}
77
84
 
85
+ for port, value in self.on_port_connect.items():
86
+ self.port_target_dict[port] = {'ip': None, 'port': int(port)}
87
+
78
88
  for subdomain, file_name in self.mtls.items():
79
89
  self.mtls[subdomain] = f'{engine_directory_path}{os.sep}{file_name}'
80
90
 
@@ -100,6 +110,47 @@ class ModuleCategory:
100
110
  return 0, ''
101
111
 
102
112
 
113
+ def get_ipv4_from_engine_on_connect_port(
114
+ address_or_file_path: str
115
+ ) -> tuple[str, str] | None:
116
+ """
117
+ Function to get the IPv4 address from the engine on connect port.
118
+
119
+ :param address_or_file_path: string, "ip_address:port" or file path that was set in the engine on_port_connect.
120
+ :return: string, IPv4 address that was parsed from the 'ip_port_address'.
121
+
122
+ """
123
+
124
+ def get_ip_port_from_address(ip_port_address: str) -> tuple[str, str] | None:
125
+ """
126
+ Function to get the IP address and port from the address string.
127
+ If the address is a file path, it will return an empty string.
128
+ """
129
+ if ':' in ip_port_address:
130
+ ipv4_to_connect, port_to_connect = ip_port_address.split(':')
131
+ if ip_addresses.is_ip_address(ipv4_to_connect, ip_type='ipv4'):
132
+ return ipv4_to_connect, port_to_connect
133
+ else:
134
+ return None
135
+ else:
136
+ return None
137
+
138
+ # Try to get it as IP address.
139
+ ip_port_address_from_config = get_ip_port_from_address(address_or_file_path)
140
+
141
+ # If it is not an IP address, try to read it as a text file.
142
+ if not ip_port_address_from_config:
143
+ if os.path.isfile(address_or_file_path):
144
+ with open(address_or_file_path, 'r', encoding='utf-8') as file:
145
+ first_line = file.readline().strip()
146
+
147
+ ip_port_address_from_config = get_ip_port_from_address(first_line)
148
+ else:
149
+ return None
150
+
151
+ return ip_port_address_from_config
152
+
153
+
103
154
  def assign_class_by_domain(
104
155
  engines_list: list,
105
156
  message_domain_name: str,
@@ -133,6 +184,22 @@ def assign_class_by_domain(
133
184
  # If the domain was found in the current list of class domains, we can stop the loop
134
185
  break
135
186
 
187
+ # If the module wasn't found by the domain, check it by the port.
188
+ if not module:
189
+ # Get the list of all the ip addresses in the on_port_connect dict.
190
+ list_of_ip_addresses_per_port: list[str] = []
191
+ for port, value in function_module.on_port_connect.items():
192
+ ipv4_to_connect, _ = get_ipv4_from_engine_on_connect_port(value)
193
+ list_of_ip_addresses_per_port.append(ipv4_to_connect)
194
+
195
+ # Checking if the message domain name is in the list of ip addresses per port.
196
+ if any(x in message_domain_name for x in list_of_ip_addresses_per_port):
197
+ # Assigning module by current engine of the port
198
+ module = function_module
199
+
200
+ # If the port was found in the current list of class ports, we can stop the loop
201
+ break
202
+
136
203
  # If none of the domains were found in the engine domains list, then we'll assign reference module.
137
204
  # It's enough to check only parser, since responder and recorder also will be empty.
138
205
  # This section is also relevant if SNI came empty in the request from the client and no domain was passed by the
@@ -196,6 +196,11 @@ def startup_output(system_logger, script_version: str):
196
196
  for domain, ip_port in engine.domain_target_dict.items():
197
197
  dns_targets.append(ip_port['ip'])
198
198
  print_api.print_api(f"[*] DNS Targets: {dns_targets}", logger=system_logger)
199
+
200
+ if engine.on_port_connect:
201
+ print_api.print_api(f"[*] Connect Ports to IPs: {list(engine.on_port_connect.values())}", logger=system_logger)
202
+ print_api.print_api(f"[*] Connect Ports to IPs Targets: {list(engine.port_target_dict.values())}", logger=system_logger)
203
+
199
204
  # print_api.print_api(f"[*] TCP Listening Interfaces: {engine.tcp_listening_address_list}", logger=system_logger)
200
205
 
201
206
  if config_static.DNSServer.enable:
@@ -235,13 +240,15 @@ def get_ipv4s_for_tcp_server():
235
240
 
236
241
  # Create a list of all the domains in all the engines.
237
242
  domains_to_create_ips_for: list[str] = list()
243
+ ports_to_create_ips_for: list[str] = list()
238
244
  for engine in config_static.ENGINES_LIST:
239
245
  domains_to_create_ips_for += list(engine.domain_target_dict.keys())
246
+ ports_to_create_ips_for += list(engine.on_port_connect.keys())
240
247
 
241
248
  engine_ips: list[str] = list()
242
249
  # Check if we need the localhost ips (12.0.0.1) or external local ips (192.168.0.100).
243
250
  if config_static.ENGINES_LIST[0].is_localhost:
244
- create_ips: int = len(domains_to_create_ips_for)
251
+ create_ips: int = len(domains_to_create_ips_for) + len(ports_to_create_ips_for)
245
252
 
246
253
  # Generate the list of localhost ips.
247
254
  for i in range(create_ips):
@@ -288,7 +295,10 @@ def get_ipv4s_for_tcp_server():
288
295
  # If the domain is in the list of domains to create IPs for, add the IP to the engine.
289
296
  if domain in domains_to_create_ips_for:
290
297
  engine.domain_target_dict[domain]['ip'] = engine_ips.pop(0)
291
-
298
+ for port in engine.on_port_connect.keys():
299
+ # If the port is in the list of ports to create IPs for, add the IP to the engine.
300
+ if port in ports_to_create_ips_for:
301
+ engine.port_target_dict[port]['ip'] = engine_ips.pop(0)
292
302
 
293
303
  def mitm_server(config_file_path: str, script_version: str):
294
304
  on_exit.register_exit_handler(exit_cleanup, at_exit=False, kill_signal=False)
@@ -1,3 +1,4 @@
1
+ import os.path
1
2
  import threading
2
3
  import select
3
4
  from typing import Literal, Union
@@ -427,8 +428,11 @@ class SocketWrapper:
427
428
  # If engines were passed, we will use the listening addresses from the engines.
428
429
  if not self.no_engine_usage_enable:
429
430
  for engine in self.engines_list:
431
+ # Combine the domain and port dicts.
432
+ connection_dict: dict = {**engine.domain_target_dict, **engine.port_target_dict}
433
+
430
434
  # Start all the regular listening interfaces.
431
- for domain, ip_port_dict in engine.domain_target_dict.items():
435
+ for domain_or_port, ip_port_dict in connection_dict.items():
432
436
  ip_address: str = ip_port_dict['ip']
433
437
  port = int(ip_port_dict['port'])
434
438
  socket_by_port = self.create_socket_ipv4_tcp(ip_address, port)
@@ -511,10 +515,28 @@ class SocketWrapper:
511
515
 
512
516
  domain_from_engine = None
513
517
  for engine in self.engines_list:
518
+ # Get the domain to connect on this process in case on no SNI provided.
514
519
  for domain, ip_port_dict in engine.domain_target_dict.items():
515
520
  if ip_port_dict['ip'] == listening_ip:
516
521
  domain_from_engine = domain
517
522
  break
523
+ # If there was no domain found, try to find the IP address for port.
524
+ if not domain_from_engine:
525
+ for port, file_or_ip in engine.port_target_dict.items():
526
+ if file_or_ip['ip'] == listening_ip:
527
+ # Get the value from the 'on_port_connect' dictionary.
528
+ address_or_file_path: str = engine.on_port_connect[str(listening_port)]
529
+ ip_port_address_from_config: tuple = initialize_engines.get_ipv4_from_engine_on_connect_port(
530
+ address_or_file_path)
531
+ if not ip_port_address_from_config:
532
+ raise ValueError(
533
+ f"Invalid IP address or file path in 'on_port_connect' for port "
534
+ f"{listening_port}: {address_or_file_path}"
535
+ )
536
+
537
+ domain_from_engine = ip_port_address_from_config[0]
538
+
539
+ break
518
540
 
519
541
  self.logger.info(f"Requested domain setting: {domain_from_engine}")
520
542
 
@@ -598,6 +620,9 @@ class SocketWrapper:
598
620
  print_kwargs={'logger': self.logger}
599
621
  )
600
622
 
623
+ # Get the real tls version after connection is wrapped.
624
+ tls_version = ssl_client_socket.version()
625
+
601
626
  # If the 'domain_from_dns_server' is empty, it means that the 'engine_name' is not set.
602
627
  # In this case we will set the 'engine_name' to from the SNI.
603
628
  if engine_name == '':
@@ -697,8 +722,18 @@ def get_engine_name(domain: str, engine_list: list):
697
722
  :return: string, engine name.
698
723
  """
699
724
 
725
+ engine_name: str = ''
700
726
  for engine in engine_list:
727
+ # Get engine name by domain.
701
728
  if domain in engine.domain_target_dict:
702
- return engine.engine_name
729
+ engine_name = engine.engine_name
730
+
731
+ # If didn't find by domain, try to find by port.
732
+ if engine_name == '':
733
+ for port, ip_port_to_connect_value in engine.on_port_connect.items():
734
+ ipv4_to_connect, _ = initialize_engines.get_ipv4_from_engine_on_connect_port(ip_port_to_connect_value)
735
+ if ipv4_to_connect == domain:
736
+ engine_name = engine.engine_name
737
+ break
703
738
 
704
- return ''
739
+ return engine_name
@@ -34,12 +34,9 @@ def is_tls(client_socket) -> Optional[Tuple[str, str]]:
34
34
 
35
35
  first_bytes = receiver.peek_first_bytes(client_socket, bytes_amount=3)
36
36
 
37
- # Ensure we got enough data.
38
- if len(first_bytes) < 3:
39
- return None
40
-
41
- # Extract the content type and version
42
- content_type, version_major, version_minor = first_bytes
37
+ # Sometimes only one byte is available, so we need to handle that case.
38
+ # convert to a tuple of ints, add three Nones, and keep only the first 3 items.
39
+ content_type, version_major, version_minor = (tuple(first_bytes) + (None, None, None))[:3]
43
40
 
44
41
  # Map TLS content types to their string representation.
45
42
  content_type_map = {
@@ -52,19 +49,19 @@ def is_tls(client_socket) -> Optional[Tuple[str, str]]:
52
49
 
53
50
  # Map TLS version bytes to their string representation.
54
51
  version_map = {
55
- (0x03, 0x00): "SSL 3.0",
56
- (0x03, 0x01): "TLS 1.0",
57
- (0x03, 0x02): "TLS 1.1",
58
- (0x03, 0x03): "TLS 1.2/1.3"
52
+ (0x03, 0x00): "SSLv3.0",
53
+ (0x03, 0x01): "TLSv1.0",
54
+ (0x03, 0x02): "TLSv1.1",
55
+ (0x03, 0x03): "TLSv1.2/1.3"
59
56
  # Remember, you can't definitively differentiate 1.2 and 1.3 just from these bytes
60
57
  }
61
58
 
62
59
  # Get the tuple of the type and version as strings.
63
- tls_content_and_version_tuple: tuple = \
60
+ tls_content_and_version_tuple: tuple[str, str] = \
64
61
  content_type_map.get(content_type), version_map.get((version_major, version_minor))
65
62
 
66
63
  # If both parts of the tuple are not None, return the protocol type.
67
- if tls_content_and_version_tuple[0] and tls_content_and_version_tuple[1]:
64
+ if tls_content_and_version_tuple[0]:
68
65
  return tls_content_and_version_tuple
69
66
  else:
70
67
  return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: atomicshop
3
- Version: 3.1.14
3
+ Version: 3.2.0
4
4
  Summary: Atomic functions and classes to make developer life easier
5
5
  Author: Denis Kras
6
6
  License: MIT License
@@ -1,4 +1,4 @@
1
- atomicshop/__init__.py,sha256=51cQhVAb57yTXRlohpUAwbJggyE5xJPvP9tWPDiTCP8,123
1
+ atomicshop/__init__.py,sha256=ia_QL-nkKuszLHN2XwNJas4i3cauADZSyyLAKJGWcD0,122
2
2
  atomicshop/_basics_temp.py,sha256=6cu2dd6r2dLrd1BRNcVDKTHlsHs_26Gpw8QS6v32lQ0,3699
3
3
  atomicshop/_create_pdf_demo.py,sha256=Yi-PGZuMg0RKvQmLqVeLIZYadqEZwUm-4A9JxBl_vYA,3713
4
4
  atomicshop/_patch_import.py,sha256=ENp55sKVJ0e6-4lBvZnpz9PQCt3Otbur7F6aXDlyje4,6334
@@ -136,16 +136,16 @@ atomicshop/file_io/xmls.py,sha256=zh3SuK-dNaFq2NDNhx6ivcf4GYCfGM8M10PcEwDSpxk,21
136
136
  atomicshop/mitm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
137
137
  atomicshop/mitm/config_static.py,sha256=N3D06C_wUytwm80PQCL90ZGHLMHeQlCcI2XQQU2FZ1I,8145
138
138
  atomicshop/mitm/config_toml_editor.py,sha256=2p1CMcktWRR_NW-SmyDwylu63ad5e0-w1QPMa8ZLDBw,1635
139
- atomicshop/mitm/connection_thread_worker.py,sha256=Fqb2OfhM0GVpPSV-6luba4eaMQ68VqwFb0eB2vrtE4E,30477
139
+ atomicshop/mitm/connection_thread_worker.py,sha256=E_DNvP4lbbcoeFziiG10Aa7bg7Ka09wdwV_uqaRm5rU,32554
140
140
  atomicshop/mitm/import_config.py,sha256=gCH1hV-CxBAdwjeFJu1I5ntbm5hqzcB0y0vzRPkzra0,16936
141
- atomicshop/mitm/initialize_engines.py,sha256=Pj9k3iLdoE0KAl3QWG1Z10LHUHY8WQivSPFnQLhCWrc,7385
141
+ atomicshop/mitm/initialize_engines.py,sha256=N4JVoC7PXN8GxUBXvNCXS-ZA5ag6rXqYXyZ3EyHOcLM,10318
142
142
  atomicshop/mitm/message.py,sha256=CDhhm4BTuZE7oNZCjvIZ4BuPOW4MuIzQLOg91hJaxDI,3065
143
- atomicshop/mitm/mitm_main.py,sha256=cfQLaPaUZgluatlZDRiToi14ekZbPT2KM4-AiivTs3w,30055
143
+ atomicshop/mitm/mitm_main.py,sha256=at9uxnXF_4b273HRXt9UGkERkHantRTOAvRtlYYI68E,30774
144
144
  atomicshop/mitm/recs_files.py,sha256=ZAAD0twun-FtmbSniXe3XQhIlawvANNB_HxwbHj7kwI,3151
145
145
  atomicshop/mitm/shared_functions.py,sha256=0lzeyINd44sVEfFbahJxQmz6KAMWbYrW5ou3UYfItvw,1777
146
146
  atomicshop/mitm/statistic_analyzer.py,sha256=5_sAYGX2Xunzo_pS2W5WijNCwr_BlGJbbOO462y_wN4,27533
147
147
  atomicshop/mitm/engines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
148
- atomicshop/mitm/engines/create_module_template.py,sha256=Qu7ca72BsbcPrtonJM1ok7pGlwu0u6gEDap1ht6vMw0,5577
148
+ atomicshop/mitm/engines/create_module_template.py,sha256=_1aoB-ety98szV__2jnn6cohxmrClU5mOnf6u-nq_Zc,5762
149
149
  atomicshop/mitm/engines/create_module_template_main_example.py,sha256=LeQ44Rp2Gi_KbIDY_4OMS0odkSK3zFZWra_oAka5eJY,243
150
150
  atomicshop/mitm/engines/__parent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
151
151
  atomicshop/mitm/engines/__parent/parser___parent.py,sha256=HHaCXhScl3OlPjz6eUxsDpJaZyk6BNuDMc9xCkeo2Ws,661
@@ -331,14 +331,14 @@ atomicshop/wrappers/socketw/sender.py,sha256=aX_K8l_rHjd5AWb8bi5mt8-YTkMYVRDB6Dn
331
331
  atomicshop/wrappers/socketw/sni.py,sha256=q-F-R1KtE94g8WGrR3QHgi-otXZJUPBprEwQqnY80_A,17639
332
332
  atomicshop/wrappers/socketw/socket_client.py,sha256=AQKjm_GZLH2PO7gkFbwzIbXzUXxRFvBTc6onrgapFqs,22048
333
333
  atomicshop/wrappers/socketw/socket_server_tester.py,sha256=Qobmh4XV8ZxLUaw-eW4ESKAbeSLecCKn2OWFzMhadk0,6420
334
- atomicshop/wrappers/socketw/socket_wrapper.py,sha256=3sEz1VUar1JJU8KxocrOT09-vIh5hLpE29aTZH9TNC8,41117
335
- atomicshop/wrappers/socketw/ssl_base.py,sha256=kmiif84kMhBr5yjQW17p935sfjR5JKG0LxIwBA4iVvU,2275
334
+ atomicshop/wrappers/socketw/socket_wrapper.py,sha256=_q_QDdyQjSmc0Q0WbMDQDajqDx0_AO3IqlL78Pk4nkE,43179
335
+ atomicshop/wrappers/socketw/ssl_base.py,sha256=62-hPm7zla1rh3m_WvDnXqKH-sDUTdiRptD8STCkgdk,2313
336
336
  atomicshop/wrappers/socketw/statistics_csv.py,sha256=WcNyaqEZ82S5-f3kzqi1nllNT2Nd2P_zg8HqCc7vW4s,4120
337
337
  atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
338
338
  atomicshop/wrappers/winregw/winreg_installed_software.py,sha256=Qzmyktvob1qp6Tjk2DjLfAqr_yXV0sgWzdMW_9kwNjY,2345
339
339
  atomicshop/wrappers/winregw/winreg_network.py,sha256=ih0BVNwByLvf9F_Lac4EdmDYYJA3PzMvmG0PieDZrsE,9905
340
- atomicshop-3.1.14.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
341
- atomicshop-3.1.14.dist-info/METADATA,sha256=lhw9Eozk9CfUi_0d053WbgebwXaDpZq1gfNAqaEvmUU,10671
342
- atomicshop-3.1.14.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
343
- atomicshop-3.1.14.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
344
- atomicshop-3.1.14.dist-info/RECORD,,
340
+ atomicshop-3.2.0.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
341
+ atomicshop-3.2.0.dist-info/METADATA,sha256=VKefd8URMpY8zVcDX7iiRnpIcssdPlobeUlqhIyA7HQ,10670
342
+ atomicshop-3.2.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
343
+ atomicshop-3.2.0.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
344
+ atomicshop-3.2.0.dist-info/RECORD,,