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
@@ -0,0 +1,80 @@
1
+ import json
2
+ import subprocess
3
+ from typing import List, Literal
4
+
5
+
6
+ def get_interface_ips(
7
+ interface_name: str,
8
+ ip_type: Literal["virtual", "dynamic", "all"] = "virtual"
9
+ ) -> List[str]:
10
+ """
11
+ Return IPv4 addresses on an interface, filtered by 'mode'.
12
+
13
+ ip_type:
14
+ - "virtual": only static/virtual IPs (PrefixOrigin != 'Dhcp')
15
+ - "dynamic": only DHCP IPs (PrefixOrigin == 'Dhcp')
16
+ - "all": all IPv4 IPs on the interface
17
+
18
+ If the interface does not exist or has no IPv4 addresses, returns [].
19
+ """
20
+
21
+ ps_script = f"""
22
+ try {{
23
+ Get-NetIPAddress -InterfaceAlias "{interface_name}" -AddressFamily IPv4 |
24
+ Select-Object IPAddress,
25
+ @{{
26
+ Name = 'PrefixOrigin';
27
+ Expression = {{ [string]$_.PrefixOrigin }}
28
+ }} |
29
+ ConvertTo-Json -Depth 3
30
+ }} catch {{
31
+ # Return empty JSON array if nothing found / interface missing
32
+ '[]'
33
+ }}
34
+ """
35
+
36
+ try:
37
+ result = subprocess.run(
38
+ ["powershell", "-NoProfile", "-Command", ps_script],
39
+ capture_output=True,
40
+ text=True,
41
+ check=True
42
+ )
43
+ except subprocess.CalledProcessError as e:
44
+ # If anything unexpected happens, raise a clearer error
45
+ msg = (e.stderr or e.stdout or "").strip()
46
+ raise RuntimeError(f"PowerShell Get-NetIPAddress failed: {msg}") from e
47
+
48
+ stdout = result.stdout.strip()
49
+ if not stdout:
50
+ return []
51
+
52
+ # At this point stdout should be valid JSON (list or single object)
53
+ data = json.loads(stdout)
54
+
55
+ if isinstance(data, dict):
56
+ data = [data]
57
+
58
+ ips: List[str] = []
59
+ ip_type = ip_type.lower()
60
+
61
+ for entry in data:
62
+ ip = entry.get("IPAddress")
63
+ origin_raw = entry.get("PrefixOrigin", "")
64
+ origin = str(origin_raw).lower()
65
+
66
+ if not ip:
67
+ continue
68
+
69
+ if ip_type == "virtual":
70
+ if origin != "dhcp":
71
+ ips.append(ip)
72
+ elif ip_type == "dynamic":
73
+ if origin == "dhcp":
74
+ ips.append(ip)
75
+ elif ip_type == "all":
76
+ ips.append(ip)
77
+ else:
78
+ raise ValueError(f"Unsupported mode: {ip_type!r}")
79
+
80
+ return ips
@@ -74,3 +74,12 @@ def get_default_connection_name() -> Union[dict, None]:
74
74
  return {interface: details}
75
75
 
76
76
  return None
