atomicshop 2.18.0__py3-none-any.whl → 2.18.2__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/mitm/config_static.py +1 -1
- atomicshop/mitm/connection_thread_worker.py +94 -37
- atomicshop/mitm/message.py +2 -0
- atomicshop/wrappers/socketw/statistics_csv.py +5 -2
- {atomicshop-2.18.0.dist-info → atomicshop-2.18.2.dist-info}/METADATA +1 -1
- {atomicshop-2.18.0.dist-info → atomicshop-2.18.2.dist-info}/RECORD +10 -10
- {atomicshop-2.18.0.dist-info → atomicshop-2.18.2.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.18.0.dist-info → atomicshop-2.18.2.dist-info}/WHEEL +0 -0
- {atomicshop-2.18.0.dist-info → atomicshop-2.18.2.dist-info}/top_level.txt +0 -0
atomicshop/__init__.py
CHANGED
atomicshop/mitm/config_static.py
CHANGED
|
@@ -72,6 +72,7 @@ def thread_worker_main(
|
|
|
72
72
|
tls_version=tls_version,
|
|
73
73
|
protocol=client_message.protocol,
|
|
74
74
|
protocol2=client_message.protocol2,
|
|
75
|
+
protocol3=client_message.protocol3,
|
|
75
76
|
path=http_path,
|
|
76
77
|
status_code=http_status_code,
|
|
77
78
|
command=http_command,
|
|
@@ -97,6 +98,8 @@ def thread_worker_main(
|
|
|
97
98
|
raw_bytes: bytes,
|
|
98
99
|
client_message: ClientMessage):
|
|
99
100
|
nonlocal protocol
|
|
101
|
+
nonlocal protocol3
|
|
102
|
+
|
|
100
103
|
# Parsing the raw bytes as HTTP.
|
|
101
104
|
request_http_parsed, is_http_request, request_parsing_error = (
|
|
102
105
|
HTTPRequestParse(raw_bytes).parse())
|
|
@@ -117,9 +120,14 @@ def thread_worker_main(
|
|
|
117
120
|
auto_parsed = response_http_parsed
|
|
118
121
|
network_logger.info(
|
|
119
122
|
f"HTTP Response Parsed: Status: {response_http_parsed.code}")
|
|
123
|
+
protocol3 = auto_parsed.headers.get('Sec-WebSocket-Protocol', None)
|
|
124
|
+
if protocol3:
|
|
125
|
+
client_message.protocol3 = protocol3
|
|
120
126
|
elif protocol == 'Websocket':
|
|
121
127
|
client_message.protocol2 = 'Frame'
|
|
122
128
|
auto_parsed = parse_websocket(raw_bytes)
|
|
129
|
+
if protocol3:
|
|
130
|
+
client_message.protocol3 = protocol3
|
|
123
131
|
else:
|
|
124
132
|
auto_parsed = None
|
|
125
133
|
|
|
@@ -276,6 +284,41 @@ def thread_worker_main(
|
|
|
276
284
|
|
|
277
285
|
return client_message
|
|
278
286
|
|
|
287
|
+
def responder_thread_worker():
|
|
288
|
+
nonlocal exception_or_close_in_receiving_thread
|
|
289
|
+
|
|
290
|
+
client_message: ClientMessage = client_message_first_start()
|
|
291
|
+
try:
|
|
292
|
+
while True:
|
|
293
|
+
client_message = responder_queue.get()
|
|
294
|
+
|
|
295
|
+
# If the message is not a ClientMessage object, then we'll break the loop, since it is the exit signal.
|
|
296
|
+
if not isinstance(client_message, ClientMessage):
|
|
297
|
+
return
|
|
298
|
+
|
|
299
|
+
raw_responses: list[bytes] = create_responder_response(client_message)
|
|
300
|
+
|
|
301
|
+
is_socket_closed: bool = False
|
|
302
|
+
for response_raw_bytes in raw_responses:
|
|
303
|
+
client_message.reinitialize_dynamic_vars()
|
|
304
|
+
client_message.timestamp = datetime.now()
|
|
305
|
+
client_message.response_raw_bytes = response_raw_bytes
|
|
306
|
+
error_on_send: str = sender.Sender(
|
|
307
|
+
ssl_socket=client_socket, class_message=client_message.response_raw_bytes,
|
|
308
|
+
logger=network_logger).send()
|
|
309
|
+
|
|
310
|
+
# If there was problem with sending data, we'll break the main while loop.
|
|
311
|
+
if error_on_send:
|
|
312
|
+
client_message.errors.append(error_on_send)
|
|
313
|
+
record_and_statistics_write(client_message)
|
|
314
|
+
is_socket_closed = True
|
|
315
|
+
|
|
316
|
+
if is_socket_closed:
|
|
317
|
+
exception_or_close_in_receiving_thread = True
|
|
318
|
+
return
|
|
319
|
+
except Exception as exc:
|
|
320
|
+
handle_exceptions_on_sub_connection_thread(client_message, client_exception_queue, exc)
|
|
321
|
+
|
|
279
322
|
def receive_send_start(
|
|
280
323
|
receiving_socket,
|
|
281
324
|
sending_socket = None,
|
|
@@ -339,33 +382,14 @@ def thread_worker_main(
|
|
|
339
382
|
# the close on the opposite socket.
|
|
340
383
|
record_and_statistics_write(client_message)
|
|
341
384
|
|
|
342
|
-
if is_socket_closed:
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
385
|
+
# if is_socket_closed:
|
|
386
|
+
# exception_or_close_in_receiving_thread = True
|
|
387
|
+
# finish_thread()
|
|
388
|
+
# return
|
|
346
389
|
|
|
347
390
|
# If we're in response mode, execute responder.
|
|
348
391
|
if config_static.TCPServer.server_response_mode:
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
is_socket_closed: bool = False
|
|
352
|
-
for response_raw_bytes in raw_responses:
|
|
353
|
-
client_message.reinitialize_dynamic_vars()
|
|
354
|
-
client_message.timestamp = datetime.now()
|
|
355
|
-
client_message.response_raw_bytes = response_raw_bytes
|
|
356
|
-
error_on_send: str = sender.Sender(
|
|
357
|
-
ssl_socket=client_socket, class_message=client_message.response_raw_bytes,
|
|
358
|
-
logger=network_logger).send()
|
|
359
|
-
|
|
360
|
-
# If there was problem with sending data, we'll break the main while loop.
|
|
361
|
-
if error_on_send:
|
|
362
|
-
client_message.errors.append(error_on_send)
|
|
363
|
-
record_and_statistics_write(client_message)
|
|
364
|
-
is_socket_closed = True
|
|
365
|
-
|
|
366
|
-
if is_socket_closed:
|
|
367
|
-
# exception_or_close_in_receiving_thread = True
|
|
368
|
-
return
|
|
392
|
+
responder_queue.put(client_message)
|
|
369
393
|
else:
|
|
370
394
|
# if side == 'Client':
|
|
371
395
|
# raise NotImplementedError
|
|
@@ -385,9 +409,10 @@ def thread_worker_main(
|
|
|
385
409
|
|
|
386
410
|
record_and_statistics_write(client_message)
|
|
387
411
|
|
|
388
|
-
# If the socket was closed, then we'll break the loop.
|
|
412
|
+
# If the socket was closed on message receive, then we'll break the loop only after send.
|
|
389
413
|
if is_socket_closed or error_on_send:
|
|
390
414
|
exception_or_close_in_receiving_thread = True
|
|
415
|
+
responder_queue.put('exit')
|
|
391
416
|
finish_thread()
|
|
392
417
|
return
|
|
393
418
|
except Exception as exc:
|
|
@@ -397,20 +422,31 @@ def thread_worker_main(
|
|
|
397
422
|
if isinstance(exc, OSError) and exc.errno == 10038:
|
|
398
423
|
print_api("Both sockets are closed, breaking the loop", logger=network_logger, logger_method='info')
|
|
399
424
|
else:
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
425
|
+
handle_exceptions_on_sub_connection_thread(client_message, exception_queue, exc)
|
|
426
|
+
|
|
427
|
+
def handle_exceptions_on_sub_connection_thread(
|
|
428
|
+
client_message: ClientMessage,
|
|
429
|
+
exception_queue: queue.Queue,
|
|
430
|
+
exc: Exception
|
|
431
|
+
):
|
|
432
|
+
nonlocal exception_or_close_in_receiving_thread
|
|
406
433
|
|
|
407
|
-
|
|
408
|
-
|
|
434
|
+
exception_or_close_in_receiving_thread=True
|
|
435
|
+
# handle_exceptions(exc, client_message, recorded)
|
|
436
|
+
exception_message = tracebacks.get_as_string(one_line=True)
|
|
437
|
+
|
|
438
|
+
error_message = f'Socket Thread [{str(thread_id)}] Exception: {exception_message}'
|
|
439
|
+
print_api("Exception in a thread, forwarding to parent thread.", logger_method='info', logger=network_logger)
|
|
440
|
+
client_message.errors.append(error_message)
|
|
441
|
+
|
|
442
|
+
# if not recorded:
|
|
443
|
+
# record_and_statistics_write(client_message)
|
|
409
444
|
|
|
410
|
-
|
|
411
|
-
|
|
445
|
+
finish_thread()
|
|
446
|
+
responder_queue.put('exit')
|
|
447
|
+
exception_queue.put(exc)
|
|
412
448
|
|
|
413
|
-
def
|
|
449
|
+
def handle_exceptions_on_main_connection_thread(
|
|
414
450
|
exc: Exception,
|
|
415
451
|
client_message: ClientMessage
|
|
416
452
|
):
|
|
@@ -441,7 +477,10 @@ def thread_worker_main(
|
|
|
441
477
|
|
|
442
478
|
thread_id = threads.current_thread_id()
|
|
443
479
|
|
|
480
|
+
# This is the main protocols.
|
|
444
481
|
protocol: str = str()
|
|
482
|
+
# This is the secondary protocol in the websocket.
|
|
483
|
+
protocol3: str = str()
|
|
445
484
|
# # This is Client Masked Frame Parser.
|
|
446
485
|
# websocket_masked_frame_parser = websocket_parse.WebsocketFrameParser()
|
|
447
486
|
# # This is Server UnMasked Frame Parser.
|
|
@@ -465,6 +504,8 @@ def thread_worker_main(
|
|
|
465
504
|
client_message_connection: ClientMessage = ClientMessage()
|
|
466
505
|
# This is needed to indicate if there was an exception or socket was closed in any of the receiving thread.
|
|
467
506
|
exception_or_close_in_receiving_thread: bool = False
|
|
507
|
+
# Responder queue for ClientMessage objects.
|
|
508
|
+
responder_queue: queue.Queue = queue.Queue()
|
|
468
509
|
|
|
469
510
|
try:
|
|
470
511
|
client_ip, source_port = client_socket.getpeername()
|
|
@@ -473,6 +514,15 @@ def thread_worker_main(
|
|
|
473
514
|
network_logger.info(f"Thread Created - Client [{client_ip}:{source_port}] | "
|
|
474
515
|
f"Destination service: [{server_name}:{destination_port}]")
|
|
475
516
|
|
|
517
|
+
# If we're in response mode, we'll start the responder thread.
|
|
518
|
+
if config_static.TCPServer.server_response_mode:
|
|
519
|
+
responder_thread: threading.Thread = threading.Thread(
|
|
520
|
+
target=responder_thread_worker, name=f"Thread-{thread_id}-Responder", daemon=True)
|
|
521
|
+
responder_thread.start()
|
|
522
|
+
else:
|
|
523
|
+
# noinspection PyTypeChecker
|
|
524
|
+
responder_thread = None
|
|
525
|
+
|
|
476
526
|
service_client = None
|
|
477
527
|
client_receive_count: int = 0
|
|
478
528
|
server_receive_count: int = 0
|
|
@@ -488,6 +538,11 @@ def thread_worker_main(
|
|
|
488
538
|
if not service_client:
|
|
489
539
|
service_client = create_client_socket(client_message_connection)
|
|
490
540
|
service_socket_instance, connection_error = service_client.service_connection()
|
|
541
|
+
else:
|
|
542
|
+
client_message_connection.timestamp = datetime.now()
|
|
543
|
+
client_message_connection.action = 'service_connect'
|
|
544
|
+
client_message_connection.info = 'Server Response Mode'
|
|
545
|
+
responder_queue.put(client_message_connection)
|
|
491
546
|
|
|
492
547
|
if connection_error:
|
|
493
548
|
client_message_connection.timestamp = datetime.now()
|
|
@@ -512,6 +567,8 @@ def thread_worker_main(
|
|
|
512
567
|
|
|
513
568
|
client_thread.join()
|
|
514
569
|
service_thread.join()
|
|
570
|
+
if config_static.TCPServer.server_response_mode:
|
|
571
|
+
responder_thread.join()
|
|
515
572
|
|
|
516
573
|
# If there was an exception in any of the threads, then we'll raise it here.
|
|
517
574
|
if not client_exception_queue.empty():
|
|
@@ -524,4 +581,4 @@ def thread_worker_main(
|
|
|
524
581
|
if not client_message_connection.timestamp:
|
|
525
582
|
client_message_connection.timestamp = datetime.now()
|
|
526
583
|
|
|
527
|
-
|
|
584
|
+
handle_exceptions_on_main_connection_thread(e, client_message_connection)
|
atomicshop/mitm/message.py
CHANGED
|
@@ -31,6 +31,7 @@ class ClientMessage:
|
|
|
31
31
|
self.errors: list = list()
|
|
32
32
|
self.protocol: str = str()
|
|
33
33
|
self.protocol2: str = str()
|
|
34
|
+
self.protocol3: str = str()
|
|
34
35
|
self.recorded_file_path: str = str()
|
|
35
36
|
self.action: str = str()
|
|
36
37
|
|
|
@@ -52,6 +53,7 @@ class ClientMessage:
|
|
|
52
53
|
self.errors = list()
|
|
53
54
|
self.protocol = str()
|
|
54
55
|
self.protocol2 = str()
|
|
56
|
+
self.protocol3 = str()
|
|
55
57
|
self.recorded_file_path = str()
|
|
56
58
|
|
|
57
59
|
def __iter__(self):
|
|
@@ -6,8 +6,8 @@ from ..loggingw import loggingw
|
|
|
6
6
|
|
|
7
7
|
LOGGER_NAME: str = 'statistics'
|
|
8
8
|
STATISTICS_HEADER: str = (
|
|
9
|
-
'request_time_sent,thread_id,tls,protocol,protocol2,host,path,command,status_code,request_size_bytes,
|
|
10
|
-
'process_cmd,action,error')
|
|
9
|
+
'request_time_sent,thread_id,tls,protocol,protocol2,protocol3,host,path,command,status_code,request_size_bytes,'
|
|
10
|
+
'response_size_bytes,file_path,process_cmd,action,error')
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class StatisticsCSVWriter:
|
|
@@ -36,6 +36,7 @@ class StatisticsCSVWriter:
|
|
|
36
36
|
tls_version: str,
|
|
37
37
|
protocol: str,
|
|
38
38
|
protocol2: str,
|
|
39
|
+
protocol3: str,
|
|
39
40
|
path: str,
|
|
40
41
|
status_code: str,
|
|
41
42
|
command: str,
|
|
@@ -61,6 +62,7 @@ class StatisticsCSVWriter:
|
|
|
61
62
|
tls_info,
|
|
62
63
|
protocol,
|
|
63
64
|
protocol2,
|
|
65
|
+
protocol3,
|
|
64
66
|
host,
|
|
65
67
|
path,
|
|
66
68
|
command,
|
|
@@ -100,6 +102,7 @@ class StatisticsCSVWriter:
|
|
|
100
102
|
tls_version='',
|
|
101
103
|
protocol='',
|
|
102
104
|
protocol2='',
|
|
105
|
+
protocol3='',
|
|
103
106
|
path='',
|
|
104
107
|
status_code='',
|
|
105
108
|
command='',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
atomicshop/__init__.py,sha256=
|
|
1
|
+
atomicshop/__init__.py,sha256=EPl1ua1q9CfR8reaw61h0P-bol2bj9D-p6to1iUifSY,123
|
|
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
|
|
@@ -125,12 +125,12 @@ atomicshop/file_io/tomls.py,sha256=ol8EvQPf9sryTmZUf1v55BYSUQ6ml7HVVBHpNKbsIlA,9
|
|
|
125
125
|
atomicshop/file_io/xlsxs.py,sha256=v_dyg9GD4LqgWi6wA1QuWRZ8zG4ZwB6Dz52ytdcmmmI,2184
|
|
126
126
|
atomicshop/file_io/xmls.py,sha256=zh3SuK-dNaFq2NDNhx6ivcf4GYCfGM8M10PcEwDSpxk,2104
|
|
127
127
|
atomicshop/mitm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
128
|
-
atomicshop/mitm/config_static.py,sha256=
|
|
128
|
+
atomicshop/mitm/config_static.py,sha256=HIzxyMEj7DZksYvJsN5VuKpB-_HSVvuR6U59ztS9gi0,7871
|
|
129
129
|
atomicshop/mitm/config_toml_editor.py,sha256=2p1CMcktWRR_NW-SmyDwylu63ad5e0-w1QPMa8ZLDBw,1635
|
|
130
|
-
atomicshop/mitm/connection_thread_worker.py,sha256=
|
|
130
|
+
atomicshop/mitm/connection_thread_worker.py,sha256=d7XMZoXbXm9IUywg-IIVApad-NKpSdErLWgHtK8A4F4,26623
|
|
131
131
|
atomicshop/mitm/import_config.py,sha256=0Ij14aISTllTOiWYJpIUMOWobQqGofD6uafui5uWllE,9272
|
|
132
132
|
atomicshop/mitm/initialize_engines.py,sha256=NWz0yBErSrYBn0xWkJDBcHStBJ-kcsv9VtorcSP9x5M,8258
|
|
133
|
-
atomicshop/mitm/message.py,sha256=
|
|
133
|
+
atomicshop/mitm/message.py,sha256=mNo4Lphr_Jo6IlNX5mPJzABpogWGkjOhwI4meAivwHw,2987
|
|
134
134
|
atomicshop/mitm/mitm_main.py,sha256=AxmqUiDHgfzqmIF8v2GZxlEKth6_AMaYcqAxziWMG0U,23430
|
|
135
135
|
atomicshop/mitm/recs_files.py,sha256=ZAAD0twun-FtmbSniXe3XQhIlawvANNB_HxwbHj7kwI,3151
|
|
136
136
|
atomicshop/mitm/shared_functions.py,sha256=0lzeyINd44sVEfFbahJxQmz6KAMWbYrW5ou3UYfItvw,1777
|
|
@@ -316,11 +316,11 @@ atomicshop/wrappers/socketw/socket_client.py,sha256=oa3GwS4OPgokrJE5_Oc4-5_wlXHx
|
|
|
316
316
|
atomicshop/wrappers/socketw/socket_server_tester.py,sha256=Qobmh4XV8ZxLUaw-eW4ESKAbeSLecCKn2OWFzMhadk0,6420
|
|
317
317
|
atomicshop/wrappers/socketw/socket_wrapper.py,sha256=WtylpezgIIBuz-A6PfM0hO1sm9Exd4j3qhDXcFc74-E,35567
|
|
318
318
|
atomicshop/wrappers/socketw/ssl_base.py,sha256=kmiif84kMhBr5yjQW17p935sfjR5JKG0LxIwBA4iVvU,2275
|
|
319
|
-
atomicshop/wrappers/socketw/statistics_csv.py,sha256=
|
|
319
|
+
atomicshop/wrappers/socketw/statistics_csv.py,sha256=fgMzDXI0cybwUEqAxprRmY3lqbh30KAV-jOpoFKT-m8,3395
|
|
320
320
|
atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
321
321
|
atomicshop/wrappers/winregw/winreg_network.py,sha256=zZQfps-CdODQaTUADbHAwKHr5RUg7BLafnKWBbKaLN4,8728
|
|
322
|
-
atomicshop-2.18.
|
|
323
|
-
atomicshop-2.18.
|
|
324
|
-
atomicshop-2.18.
|
|
325
|
-
atomicshop-2.18.
|
|
326
|
-
atomicshop-2.18.
|
|
322
|
+
atomicshop-2.18.2.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
|
|
323
|
+
atomicshop-2.18.2.dist-info/METADATA,sha256=jeXe5N1uxADb9T7GA5B10ENn-cmKa6WN6RywG1h3WgY,10499
|
|
324
|
+
atomicshop-2.18.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
325
|
+
atomicshop-2.18.2.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
|
|
326
|
+
atomicshop-2.18.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|