atomicshop 3.3.8__py3-none-any.whl → 3.10.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 (120) hide show
  1. atomicshop/__init__.py +1 -1
  2. atomicshop/a_mains/get_local_tcp_ports.py +85 -0
  3. atomicshop/a_mains/install_ca_certificate.py +172 -0
  4. atomicshop/a_mains/process_from_port.py +119 -0
  5. atomicshop/a_mains/set_default_dns_gateway.py +90 -0
  6. atomicshop/basics/strings.py +1 -1
  7. atomicshop/certificates.py +2 -2
  8. atomicshop/dns.py +26 -28
  9. atomicshop/etws/traces/trace_tcp.py +1 -2
  10. atomicshop/mitm/centered_settings.py +133 -0
  11. atomicshop/mitm/config_static.py +22 -44
  12. atomicshop/mitm/connection_thread_worker.py +383 -165
  13. atomicshop/mitm/engines/__parent/recorder___parent.py +1 -1
  14. atomicshop/mitm/engines/__parent/requester___parent.py +1 -1
  15. atomicshop/mitm/engines/__parent/responder___parent.py +15 -2
  16. atomicshop/mitm/engines/create_module_template.py +1 -2
  17. atomicshop/mitm/import_config.py +91 -89
  18. atomicshop/mitm/initialize_engines.py +1 -2
  19. atomicshop/mitm/message.py +5 -4
  20. atomicshop/mitm/mitm_main.py +238 -122
  21. atomicshop/mitm/recs_files.py +61 -5
  22. atomicshop/mitm/ssh_tester.py +82 -0
  23. atomicshop/mitm/statistic_analyzer.py +33 -12
  24. atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py +104 -31
  25. atomicshop/networks.py +160 -92
  26. atomicshop/package_mains_processor.py +84 -0
  27. atomicshop/permissions/ubuntu_permissions.py +47 -0
  28. atomicshop/print_api.py +3 -5
  29. atomicshop/process.py +11 -4
  30. atomicshop/python_functions.py +23 -108
  31. atomicshop/speech_recognize.py +8 -0
  32. atomicshop/ssh_remote.py +140 -164
  33. atomicshop/web.py +63 -22
  34. atomicshop/web_apis/google_llm.py +22 -14
  35. atomicshop/wrappers/ctyping/msi_windows_installer/cabs.py +2 -1
  36. atomicshop/wrappers/ctyping/msi_windows_installer/extract_msi_main.py +2 -1
  37. atomicshop/wrappers/dockerw/dockerw.py +2 -2
  38. atomicshop/wrappers/elasticsearchw/config_basic.py +0 -12
  39. atomicshop/wrappers/elasticsearchw/elastic_infra.py +0 -190
  40. atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py +5 -5
  41. atomicshop/wrappers/githubw.py +180 -68
  42. atomicshop/wrappers/loggingw/consts.py +1 -1
  43. atomicshop/wrappers/loggingw/handlers.py +1 -1
  44. atomicshop/wrappers/loggingw/loggingw.py +20 -4
  45. atomicshop/wrappers/loggingw/reading.py +18 -0
  46. atomicshop/wrappers/mongodbw/mongo_infra.py +0 -38
  47. atomicshop/wrappers/netshw.py +124 -3
  48. atomicshop/wrappers/playwrightw/scenarios.py +1 -1
  49. atomicshop/wrappers/powershell_networking.py +80 -0
  50. atomicshop/wrappers/psutilw/psutil_networks.py +9 -0
  51. atomicshop/wrappers/pywin32w/win_event_log/fetch.py +174 -0
  52. atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_create.py +3 -105
  53. atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_terminate.py +3 -57
  54. atomicshop/wrappers/pywin32w/wmis/win32_networkadapterconfiguration.py +12 -27
  55. atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +15 -9
  56. atomicshop/wrappers/socketw/certificator.py +19 -9
  57. atomicshop/wrappers/socketw/creator.py +101 -14
  58. atomicshop/wrappers/socketw/dns_server.py +17 -5
  59. atomicshop/wrappers/socketw/exception_wrapper.py +21 -16
  60. atomicshop/wrappers/socketw/process_getter.py +86 -0
  61. atomicshop/wrappers/socketw/receiver.py +29 -9
  62. atomicshop/wrappers/socketw/sender.py +10 -9
  63. atomicshop/wrappers/socketw/sni.py +31 -10
  64. atomicshop/wrappers/socketw/{base.py → socket_base.py} +33 -1
  65. atomicshop/wrappers/socketw/socket_client.py +11 -10
  66. atomicshop/wrappers/socketw/socket_wrapper.py +125 -32
  67. atomicshop/wrappers/socketw/ssl_base.py +6 -2
  68. atomicshop/wrappers/ubuntu_terminal.py +21 -18
  69. atomicshop/wrappers/win_auditw.py +189 -0
  70. {atomicshop-3.3.8.dist-info → atomicshop-3.10.0.dist-info}/METADATA +25 -30
  71. {atomicshop-3.3.8.dist-info → atomicshop-3.10.0.dist-info}/RECORD +83 -109
  72. atomicshop/_basics_temp.py +0 -101
  73. atomicshop/a_installs/ubuntu/docker_rootless.py +0 -11
  74. atomicshop/a_installs/ubuntu/docker_sudo.py +0 -11
  75. atomicshop/a_installs/ubuntu/elastic_search_and_kibana.py +0 -10
  76. atomicshop/a_installs/ubuntu/mongodb.py +0 -12
  77. atomicshop/a_installs/win/fibratus.py +0 -9
  78. atomicshop/a_installs/win/mongodb.py +0 -9
  79. atomicshop/a_installs/win/wsl_ubuntu_lts.py +0 -10
  80. atomicshop/addons/a_setup_scripts/install_psycopg2_ubuntu.sh +0 -3
  81. atomicshop/addons/package_setup/CreateWheel.cmd +0 -7
  82. atomicshop/addons/package_setup/Setup in Edit mode.cmd +0 -6
  83. atomicshop/addons/package_setup/Setup.cmd +0 -7
  84. atomicshop/archiver/__init__.py +0 -0
  85. atomicshop/archiver/_search_in_zip.py +0 -189
  86. atomicshop/archiver/search_in_archive.py +0 -284
  87. atomicshop/archiver/sevenz_app_w.py +0 -86
  88. atomicshop/archiver/sevenzs.py +0 -73
  89. atomicshop/archiver/shutils.py +0 -34
  90. atomicshop/archiver/zips.py +0 -353
  91. atomicshop/file_types.py +0 -24
  92. atomicshop/pbtkmultifile_argparse.py +0 -88
  93. atomicshop/script_as_string_processor.py +0 -42
  94. atomicshop/ssh_scripts/process_from_ipv4.py +0 -37
  95. atomicshop/ssh_scripts/process_from_port.py +0 -27
  96. atomicshop/wrappers/_process_wrapper_curl.py +0 -27
  97. atomicshop/wrappers/_process_wrapper_tar.py +0 -21
  98. atomicshop/wrappers/dockerw/install_docker.py +0 -449
  99. atomicshop/wrappers/elasticsearchw/install_elastic.py +0 -233
  100. atomicshop/wrappers/ffmpegw.py +0 -125
  101. atomicshop/wrappers/fibratusw/__init__.py +0 -0
  102. atomicshop/wrappers/fibratusw/install.py +0 -80
  103. atomicshop/wrappers/mongodbw/install_mongodb_ubuntu.py +0 -100
  104. atomicshop/wrappers/mongodbw/install_mongodb_win.py +0 -244
  105. atomicshop/wrappers/process_wrapper_pbtk.py +0 -16
  106. atomicshop/wrappers/socketw/get_process.py +0 -123
  107. atomicshop/wrappers/wslw.py +0 -192
  108. atomicshop-3.3.8.dist-info/entry_points.txt +0 -2
  109. /atomicshop/{addons → a_mains/addons}/PlayWrightCodegen.cmd +0 -0
  110. /atomicshop/{addons → a_mains/addons}/ScriptExecution.cmd +0 -0
  111. /atomicshop/{addons → a_mains/addons}/inits/init_to_import_all_modules.py +0 -0
  112. /atomicshop/{addons → a_mains/addons}/process_list/ReadMe.txt +0 -0
  113. /atomicshop/{addons → a_mains/addons}/process_list/compile.cmd +0 -0
  114. /atomicshop/{addons → a_mains/addons}/process_list/compiled/Win10x64/process_list.dll +0 -0
  115. /atomicshop/{addons → a_mains/addons}/process_list/compiled/Win10x64/process_list.exp +0 -0
  116. /atomicshop/{addons → a_mains/addons}/process_list/compiled/Win10x64/process_list.lib +0 -0
  117. /atomicshop/{addons → a_mains/addons}/process_list/process_list.cpp +0 -0
  118. {atomicshop-3.3.8.dist-info → atomicshop-3.10.0.dist-info}/WHEEL +0 -0
  119. {atomicshop-3.3.8.dist-info → atomicshop-3.10.0.dist-info}/licenses/LICENSE.txt +0 -0
  120. {atomicshop-3.3.8.dist-info → atomicshop-3.10.0.dist-info}/top_level.txt +0 -0
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.3.8'
4
+ __version__ = '3.10.0'
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env python3
2
+ import argparse
3
+ import sys
4
+
5
+ import psutil
6
+
7
+
8
+ def _make_parser():
9
+ parser = argparse.ArgumentParser(
10
+ description="List all local TCP source ports currently in use that have a command line."
11
+ )
12
+
13
+ parser.add_argument(
14
+ '-a', '--show-all', action='store_true',
15
+ help='Show all the TCP ports and not only these that have command line.')
16
+
17
+ return parser
18
+
19
+
20
+ def main(
21
+ show_all: bool = False
22
+ ) -> int:
23
+ # Use a set so we only print each port once
24
+ source_ports = set()
25
+
26
+ try:
27
+ # Get all TCP connections (any state)
28
+ # If you only want established ones, use: kind='tcp' and filter by c.status
29
+ connections = psutil.net_connections(kind='tcp')
30
+ except psutil.AccessDenied:
31
+ print("Access denied when reading connections. Try running as admin/root.")
32
+ return 1
33
+ except Exception as e:
34
+ print(f"Error getting connections: {e}")
35
+ return 1
36
+
37
+ # Cache whether each PID has a non-empty cmdline to avoid repeated lookups
38
+ pid_has_cmdline: dict[int, bool] = {}
39
+
40
+ for c in connections:
41
+ # c.laddr is the local (source) address; may be empty for some entries
42
+ if not c.laddr:
43
+ continue
44
+
45
+ # psutil uses a namedtuple for laddr: (ip, port)
46
+ try:
47
+ port = c.laddr.port # works on modern psutil (namedtuple)
48
+ except AttributeError:
49
+ # fallback if it's a plain tuple
50
+ port = c.laddr[1]
51
+
52
+ if not show_all:
53
+ pid = c.pid
54
+ if pid is None:
55
+ # No associated process => treat as "no command line"
56
+ continue
57
+
58
+ if pid not in pid_has_cmdline:
59
+ try:
60
+ proc = psutil.Process(pid)
61
+ cmdline = proc.cmdline()
62
+ # Non-empty list and at least one non-empty arg
63
+ has_cmd = bool(cmdline and any(arg.strip() for arg in cmdline))
64
+ pid_has_cmdline[pid] = has_cmd
65
+ except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
66
+ # If we can't read it, treat as no command line
67
+ pid_has_cmdline[pid] = False
68
+
69
+ if not pid_has_cmdline[pid]:
70
+ # Skip ports whose owning process has an empty/unavailable cmdline
71
+ continue
72
+
73
+ # Either show_all is True, or the owning process has a non-empty cmdline
74
+ source_ports.add(port)
75
+
76
+ # Print ports sorted for readability
77
+ for port in sorted(source_ports):
78
+ print(port)
79
+
80
+ return 0
81
+
82
+ if __name__ == "__main__":
83
+ arg_parser = _make_parser()
84
+ args = arg_parser.parse_args()
85
+ sys.exit(main(**vars(args)))
@@ -0,0 +1,172 @@
1
+ import sys
2
+ import os
3
+ import tempfile
4
+ import subprocess
5
+ import re
6
+ import base64
7
+ import textwrap
8
+
9
+
10
+ def is_ca_installed(issuer_name: str) -> tuple[bool, str]:
11
+ result = subprocess.run(
12
+ ['certutil', '-store', 'Root', issuer_name],
13
+ capture_output=True,
14
+ text=True,
15
+ )
16
+
17
+ if 'Object was not found' in result.stdout:
18
+ return False, ''
19
+
20
+ if result.returncode == 0:
21
+ return True, ''
22
+ else:
23
+ message: str = (f"stdout: {result.stdout}\n"
24
+ f"stderr: {result.stderr}\n")
25
+ return False, message
26
+
27
+
28
+ def remove_ca_certificate(issuer_name: str) -> int:
29
+ result = subprocess.run(
30
+ ['certutil', '-delstore', 'Root', issuer_name],
31
+ capture_output=True,
32
+ text=True
33
+ )
34
+
35
+ if result.returncode != 0:
36
+ print(f"Error removing certificate: {result.stderr}", file=sys.stderr)
37
+ return 1
38
+
39
+ return 0
40
+
41
+
42
+ def install_ca_certificate(certificate_string: str) -> int:
43
+ pem = certificate_string or ""
44
+
45
+ # Extract one or more CERTIFICATE blocks
46
+ blocks = re.findall(
47
+ r"-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----",
48
+ pem,
49
+ flags=re.DOTALL,
50
+ )
51
+ if not blocks:
52
+ print("Error installing certificate: no PEM CERTIFICATE block found.", file=sys.stderr)
53
+ return 1
54
+
55
+ def normalize_pem(block: str) -> str:
56
+ m = re.search(
57
+ r"-----BEGIN CERTIFICATE-----(.*?)-----END CERTIFICATE-----",
58
+ block,
59
+ flags=re.DOTALL,
60
+ )
61
+ if not m:
62
+ raise ValueError("Invalid PEM block.")
63
+
64
+ # Remove everything except Base64 alphabet and padding
65
+ b64 = re.sub(r"[^A-Za-z0-9+/=]", "", m.group(1))
66
+
67
+ # Strict decode/encode round-trip to ensure it is valid DER
68
+ der = base64.b64decode(b64, validate=True)
69
+ b64_clean = base64.b64encode(der).decode("ascii")
70
+ wrapped = "\r\n".join(textwrap.wrap(b64_clean, 64))
71
+
72
+ return (
73
+ "-----BEGIN CERTIFICATE-----\r\n"
74
+ + wrapped
75
+ + "\r\n-----END CERTIFICATE-----\r\n"
76
+ )
77
+
78
+ for block in blocks:
79
+ tmp_path = None
80
+ try:
81
+ normalized = normalize_pem(block)
82
+
83
+ with tempfile.NamedTemporaryFile(
84
+ mode="w",
85
+ suffix=".cer",
86
+ delete=False, # certutil needs a real path on Windows
87
+ encoding="ascii",
88
+ newline="",
89
+ ) as f:
90
+ f.write(normalized)
91
+ tmp_path = f.name
92
+
93
+ result = subprocess.run(
94
+ ["certutil", "-f", "-addstore", "Root", tmp_path],
95
+ text=True,
96
+ capture_output=True,
97
+ )
98
+
99
+ if result.returncode != 0:
100
+ # Optional: try to get a more descriptive parse error
101
+ dump = subprocess.run(
102
+ ["certutil", "-dump", tmp_path],
103
+ text=True,
104
+ capture_output=True,
105
+ )
106
+
107
+ print(
108
+ "Error installing certificate:\n"
109
+ f"stdout: {result.stdout}\n"
110
+ f"stderr: {result.stderr}\n"
111
+ "certutil -dump output:\n"
112
+ f"{dump.stdout}\n"
113
+ f"{dump.stderr}",
114
+ file=sys.stderr,
115
+ )
116
+ return 1
117
+
118
+ except Exception as e:
119
+ print(f"Error installing certificate: {e}", file=sys.stderr)
120
+ return 1
121
+
122
+ finally:
123
+ if tmp_path:
124
+ try:
125
+ os.remove(tmp_path)
126
+ except OSError:
127
+ pass
128
+
129
+ return 0
130
+
131
+
132
+ def main() -> int:
133
+ if len(sys.argv) < 3:
134
+ print("Usage: install_ca_certificate.py <Issuer Name> <crt cert string>", file=sys.stderr)
135
+ return 1
136
+
137
+ certificate_string_base64: str = sys.argv[2]
138
+ certificate_string = base64.b64decode(certificate_string_base64).decode("utf-8")
139
+ if not "-----BEGIN CERTIFICATE-----" in certificate_string:
140
+ print("Error: Certificate string must be in PEM format.", file=sys.stderr)
141
+ print(certificate_string, file=sys.stderr)
142
+ return 1
143
+
144
+ issuer_name: str = sys.argv[1]
145
+ is_installed, message = is_ca_installed(issuer_name)
146
+ if not is_installed and message:
147
+ print(f"Error checking certificate installation: {message}", file=sys.stderr)
148
+ return 1
149
+
150
+ if is_installed:
151
+ rc: int = remove_ca_certificate(issuer_name)
152
+ if rc != 0:
153
+ return rc
154
+
155
+ rc: int = install_ca_certificate(certificate_string)
156
+ if rc != 0:
157
+ return rc
158
+
159
+ is_installed, message = is_ca_installed(issuer_name)
160
+ if not is_installed and message:
161
+ print(f"Error checking certificate installation: {message}", file=sys.stderr)
162
+ return 1
163
+
164
+ if not is_installed:
165
+ print("Error: Certificate installation failed.", file=sys.stderr)
166
+ return 1
167
+
168
+ return 0
169
+
170
+
171
+ if __name__ == '__main__':
172
+ sys.exit(main())
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Print the command line of the process that owns a given TCP/UDP source port.
4
+
5
+ Usage:
6
+ python get_cmdline_from_port.py <port> [kind]
7
+
8
+ <port> is required (e.g. 54321)
9
+ [kind] is optional: 'tcp', 'udp', or 'inet' (default: 'inet')
10
+
11
+ Requires: psutil
12
+
13
+ ===========================
14
+
15
+ In Ubuntu, you can check available TCP connections and processes with:
16
+ ss -tnpa
17
+ In Windows, you can check available TCP connections and processes with (only PIDs, no command lines):
18
+ netstat -ano
19
+ """
20
+
21
+ import sys
22
+ import shlex
23
+ import psutil
24
+
25
+
26
+ def find_cmdline_by_port(
27
+ port: int,
28
+ # kind: str = "inet"
29
+ kind: str = "tcp"
30
+ ) -> str | None:
31
+ """
32
+ Return the command line (joined string) of the first process whose local
33
+ port == `port`, for connections of type `kind` ('tcp', 'udp', 'inet', etc).
34
+
35
+ 'tcp' is much more specific and faster than 'inet' (which includes both TCP and UDP).
36
+ """
37
+
38
+ # Single system-wide call; 'inet' = IPv4 + IPv6 only (no unix sockets)
39
+ # Use 'tcp' if you know it's TCP only – slightly faster.
40
+ try:
41
+ conns = psutil.net_connections(kind=kind)
42
+ except psutil.Error:
43
+ return None
44
+
45
+ for conn in conns:
46
+ # Some entries have no local address or PID (e.g. kernel sockets)
47
+ laddr = conn.laddr
48
+ if not laddr:
49
+ continue
50
+
51
+ # laddr is a namedtuple (ip, port) for AF_INET / AF_INET6
52
+ try:
53
+ local_port = laddr.port
54
+ except AttributeError:
55
+ # Older psutil: laddr is a simple tuple (ip, port)
56
+ if len(laddr) < 2:
57
+ continue
58
+ local_port = laddr[1]
59
+
60
+ if local_port != port:
61
+ continue
62
+
63
+ pid = conn.pid
64
+ if pid is None or pid == 0:
65
+ continue
66
+
67
+ try:
68
+ proc = psutil.Process(pid)
69
+ cmdline_list = proc.cmdline()
70
+ except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
71
+ continue
72
+
73
+ if cmdline_list:
74
+ result = shlex.join(cmdline_list)
75
+ else:
76
+ # Fallback to process name if cmdline missing
77
+ try:
78
+ result = proc.name()
79
+ except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
80
+ return None
81
+
82
+ # If result is just a PID string, also fallback to name
83
+ if result.isnumeric():
84
+ try:
85
+ result = proc.name()
86
+ except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
87
+ return None
88
+
89
+ return result
90
+
91
+ return None
92
+
93
+
94
+ def main() -> None:
95
+ if len(sys.argv) < 2:
96
+ print("Usage: get_cmdline_from_port.py <port> [kind]", file=sys.stderr)
97
+ sys.exit(1)
98
+
99
+ try:
100
+ port = int(sys.argv[1])
101
+ except ValueError:
102
+ print("Port must be an integer", file=sys.stderr)
103
+ sys.exit(1)
104
+
105
+ kind = sys.argv[2] if len(sys.argv) >= 3 else "tcp"
106
+
107
+ result = find_cmdline_by_port(port, kind)
108
+ if result is not None:
109
+ print(result)
110
+ sys.exit(0)
111
+ else:
112
+ # Print nothing, or a message – up to you.
113
+ # Empty output is often nicer for scripts that just parse stdout.
114
+ # print(f"No process found with local port {port}", file=sys.stderr)
115
+ sys.exit(2)
116
+
117
+
118
+ if __name__ == "__main__":
119
+ main()
@@ -0,0 +1,90 @@
1
+ import sys
2
+ import socket
3
+ from typing import Union
4
+ import ipaddress
5
+ import subprocess
6
+
7
+ import psutil
8
+
9
+
10
+ def is_ip_address(string_value: str) -> bool:
11
+ try:
12
+ ipaddress.IPv4Address(string_value)
13
+ return True
14
+ except (ipaddress.AddressValueError, ValueError):
15
+ return False
16
+
17
+
18
+ def get_default_internet_ipv4(target: str = "8.8.8.8") -> str:
19
+ with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
20
+ s.connect((target, 80)) # no packet sent; OS just chooses a route
21
+ return s.getsockname()[0] # local address of that route
22
+
23
+
24
+ def get_default_connection_name() -> Union[dict, None]:
25
+ """
26
+ Function to get the default network interface.
27
+ :return: dict[interface_name: details] or None.
28
+ """
29
+ # Get all interfaces.
30
+ interfaces: dict = psutil.net_if_addrs()
31
+ default_ip_address: str = get_default_internet_ipv4()
32
+
33
+ for interface, details in interfaces.items():
34
+ for address in details:
35
+ # Check if the address is an IPv4 address (AF_INET) and not a loopback (127.0.0.1)
36
+ if address.family == socket.AF_INET and not address.address.startswith('127.'):
37
+ # Check if the address is the default IP address.
38
+ if address.address == default_ip_address:
39
+ return {interface: details}
40
+
41
+ return None
42
+
43
+
44
+ def get_default_interface_name() -> str:
45
+ default_connection_name_dict: dict = get_default_connection_name()
46
+ if not default_connection_name_dict:
47
+ return ""
48
+ # Get the first key from the dictionary.
49
+ connection_name: str = list(default_connection_name_dict.keys())[0]
50
+ return connection_name
51
+
52
+
53
+ def set_default_gateway_ipv4(gateway_ipv4: str) -> str | None:
54
+ interface_name: str = get_default_interface_name()
55
+ if not interface_name:
56
+ return "Could not determine the default network interface name."
57
+
58
+ # Set the default gateway using 'netsh' command.
59
+ command: str = f'netsh interface ipv4 set dns name="{interface_name}" static {gateway_ipv4} primary'
60
+ result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
61
+ stdout: str = result.stdout.decode().strip()
62
+ stderr: str = result.stderr.decode().strip()
63
+
64
+ if result.returncode != 0:
65
+ return (f"stdout: {stdout}\n"
66
+ f"stderr: {stderr}")
67
+
68
+ return None
69
+
70
+
71
+ def main() -> int:
72
+ if len(sys.argv) < 2:
73
+ print("Usage: set_default_dns_gateway.py <IPv4>", file=sys.stderr)
74
+ return 1
75
+
76
+ dns_ipv4: str = sys.argv[1]
77
+ if not is_ip_address(dns_ipv4):
78
+ print("Invalid IPv4 address", file=sys.stderr)
79
+ return 1
80
+
81
+ error_message: str | None = set_default_gateway_ipv4(dns_ipv4)
82
+ if error_message:
83
+ print(f"Failed to set default DNS gateway:\n{error_message}", file=sys.stderr)
84
+ return 1
85
+
86
+ return 0
87
+
88
+
89
+ if __name__ == '__main__':
90
+ sys.exit(main())
@@ -423,7 +423,7 @@ def replace_words_with_values_from_dict(
423
423
 
424
424
 
425
425
  def replace_strings_with_values_from_dict(string_to_replace: str, dictionary: dict) -> str:
426
- """
426
+ r"""
427
427
  Function replaces strings, which are keys with values from dictionary.
428
428
 
429
429
  :param string_to_replace: string, to replace words in.
@@ -5,7 +5,7 @@ https://oidref.com/1.3.6.1.5.5.7.3.1
5
5
 
6
6
 
7
7
  import ssl
8
- from typing import Literal
8
+ from typing import Literal, Any
9
9
 
10
10
  from .wrappers import cryptographyw
11
11
  from .wrappers.pywin32w import cert_store
@@ -64,7 +64,7 @@ def write_crt_certificate_file_in_pem_format_from_pem_file(
64
64
 
65
65
 
66
66
  def is_certificate_in_store(
67
- certificate: any = None,
67
+ certificate: Any = None,
68
68
  by_cert_issuer: bool = True,
69
69
  by_cert_thumbprint: bool = True,
70
70
  issuer_name: str = None,
atomicshop/dns.py CHANGED
@@ -5,6 +5,7 @@ import argparse
5
5
  import dns.resolver
6
6
 
7
7
  from . import print_api
8
+ from . import networks
8
9
  from .permissions import permissions
9
10
  from .wrappers.pywin32w.wmis import win32networkadapter
10
11
  from .wrappers import netshw
@@ -98,38 +99,31 @@ def get_default_dns_gateway_with_dns_resolver() -> list[str]:
98
99
  return dns_servers
99
100
 
100
101
 
101
- def set_connection_dns_gateway_static(
102
- dns_servers: list[str],
103
- connection_name: str = None,
104
- use_default_connection: bool = False
102
+ def set_interface_dns_gateway_static(
103
+ interface_name: str,
104
+ dns_servers: list[str]
105
105
  ) -> None:
106
106
  """