77
+
78
+
79
+ def list_network_interfaces() -> list:
80
+ """
81
+ Function to list all network interfaces.
82
+ :return: list of interface names.
83
+ """
84
+ iface_names = list(psutil.net_if_addrs().keys())
85
+ return iface_names
@@ -0,0 +1,174 @@
1
+ import win32evtlog
2
+ import win32security
3
+ import win32con
4
+
5
+
6
+ def get_latest_events(
7
+ server_ip: str = ".",
8
+ username: str = None,
9
+ password: str = None,
10
+ domain: str = ".",
11
+ log_name: str = "Security",
12
+ count: int = None,
13
+ event_id_list: list[int] | None = None
14
+ ):
15
+ """
16
+ Fetch latest `count` events from a Windows Event Log (local or remote) using pywin32.
17
+
18
+ - If username/password are None => use current security context.
19
+ - If server_ip is ".", "localhost", "127.0.0.1", "" or None => open local log.
20
+ - If count is None => return *all* events in the log.
21
+ - If event_id_list is not None => only return events whose EventID is in that list.
22
+
23
+ :param server_ip: IPv4/hostname of remote machine, or "." / None for local
24
+ :param username: Username to authenticate with (optional)
25
+ :param password: Password for the user (optional)
26
+ :param domain: Domain or computer name; ignored if username is None.
27
+ If None and username is given, "." is used.
28
+ :param log_name: Log name (e.g. "Security", "System", "Application")
29
+ :param count: Number of most recent events to return, or None for all
30
+ :param event_id_list: List of Event IDs (low 16-bit) to include, or None for all
31
+ :return: List of dicts describing events (most recent first)
32
+ """
33
+
34
+ # Normalize server for OpenEventLog: None means "local machine"
35
+ normalized_server = server_ip
36
+ if server_ip in (None, "", ".", "localhost", "127.0.0.1"):
37
+ normalized_server = None
38
+
39
+ # Max events logic: None => infinite
40
+ max_events = float("inf") if count is None else count
41
+
42
+ # Precompute set of event IDs for fast membership checks
43
+ event_ids_set = set(event_id_list) if event_id_list is not None else None
44
+
45
+ # Decide whether we need impersonation
46
+ use_impersonation = username is not None and password is not None
47
+
48
+ h_user = None
49
+ events = []
50
+
51
+ try:
52
+ if use_impersonation:
53
+ if domain is None:
54
+ domain = "."
55
+
56
+ # Log on with explicit credentials and impersonate for the remote call
57
+ # LOGON32_LOGON_NEW_CREDENTIALS lets us use these creds for remote access
58
+ # while keeping the local token mostly unchanged.
59
+ h_user = win32security.LogonUser(
60
+ username,
61
+ domain,
62
+ password,
63
+ win32con.LOGON32_LOGON_NEW_CREDENTIALS,
64
+ win32con.LOGON32_PROVIDER_WINNT50,
65
+ )
66
+
67
+ win32security.ImpersonateLoggedOnUser(h_user)
68
+
69
+ # Connect to remote event log
70
+ # `server_ip` can be an IP or hostname; no need for leading "\\".
71
+ # local if normalized_server is None.
72
+ h_log = win32evtlog.OpenEventLog(normalized_server, log_name)
73
+
74
+ flags = (
75
+ win32evtlog.EVENTLOG_BACKWARDS_READ
76
+ | win32evtlog.EVENTLOG_SEQUENTIAL_READ
77
+ )
78
+
79
+ offset = 0 # not used with BACKWARDS_READ + SEQUENTIAL_READ, but kept for clarity
80
+
81
+ while len(events) < max_events:
82
+ records = win32evtlog.ReadEventLog(h_log, flags, offset)
83
+ if not records:
84
+ break
85
+
86
+ for ev in records:
87
+ # Low 16 bits are the actual Event ID
88
+ eid = ev.EventID & 0xFFFF
89
+
90
+ # If filtering by event IDs, skip others
91
+ if event_ids_set is not None and eid not in event_ids_set:
92
+ continue
93
+
94
+ raw_strings = list(ev.StringInserts or [])
95
+ strings_dict = _parse_strings(eid, ev.SourceName, raw_strings)
96
+
97
+ evt = {
98
+ "RecordNumber": ev.RecordNumber,
99
+ "TimeGenerated": ev.TimeGenerated.Format(), # string time
100
+ "ComputerName": ev.ComputerName,
101
+ "SourceName": ev.SourceName,
102
+ # Low 16 bits are the actual Event ID
103
+ "EventID": ev.EventID & 0xFFFF,
104
+ "EventType": ev.EventType,
105
+ "EventCategory": ev.EventCategory,
106
+ "Strings": raw_strings,
107
+ "StringsDict": strings_dict,
108
+ }
109
+ events.append(evt)
110
+
111
+ if len(events) >= max_events:
112
+ break
113
+
114
+ win32evtlog.CloseEventLog(h_log)
115
+
116
+ finally:
117
+ # Clean up impersonation if we used it, Always revert impersonation and close handle
118
+ if use_impersonation and h_user is not None:
119
+ win32security.RevertToSelf()
120
+ h_user.Close()
121
+
122
+ # `events` is in newest to oldest already because of BACKWARDS_READ.
123
+ return events
124
+
125
+
126
+ def _parse_strings(event_id: int, source_name: str, strings: list[str]) -> dict:
127
+ """
128
+ Convert the raw 'Strings' list into a dictionary with friendly field names
129
+ for specific event IDs. For unknown events, fall back to String1, String2, ...
130
+
131
+ Currently has a special mapping for:
132
+ - 5156 (Security log, WFP allowed connection)
133
+ """
134
+ if not strings:
135
+ return {}
136
+
137
+ # Normalize source name a bit
138
+ src = (source_name or "").lower()
139
+
140
+ # Special-case: Security 5156 (Windows Filtering Platform has permitted a connection)
141
+ # Insertion strings (in order) are:
142
+ # 1 Process ID
143
+ # 2 Application Name
144
+ # 3 Direction
145
+ # 4 Source Address
146
+ # 5 Source Port
147
+ # 6 Destination Address
148
+ # 7 Destination Port
149
+ # 8 Protocol
150
+ # 9 Filter Run-Time ID
151
+ # 10 Layer Name
152
+ # 11 Layer Run-Time ID
153
+ if event_id == 5156 and "security-auditing" in src:
154
+ keys_5156 = [
155
+ "Process ID",
156
+ "Application Name",
157
+ "Direction",
158
+ "Source Address",
159
+ "Source Port",
160
+ "Destination Address",
161
+ "Destination Port",
162
+ "Protocol",
163
+ "Filter Run-Time ID",
164
+ "Layer Name",
165
+ "Layer Run-Time ID",
166
+ ]
167
+ return {
168
+ key: strings[i]
169
+ for i, key in enumerate(keys_5156)
170
+ if i < len(strings)
171
+ }
172
+
173
+ # Default: generic mapping
174
+ return {f"String{i+1}": s for i, s in enumerate(strings)}
@@ -1,12 +1,7 @@
1
- import subprocess
2
- import winreg
3
-
4
1
  from .. import subscribe
5
- from .....print_api import print_api
2
+ from .... import win_auditw
6
3
 
7
4
 
8
- AUDITING_REG_PATH: str = r"Software\Microsoft\Windows\CurrentVersion\Policies\System\Audit"
9
- PROCESS_CREATION_INCLUDE_CMDLINE_VALUE: str = "ProcessCreationIncludeCmdLine_Enabled"
10
5
  LOG_CHANNEL: str = 'Security'
11
6
  EVENT_ID: int = 4688
12
7
 
@@ -30,8 +25,8 @@ class ProcessCreateSubscriber(subscribe.EventLogSubscriber):
30
25
 
31
26
  def start(self):
32
27
  """Start the subscription process."""
33
- enable_audit_process_creation()
34
- enable_command_line_auditing()
28
+ win_auditw.enable_audit_process_creation()
29
+ win_auditw.enable_command_line_auditing()
35
30
 
36
31
  super().start()
37
32
 
@@ -60,100 +55,3 @@ class ProcessCreateSubscriber(subscribe.EventLogSubscriber):
60
55
  # print(f"Error looking up account SID: {e}")
61
56
 
62
57
  return data
63
-
64
-
65
- def enable_audit_process_creation(print_kwargs: dict = None):
66
- """
67
- Enable the 'Audit Process Creation' policy.
68
-
69
- :param print_kwargs: Optional keyword arguments for the print function.
70
- """
71
- if is_audit_process_creation_enabled():
72
- print_api("Audit Process Creation is already enabled.", color='blue', **(print_kwargs or {}))
73
- return
74
-
75
- # Enable "Audit Process Creation" policy
76
- audit_policy_command = [
77
- "auditpol", "/set", "/subcategory:Process Creation", "/success:enable", "/failure:enable"
78
- ]
79
- try:
80
- subprocess.run(audit_policy_command, check=True)
81
- print_api("Successfully enabled 'Audit Process Creation'.", color='green', **(print_kwargs or {}))
82
- except subprocess.CalledProcessError as e:
83
- print_api(f"Failed to enable 'Audit Process Creation': {e}", error_type=True, color='red', **(print_kwargs or {}))
84
- raise e
85
-
86
-
87
- def is_audit_process_creation_enabled(print_kwargs: dict = None) -> bool:
88
- """
89
- Check if the 'Audit Process Creation' policy is enabled.
90
-
91
- :param print_kwargs: Optional keyword arguments for the print function.
92
- """
93
- # Command to check the "Audit Process Creation" policy
94
- audit_policy_check_command = [
95
- "auditpol", "/get", "/subcategory:Process Creation"
96
- ]
97
- try:
98
- result = subprocess.run(audit_policy_check_command, check=True, capture_output=True, text=True)
99
- output = result.stdout
100
- # print_api(output) # Print the output for inspection
101
-
102
- if "Process Creation" in output and "Success and Failure" in output:
103
- # print_api(
104
- # "'Audit Process Creation' is enabled for both success and failure.",
105
- # color='green', **(print_kwargs or {}))
106
- return True
107
- else:
108
- # print_api(output, **(print_kwargs or {}))
109
- # print_api(
110
- # "'Audit Process Creation' is not fully enabled. Check the output above for details.",
111
- # color='yellow', **(print_kwargs or {}))
112
- return False
113
- except subprocess.CalledProcessError as e:
114
- print_api(f"Failed to check 'Audit Process Creation': {e}", color='red', error_type=True, **(print_kwargs or {}))
115
- return False
116
-
117
-
118
- def enable_command_line_auditing(print_kwargs: dict = None):
119
- """
120
- Enable the 'Include command line in process creation events' policy.
121
-
122
- :param print_kwargs: Optional keyword arguments for the print function.
123
- """
124
-
125
- if is_command_line_auditing_enabled():
126
- print_api(
127
- "[Include command line in process creation events] is already enabled.", color='blue',
128
- **(print_kwargs or {}))
129
- return
130
-
131
- try:
132
- # Open the registry key
133
- with winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, AUDITING_REG_PATH) as reg_key:
134
- # Set the value
135
- winreg.SetValueEx(reg_key, PROCESS_CREATION_INCLUDE_CMDLINE_VALUE, 0, winreg.REG_DWORD, 1)
136
-
137
- print_api(
138
- "Successfully enabled [Include command line in process creation events].",
139
- color='green', **(print_kwargs or {}))
140
- except WindowsError as e:
141
- print_api(
142
- f"Failed to enable [Include command line in process creation events]: {e}", error_type=True,
143
- color='red', **(print_kwargs or {}))
144
-
145
-
146
- def is_command_line_auditing_enabled():
147
- try:
148
- # Open the registry key
149
- with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, AUDITING_REG_PATH, 0, winreg.KEY_READ) as reg_key:
150
- # Query the value
151
- value, reg_type = winreg.QueryValueEx(reg_key, PROCESS_CREATION_INCLUDE_CMDLINE_VALUE)
152
- # Check if the value is 1 (enabled)
153
- return value == 1
154
- except FileNotFoundError:
155
- # Key or value not found, assume it's not enabled
156
- return False
157
- except WindowsError as e:
158
- print(f"Failed to read the 'Include command line in process creation events' setting: {e}")
159
- return False
@@ -1,7 +1,5 @@
1
- import subprocess
2
-
3
1
  from .. import subscribe