107
107
  Set the DNS servers for a network adapter.
108
- :param connection_name: string, adapter name as shown in the network settings.
108
+ :param interface_name: string, adapter name as shown in the network settings.
109
109
  :param dns_servers: list of strings, DNS server IPv4 addresses.
110
- :param use_default_connection: bool, if True, the default network interface will be used. This is the connection
111
- that you internet is being used from.
112
110
  :return: None
113
111
  """
114
112
 
115
- win32networkadapter.set_dns_server(
116
- connection_name=connection_name, dns_servers=dns_servers, use_default_interface=use_default_connection)
113
+ win32networkadapter.set_dns_server(interface_name=interface_name, dns_servers=dns_servers)
117
114
 
118
115
 
119
- def set_connection_dns_gateway_dynamic(
120
- connection_name: str = None,
121
- use_default_connection: bool = False
116
+ def set_interface_dns_gateway_dynamic(
117
+ interface_name: str = None
122
118
  ) -> None:
123
119
  """
124
120
  Set the DNS servers for a network adapter to obtain them automatically from DHCP.
125
- :param connection_name: string, adapter name as shown in the network settings.
126
- :param use_default_connection: bool, if True, the default network interface will be used. This is the connection
127
- that you internet is being used from.
121
+ :param interface_name: string, adapter name as shown in the network settings.
128
122
  :return: None