4
- from .....print_api import print_api
2
+ from .... import win_auditw
5
3
 
6
4
 
7
5
  LOG_CHANNEL: str = 'Security'
@@ -27,7 +25,7 @@ class ProcessTerminateSubscriber(subscribe.EventLogSubscriber):
27
25
 
28
26
  def start(self):
29
27
  """Start the subscription process."""
30
- enable_audit_process_termination()
28
+ win_auditw.enable_audit_process_termination()
31
29
 
32
30
  super().start()
33
31
 
@@ -48,56 +46,4 @@ class ProcessTerminateSubscriber(subscribe.EventLogSubscriber):
48
46
 
49
47
  data['ProcessIdInt'] = int(data['ProcessId'], 16)
50
48
 
51
- return data
52
-
53
-
54
- def enable_audit_process_termination(print_kwargs: dict = None):
55
- """
56
- Enable the 'Audit Process Termination' policy.
57
-
58
- :param print_kwargs: Optional keyword arguments for the print function.
59
- """
60
- if is_audit_process_termination_enabled():
61
- print_api("Audit Process Termination is already enabled.", color='blue', **(print_kwargs or {}))
62
- return
63
-
64
- audit_policy_command = [
65
- "auditpol", "/set", "/subcategory:Process Termination", "/success:enable", "/failure:enable"
66
- ]
67
- try:
68
- subprocess.run(audit_policy_command, check=True)
69
- print_api("Successfully enabled 'Audit Process Termination'.", color='green', **(print_kwargs or {}))
70
- except subprocess.CalledProcessError as e:
71
- print_api(f"Failed to enable 'Audit Process Termination': {e}", error_type=True, color='red', **(print_kwargs or {}))
72
- raise e
73
-
74
-
75
- def is_audit_process_termination_enabled(print_kwargs: dict = None) -> bool:
76
- """
77
- Check if the 'Audit Process Termination' policy is enabled.
78
-
79
- :param print_kwargs: Optional keyword arguments for the print function.
80
- """
81
- # Command to check the "Audit Process Creation" policy
82
- audit_policy_check_command = [
83
- "auditpol", "/get", "/subcategory:Process Termination"
84
- ]
85
- try:
86
- result = subprocess.run(audit_policy_check_command, check=True, capture_output=True, text=True)
87
- output = result.stdout
88
- # print_api(output) # Print the output for inspection
89
-
90
- if "Process Termination" in output and "Success and Failure" in output:
91
- # print_api(
92
- # "'Audit Process Termination' is enabled for both success and failure.",
93
- # color='green', **(print_kwargs or {}))
94
- return True
95
- else:
96
- # print_api(output, **(print_kwargs or {}))
97
- # print_api(
98
- # "'Audit Process Termination' is not fully enabled. Check the output above for details.",
99
- # color='yellow', **(print_kwargs or {}))
100
- return False
101
- except subprocess.CalledProcessError as e:
102
- print_api(f"Failed to check 'Audit Process Termination': {e}", color='red', error_type=True, **(print_kwargs or {}))
103
- return False
49
+ return data
@@ -6,7 +6,6 @@ from win32com.client import CDispatch
6
6
  import pywintypes
7
7
 
8
8
  from . import wmi_helpers, win32networkadapter
9
- from ...psutilw import psutil_networks
10
9
  from .... import ip_addresses
11
10
 
12
11
 
@@ -30,16 +29,13 @@ def get_network_configuration_by_adapter(
30
29
 
31
30
 
32
31
  def get_adapter_network_configuration(
33
- use_default_interface: bool = False,
34
- connection_name: str = None,
32
+ interface_name: str = None,
35
33
  mac_address: str = None,
36
34
  wmi_instance: CDispatch = None
37
35
  ) -> tuple:
38
36
  """
39
37
  Get the WMI network configuration for a network adapter.
40
- :param use_default_interface: bool, if True, the default network interface will be used.
41
- This is the adapter that your internet is being used from.
42
- :param connection_name: string, adapter name as shown in the network settings.
38
+ :param interface_name: string, adapter name as shown in the network settings.
43
39
  :param mac_address: string, MAC address of the adapter. Format: '00:00:00:00:00:00'.
44
40
  :param wmi_instance: WMI instance. You can get it from:
45
41
  wrappers.pywin32s.wmis.wmi_helpers.get_wmi_instance()
@@ -47,37 +43,25 @@ def get_adapter_network_configuration(
47
43
  :return: tuple(Win32_NetworkAdapterConfiguration, Win32_NetworkAdapter)
48
44
  """
49
45
 
50
- if use_default_interface and connection_name:
51
- raise ValueError("Only one of 'use_default_interface' or 'connection_name' must be provided.")
52
- elif not use_default_interface and not connection_name:
53
- raise ValueError("Either 'use_default_interface' or 'connection_name' must be provided.")
54
-
55
46
  if not wmi_instance:
56
47
  wmi_instance, _ = wmi_helpers.get_wmi_instance()
57
48
 
58
49
  adapters = win32networkadapter.list_network_adapters(wmi_instance)
59
50
 
51
+ if interface_name is None and mac_address is None:
52
+ raise ValueError("Either 'interface_name' or 'mac_address' must be provided.")
53
+ elif interface_name and mac_address:
54
+ raise ValueError("Only one of 'interface_name' or 'mac_address' must be provided.")
55
+
60
56
  current_adapter = None
61
- if use_default_interface:
62
- default_connection_name_dict: dict = psutil_networks.get_default_connection_name()
63
- if not default_connection_name_dict:
64
- raise wmi_helpers.WMINetworkAdapterNotFoundError("Default network adapter not found.")
65
- # Get the first key from the dictionary.
66
- connection_name: str = list(default_connection_name_dict.keys())[0]
67
-
68
- if connection_name is None and mac_address is None:
69
- raise ValueError("Either 'connection_name' or 'mac_address' must be provided.")
70
- elif connection_name and mac_address:
71
- raise ValueError("Only one of 'connection_name' or 'mac_address' must be provided.")
72
-
73
- if connection_name:
57
+ if interface_name:
74
58
  for adapter in adapters:
75
- if connection_name == adapter.NetConnectionID:
59
+ if interface_name == adapter.NetConnectionID:
76
60
  current_adapter = adapter
77
61
  break
78
62
 
79
63
  if not current_adapter:
80
- raise wmi_helpers.WMINetworkAdapterNotFoundError(f"Adapter with connection name '{connection_name}' not found.")
64
+ raise wmi_helpers.WMINetworkAdapterNotFoundError(f"Adapter with interface name '{interface_name}' not found.")
81
65
  elif mac_address:
82
66
  for adapter in adapters:
83
67
  if mac_address == adapter.MACAddress:
@@ -93,7 +77,7 @@ def get_adapter_network_configuration(
93
77
 
94
78
  # Check if the adapter exists
95
79
  if len(adapter_configs) == 0:
96
- raise wmi_helpers.WMINetworkAdapterNotFoundError(f"Adapter with connection name '{connection_name}' not found.")
80
+ raise wmi_helpers.WMINetworkAdapterNotFoundError(f"Adapter with interface name '{interface_name}' not found.")
97
81
 
98
82
  return adapter_configs[0], current_adapter
99
83
 
@@ -260,6 +244,7 @@ def get_info_from_network_config(
260
244
 
261
245
  ipv4s, ipv6s, ipv4subnets, ipv6prefixes = _split_ips(network_config)
262
246
  adapter = {
247
+ "caption": network_config.Caption,
263
248
  "description": network_config.Description,
264
249
  "interface_index": network_config.InterfaceIndex,
265
250
  "is_dynamic": bool(network_config.DHCPEnabled),
@@ -1,3 +1,4 @@
1
+ from logging import Logger
1
2
  from typing import Union
2
3
 
3
4
  from win32com.client import CDispatch
@@ -80,27 +81,32 @@ def get_default_network_adapter(wmi_instance: CDispatch = None):
80
81
 
81
82
  def set_dns_server(
82
83
  dns_servers: Union[list[str], None],
83
- use_default_interface: bool = False,
84
- connection_name: str = None,
85
- mac_address: str = None
84
+ interface_name: str = None,
85
+ mac_address: str = None,
86
+ verbose: bool = False,
87
+ logger: Logger = None
86
88
  ):
87
89
  """
88
90
  Set the DNS servers for a network adapter.
89
91
  :param dns_servers: list of strings, DNS server IPv4 addresses.
90
92
  None, if you want to remove the DNS servers and make the interface to obtain them automatically from DHCP.
91
93
  list[str], if you want to set the DNS servers manually to the list of strings.
92
- :param use_default_interface: bool, if True, the default network interface will be used.
93
- This is the adapter that your internet is being used from.
94
- :param connection_name: string, adapter name as shown in the network settings.
94
+ :param interface_name: string, network interface name as shown in the network settings.
95
95
  :param mac_address: string, MAC address of the adapter. Format: '00:00:00:00:00:00'.
96
+
97
+ :param verbose: bool, if True, print verbose output.
98
+ :param logger: Logger object, if provided, will log the output instead of printing.
96
99
  :return:
97
100
  """
98
101
 
99
102
  adapter_config, current_adapter = win32_networkadapterconfiguration.get_adapter_network_configuration(
100
- use_default_interface=use_default_interface, connection_name=connection_name, mac_address=mac_address)
103
+ interface_name=interface_name, mac_address=mac_address)
101
104
 
102
- print_api(f"Adapter [{current_adapter.Description}], Connection name [{current_adapter.NetConnectionID}]\n"
103
- f"Setting DNS servers to {dns_servers}", color='blue')
105
+ if verbose:
106
+ message = (
107
+ f"Adapter [{current_adapter.Description}], Connection name [{current_adapter.NetConnectionID}]\n"
108
+ f"Setting DNS servers to {dns_servers}")
109
+ print_api(message, color='blue', logger=logger)
104
110
 
105
111
  # Set DNS servers
106
112
  wmi_helpers.call_method(adapter_config, 'SetDNSServerSearchOrder', dns_servers)
@@ -3,7 +3,7 @@ import sys
3
3
 
4
4
  from cryptography import x509
5
5
 
6
- from . import creator, base, socket_client
6
+ from . import creator, socket_base, socket_client
7
7
  from .. import pyopensslw, cryptographyw
8
8
  from ..certauthw.certauthw import CertAuthWrapper
9
9
  from ...print_api import print_api
@@ -30,7 +30,9 @@ class Certificator:
30
30
  custom_private_key_path: str,
31
31
  forwarding_dns_service_ipv4_list___only_for_localhost: list,
32
32
  skip_extension_id_list: list,
33
- tls: bool
33
+ tls: bool,
34
+ enable_sslkeylogfile_env_to_client_ssl_context: bool,
35
+ sslkeylog_file_path: str
34
36
  ):
35
37
  self.ca_certificate_name = ca_certificate_name
36
38
  self.ca_certificate_filepath = ca_certificate_filepath
@@ -49,6 +51,9 @@ class Certificator:
49
51
  forwarding_dns_service_ipv4_list___only_for_localhost)
50
52
  self.skip_extension_id_list = skip_extension_id_list
51
53
  self.tls = tls
54
+ self.enable_sslkeylogfile_env_to_client_ssl_context: bool = (
55
+ enable_sslkeylogfile_env_to_client_ssl_context)
56
+ self.sslkeylog_file_path: str = sslkeylog_file_path
52
57
 
53
58
  # noinspection PyTypeChecker
54
59
  self.certauth_wrapper: CertAuthWrapper = None
@@ -146,13 +151,13 @@ class Certificator:
146
151
  self.sni_server_certificate_from_server_socket_download_directory + \
147
152
  os.sep + sni_received_parameters.destination_name + ".pem"
148
153
  # Get client ip.
149
- client_ip = base.get_source_address_from_socket(sni_received_parameters.ssl_socket)[0]
154
+ client_ip = socket_base.get_source_address_from_socket(sni_received_parameters.ssl_socket)[0]
150
155
 
151
156
  # If we're on localhost, then use external services list in order to resolve the domain:
152
- if client_ip in base.THIS_DEVICE_IP_LIST:
157
+ if client_ip in socket_base.THIS_DEVICE_IP_LIST:
153
158
  service_client = socket_client.SocketClient(
154
159
  service_name=sni_received_parameters.destination_name,
155
- service_port=base.get_destination_address_from_socket(sni_received_parameters.ssl_socket)[1],
160
+ service_port=socket_base.get_destination_address_from_socket(sni_received_parameters.ssl_socket)[1],
156
161
  tls=self.tls,
157
162
  dns_servers_list=self.forwarding_dns_service_ipv4_list___only_for_localhost,
158
163
  logger=print_kwargs.get('logger') if print_kwargs else None
@@ -161,7 +166,7 @@ class Certificator:
161
166
  else:
162
167
  service_client = socket_client.SocketClient(
163
168
  service_name=sni_received_parameters.destination_name,
164
- service_port=base.get_destination_address_from_socket(sni_received_parameters.ssl_socket)[1],
169
+ service_port=socket_base.get_destination_address_from_socket(sni_received_parameters.ssl_socket)[1],
165
170
  tls=self.tls,
166
171
  logger=print_kwargs.get('logger') if print_kwargs else None
167
172
  )
@@ -215,11 +220,16 @@ class Certificator:
215
220
  sni_received_parameters.destination_name, certificate_from_socket_x509)
216
221
 
217
222
  message = f"SNI Handler: port " \
218
- f"{base.get_destination_address_from_socket(sni_received_parameters.ssl_socket)[1]}: " \
223
+ f"{socket_base.get_destination_address_from_socket(sni_received_parameters.ssl_socket)[1]}: " \
219
224
  f"Using certificate: {sni_server_certificate_file_path}"
220
225
  print_api(message, **print_kwargs)
221
226
 
222
227
  # You need to build new context and exchange the context that being inherited from the main socket,
223
228
  # or else the context will receive previous certificate each time.
224
- sni_received_parameters.ssl_socket.context = \
225
- creator.create_server_ssl_context___load_certificate_and_key(sni_server_certificate_file_path, None)
229
+ sni_received_parameters.ssl_socket.context = (
230
+ creator.create_server_ssl_context___load_certificate_and_key(
231
+ certificate_file_path=sni_server_certificate_file_path, key_file_path=None,
232
+ enable_sslkeylogfile_env_to_client_ssl_context=self.enable_sslkeylogfile_env_to_client_ssl_context,
233
+ sslkeylog_file_path=self.sslkeylog_file_path
234
+ )
235
+ )