129
123
  """
130
124
 
131
125
  win32networkadapter.set_dns_server(
132
- connection_name=connection_name, dns_servers=None, use_default_interface=use_default_connection)
126
+ interface_name=interface_name, dns_servers=None)
133
127
 
134
128
 
135
129
  def default_dns_gateway_main() -> int:
@@ -150,17 +144,17 @@ def default_dns_gateway_main() -> int:
150
144
  '-d', '--dynamic', action='store_true',
151
145
  help='Set the DNS gateway to obtain automatically from DHCP.')
152
146
 
153
- arg_connection_group = argparse_obj.add_mutually_exclusive_group()
154
- arg_connection_group.add_argument(
155
- '-cn', '--connection_name', type=str, help='Connection name as shown in the network settings.')
156
- arg_connection_group.add_argument(
157
- '-cd', '--connection_default', action='store_true', help='Use the default connection.')
147
+ arg_interface_group = argparse_obj.add_mutually_exclusive_group()
148
+ arg_interface_group.add_argument(
149
+ '-in', '--interface_name', type=str, help='Network Interface name as shown in the network settings.')
150
+ arg_interface_group.add_argument(
151
+ '-id', '--interface_default', action='store_true', help='Use the default network interface.')
158
152
 
159
153
  args = argparse_obj.parse_args()
160
154
 
161
- if (args.set or args.dynamic) and not (args.connection_name or args.connection_default):
155
+ if (args.set or args.dynamic) and not (args.interface_name or args.interface_default):
162
156
  print_api.print_api(
163
- "Please provide the connection name [-cn] or use the default connection [-cd].", color='red')
157
+ "Please provide the interface name [-in] or use the default interface [-id].", color='red')
164
158
  return 1
165
159
 
166
160
  if args.set or args.dynamic:
@@ -168,6 +162,12 @@ def default_dns_gateway_main() -> int:
168
162
  print_api.print_api("You need to run this script as an administrator", color='red')
169
163
  return 1
170
164
 
165
+ def get_interface_name() -> str:
166
+ if args.interface_default:
167
+ return networks.get_default_interface_name()
168
+ else:
169
+ return args.interface_name
170
+
171
171
  if args.get:
172
172
  is_dynamic, dns_servers = get_default_dns_gateway()
173
173
 
@@ -178,11 +178,9 @@ def default_dns_gateway_main() -> int:
178
178
  print_api.print_api(f'DNS Gateway: {is_dynamic_string} - {dns_servers}', color='blue')
179
179
  elif args.set:
180
180
  # dns_servers_list: list = args.dns_servers.split(',')
181
- set_connection_dns_gateway_static(
182
- dns_servers=args.set, connection_name=args.connection_name,
183
- use_default_connection=args.connection_default)
181
+ set_interface_dns_gateway_static(
182
+ dns_servers=args.set, interface_name=get_interface_name())
184
183
  elif args.dynamic:
185
- set_connection_dns_gateway_dynamic(
186
- connection_name=args.connection_name, use_default_connection=args.connection_default)
184
+ set_interface_dns_gateway_dynamic(interface_name=get_interface_name())
187
185
 
188
186
  return 0
@@ -1,8 +1,7 @@
1
1
  import multiprocessing.managers
2
2
 
3
- from .. import trace, const, providers
3
+ from .. import trace, providers
4
4
  from ...basics import dicts
5
- from ... import dns, ip_addresses
6
5
 
7
6
 
8
7
  ETW_DEFAULT_SESSION_NAME: str = 'AtomicShopTcpTrace'