atomicshop 2.11.47__py3-none-any.whl → 3.10.5__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.
- atomicshop/__init__.py +1 -1
- atomicshop/{addons/mains → a_mains}/FACT/update_extract.py +3 -2
- atomicshop/a_mains/addons/process_list/compile.cmd +7 -0
- atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.dll +0 -0
- atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.exp +0 -0
- atomicshop/a_mains/addons/process_list/compiled/Win10x64/process_list.lib +0 -0
- atomicshop/{addons → a_mains/addons}/process_list/process_list.cpp +8 -1
- atomicshop/a_mains/dns_gateway_setting.py +11 -0
- atomicshop/a_mains/get_local_tcp_ports.py +85 -0
- atomicshop/a_mains/github_wrapper.py +11 -0
- atomicshop/a_mains/install_ca_certificate.py +172 -0
- atomicshop/{addons/mains → a_mains}/msi_unpacker.py +3 -1
- atomicshop/a_mains/process_from_port.py +119 -0
- atomicshop/a_mains/set_default_dns_gateway.py +90 -0
- atomicshop/a_mains/update_config_toml.py +38 -0
- atomicshop/appointment_management.py +5 -3
- atomicshop/basics/ansi_escape_codes.py +3 -1
- atomicshop/basics/argparse_template.py +2 -0
- atomicshop/basics/booleans.py +27 -30
- atomicshop/basics/bytes_arrays.py +43 -0
- atomicshop/basics/classes.py +149 -1
- atomicshop/basics/dicts.py +12 -0
- atomicshop/basics/enums.py +2 -2
- atomicshop/basics/exceptions.py +5 -1
- atomicshop/basics/list_of_classes.py +29 -0
- atomicshop/basics/list_of_dicts.py +69 -5
- atomicshop/basics/lists.py +14 -0
- atomicshop/basics/multiprocesses.py +374 -50
- atomicshop/basics/package_module.py +10 -0
- atomicshop/basics/strings.py +160 -7
- atomicshop/basics/threads.py +14 -0
- atomicshop/basics/tracebacks.py +13 -4
- atomicshop/certificates.py +153 -52
- atomicshop/config_init.py +12 -7
- atomicshop/console_user_response.py +7 -14
- atomicshop/consoles.py +9 -0
- atomicshop/datetimes.py +98 -0
- atomicshop/diff_check.py +340 -40
- atomicshop/dns.py +128 -12
- atomicshop/etws/_pywintrace_fix.py +17 -0
- atomicshop/etws/const.py +38 -0
- atomicshop/etws/providers.py +21 -0
- atomicshop/etws/sessions.py +43 -0
- atomicshop/etws/trace.py +168 -0
- atomicshop/etws/traces/trace_dns.py +162 -0
- atomicshop/etws/traces/trace_sysmon_process_creation.py +126 -0
- atomicshop/etws/traces/trace_tcp.py +130 -0
- atomicshop/file_io/csvs.py +222 -24
- atomicshop/file_io/docxs.py +35 -18
- atomicshop/file_io/file_io.py +35 -19
- atomicshop/file_io/jsons.py +49 -0
- atomicshop/file_io/tomls.py +139 -0
- atomicshop/filesystem.py +864 -293
- atomicshop/get_process_list.py +133 -0
- atomicshop/{process_name_cmd.py → get_process_name_cmd_dll.py} +52 -19
- atomicshop/http_parse.py +149 -93
- atomicshop/ip_addresses.py +6 -1
- atomicshop/mitm/centered_settings.py +132 -0
- atomicshop/mitm/config_static.py +207 -0
- atomicshop/mitm/config_toml_editor.py +55 -0
- atomicshop/mitm/connection_thread_worker.py +875 -357
- atomicshop/mitm/engines/__parent/parser___parent.py +4 -17
- atomicshop/mitm/engines/__parent/recorder___parent.py +108 -51
- atomicshop/mitm/engines/__parent/requester___parent.py +116 -0
- atomicshop/mitm/engines/__parent/responder___parent.py +75 -114
- atomicshop/mitm/engines/__reference_general/parser___reference_general.py +10 -7
- atomicshop/mitm/engines/__reference_general/recorder___reference_general.py +5 -5
- atomicshop/mitm/engines/__reference_general/requester___reference_general.py +47 -0
- atomicshop/mitm/engines/__reference_general/responder___reference_general.py +95 -13
- atomicshop/mitm/engines/create_module_template.py +58 -14
- atomicshop/mitm/import_config.py +359 -139
- atomicshop/mitm/initialize_engines.py +160 -74
- atomicshop/mitm/message.py +64 -23
- atomicshop/mitm/mitm_main.py +892 -0
- atomicshop/mitm/recs_files.py +183 -0
- atomicshop/mitm/shared_functions.py +4 -10
- atomicshop/mitm/ssh_tester.py +82 -0
- atomicshop/mitm/statistic_analyzer.py +257 -166
- atomicshop/mitm/statistic_analyzer_helper/analyzer_helper.py +136 -0
- atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py +525 -0
- atomicshop/monitor/change_monitor.py +96 -120
- atomicshop/monitor/checks/dns.py +139 -70
- atomicshop/monitor/checks/file.py +77 -0
- atomicshop/monitor/checks/network.py +81 -77
- atomicshop/monitor/checks/process_running.py +33 -34
- atomicshop/monitor/checks/url.py +94 -0
- atomicshop/networks.py +671 -0
- atomicshop/on_exit.py +205 -0
- atomicshop/package_mains_processor.py +84 -0
- atomicshop/permissions/permissions.py +22 -0
- atomicshop/permissions/ubuntu_permissions.py +239 -0
- atomicshop/permissions/win_permissions.py +33 -0
- atomicshop/print_api.py +24 -41
- atomicshop/process.py +63 -17
- atomicshop/process_poller/__init__.py +0 -0
- atomicshop/process_poller/pollers/__init__.py +0 -0
- atomicshop/process_poller/pollers/psutil_pywin32wmi_dll.py +95 -0
- atomicshop/process_poller/process_pool.py +207 -0
- atomicshop/process_poller/simple_process_pool.py +311 -0
- atomicshop/process_poller/tracer_base.py +45 -0
- atomicshop/process_poller/tracers/__init__.py +0 -0
- atomicshop/process_poller/tracers/event_log.py +46 -0
- atomicshop/process_poller/tracers/sysmon_etw.py +68 -0
- atomicshop/python_file_patcher.py +1 -1
- atomicshop/python_functions.py +27 -75
- atomicshop/question_answer_engine.py +2 -2
- atomicshop/scheduling.py +24 -5
- atomicshop/sound.py +4 -2
- atomicshop/speech_recognize.py +8 -0
- atomicshop/ssh_remote.py +158 -172
- atomicshop/startup/__init__.py +0 -0
- atomicshop/startup/win/__init__.py +0 -0
- atomicshop/startup/win/startup_folder.py +53 -0
- atomicshop/startup/win/task_scheduler.py +119 -0
- atomicshop/system_resource_monitor.py +61 -46
- atomicshop/system_resources.py +8 -8
- atomicshop/tempfiles.py +1 -2
- atomicshop/timer.py +30 -11
- atomicshop/urls.py +41 -0
- atomicshop/venvs.py +28 -0
- atomicshop/versioning.py +27 -0
- atomicshop/web.py +110 -25
- atomicshop/web_apis/__init__.py +0 -0
- atomicshop/web_apis/google_custom_search.py +44 -0
- atomicshop/web_apis/google_llm.py +188 -0
- atomicshop/websocket_parse.py +450 -0
- atomicshop/wrappers/certauthw/certauth.py +1 -0
- atomicshop/wrappers/cryptographyw.py +29 -8
- atomicshop/wrappers/ctyping/etw_winapi/__init__.py +0 -0
- atomicshop/wrappers/ctyping/etw_winapi/const.py +335 -0
- atomicshop/wrappers/ctyping/etw_winapi/etw_functions.py +393 -0
- atomicshop/wrappers/ctyping/file_details_winapi.py +67 -0
- atomicshop/wrappers/ctyping/msi_windows_installer/cabs.py +2 -1
- atomicshop/wrappers/ctyping/msi_windows_installer/extract_msi_main.py +13 -9
- atomicshop/wrappers/ctyping/msi_windows_installer/tables.py +35 -0
- atomicshop/wrappers/ctyping/setup_device.py +466 -0
- atomicshop/wrappers/ctyping/win_console.py +39 -0
- atomicshop/wrappers/dockerw/dockerw.py +113 -2
- atomicshop/wrappers/elasticsearchw/config_basic.py +0 -12
- atomicshop/wrappers/elasticsearchw/elastic_infra.py +75 -0
- atomicshop/wrappers/elasticsearchw/elasticsearchw.py +2 -20
- atomicshop/wrappers/factw/get_file_data.py +12 -5
- atomicshop/wrappers/factw/install/install_after_restart.py +89 -5
- atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py +20 -14
- atomicshop/wrappers/factw/postgresql/firmware.py +4 -6
- atomicshop/wrappers/githubw.py +583 -51
- atomicshop/wrappers/loggingw/consts.py +49 -0
- atomicshop/wrappers/loggingw/filters.py +102 -0
- atomicshop/wrappers/loggingw/formatters.py +58 -71
- atomicshop/wrappers/loggingw/handlers.py +459 -40
- atomicshop/wrappers/loggingw/loggers.py +19 -0
- atomicshop/wrappers/loggingw/loggingw.py +1010 -178
- atomicshop/wrappers/loggingw/reading.py +344 -19
- atomicshop/wrappers/mongodbw/__init__.py +0 -0
- atomicshop/wrappers/mongodbw/mongo_infra.py +31 -0
- atomicshop/wrappers/mongodbw/mongodbw.py +1432 -0
- atomicshop/wrappers/netshw.py +271 -0
- atomicshop/wrappers/playwrightw/engine.py +34 -19
- atomicshop/wrappers/playwrightw/infra.py +5 -0
- atomicshop/wrappers/playwrightw/javascript.py +7 -3
- atomicshop/wrappers/playwrightw/keyboard.py +14 -0
- atomicshop/wrappers/playwrightw/scenarios.py +172 -5
- atomicshop/wrappers/playwrightw/waits.py +9 -7
- atomicshop/wrappers/powershell_networking.py +80 -0
- atomicshop/wrappers/psutilw/processes.py +81 -0
- atomicshop/wrappers/psutilw/psutil_networks.py +85 -0
- atomicshop/wrappers/psutilw/psutilw.py +9 -0
- atomicshop/wrappers/pyopensslw.py +9 -2
- atomicshop/wrappers/pywin32w/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/cert_store.py +116 -0
- atomicshop/wrappers/pywin32w/console.py +34 -0
- atomicshop/wrappers/pywin32w/win_event_log/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/win_event_log/fetch.py +174 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribe.py +212 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_create.py +57 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/process_terminate.py +49 -0
- atomicshop/wrappers/pywin32w/win_event_log/subscribes/schannel_logging.py +97 -0
- atomicshop/wrappers/pywin32w/winshell.py +19 -0
- atomicshop/wrappers/pywin32w/wmis/__init__.py +0 -0
- atomicshop/wrappers/pywin32w/wmis/msft_netipaddress.py +113 -0
- atomicshop/wrappers/pywin32w/wmis/win32_networkadapterconfiguration.py +259 -0
- atomicshop/wrappers/pywin32w/wmis/win32networkadapter.py +112 -0
- atomicshop/wrappers/pywin32w/wmis/wmi_helpers.py +236 -0
- atomicshop/wrappers/socketw/accepter.py +21 -7
- atomicshop/wrappers/socketw/certificator.py +216 -150
- atomicshop/wrappers/socketw/creator.py +190 -50
- atomicshop/wrappers/socketw/dns_server.py +500 -173
- atomicshop/wrappers/socketw/exception_wrapper.py +45 -52
- atomicshop/wrappers/socketw/process_getter.py +86 -0
- atomicshop/wrappers/socketw/receiver.py +144 -102
- atomicshop/wrappers/socketw/sender.py +65 -35
- atomicshop/wrappers/socketw/sni.py +334 -165
- atomicshop/wrappers/socketw/socket_base.py +134 -0
- atomicshop/wrappers/socketw/socket_client.py +137 -95
- atomicshop/wrappers/socketw/socket_server_tester.py +14 -9
- atomicshop/wrappers/socketw/socket_wrapper.py +717 -116
- atomicshop/wrappers/socketw/ssl_base.py +15 -14
- atomicshop/wrappers/socketw/statistics_csv.py +148 -17
- atomicshop/wrappers/sysmonw.py +157 -0
- atomicshop/wrappers/ubuntu_terminal.py +65 -26
- atomicshop/wrappers/win_auditw.py +189 -0
- atomicshop/wrappers/winregw/__init__.py +0 -0
- atomicshop/wrappers/winregw/winreg_installed_software.py +58 -0
- atomicshop/wrappers/winregw/winreg_network.py +232 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/METADATA +31 -49
- atomicshop-3.10.5.dist-info/RECORD +306 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info}/WHEEL +1 -1
- atomicshop/_basics_temp.py +0 -101
- atomicshop/addons/a_setup_scripts/install_psycopg2_ubuntu.sh +0 -3
- atomicshop/addons/a_setup_scripts/install_pywintrace_0.3.cmd +0 -2
- atomicshop/addons/mains/install_docker_rootless_ubuntu.py +0 -11
- atomicshop/addons/mains/install_docker_ubuntu_main_sudo.py +0 -11
- atomicshop/addons/mains/install_elastic_search_and_kibana_ubuntu.py +0 -10
- atomicshop/addons/mains/install_wsl_ubuntu_lts_admin.py +0 -9
- atomicshop/addons/package_setup/CreateWheel.cmd +0 -7
- atomicshop/addons/package_setup/Setup in Edit mode.cmd +0 -6
- atomicshop/addons/package_setup/Setup.cmd +0 -7
- atomicshop/addons/process_list/compile.cmd +0 -2
- atomicshop/addons/process_list/compiled/Win10x64/process_list.dll +0 -0
- atomicshop/addons/process_list/compiled/Win10x64/process_list.exp +0 -0
- atomicshop/addons/process_list/compiled/Win10x64/process_list.lib +0 -0
- atomicshop/archiver/_search_in_zip.py +0 -189
- atomicshop/archiver/archiver.py +0 -34
- atomicshop/archiver/search_in_archive.py +0 -250
- atomicshop/archiver/sevenz_app_w.py +0 -86
- atomicshop/archiver/sevenzs.py +0 -44
- atomicshop/archiver/zips.py +0 -293
- atomicshop/etw/dns_trace.py +0 -118
- atomicshop/etw/etw.py +0 -61
- atomicshop/file_types.py +0 -24
- atomicshop/mitm/engines/create_module_template_example.py +0 -13
- atomicshop/mitm/initialize_mitm_server.py +0 -240
- atomicshop/monitor/checks/hash.py +0 -44
- atomicshop/monitor/checks/hash_checks/file.py +0 -55
- atomicshop/monitor/checks/hash_checks/url.py +0 -62
- atomicshop/pbtkmultifile_argparse.py +0 -88
- atomicshop/permissions.py +0 -110
- atomicshop/process_poller.py +0 -237
- atomicshop/script_as_string_processor.py +0 -38
- atomicshop/ssh_scripts/process_from_ipv4.py +0 -37
- atomicshop/ssh_scripts/process_from_port.py +0 -27
- atomicshop/wrappers/_process_wrapper_curl.py +0 -27
- atomicshop/wrappers/_process_wrapper_tar.py +0 -21
- atomicshop/wrappers/dockerw/install_docker.py +0 -209
- atomicshop/wrappers/elasticsearchw/infrastructure.py +0 -265
- atomicshop/wrappers/elasticsearchw/install_elastic.py +0 -232
- atomicshop/wrappers/ffmpegw.py +0 -125
- atomicshop/wrappers/loggingw/checks.py +0 -20
- atomicshop/wrappers/nodejsw/install_nodejs.py +0 -139
- atomicshop/wrappers/process_wrapper_pbtk.py +0 -16
- atomicshop/wrappers/socketw/base.py +0 -59
- atomicshop/wrappers/socketw/get_process.py +0 -107
- atomicshop/wrappers/wslw.py +0 -191
- atomicshop-2.11.47.dist-info/RECORD +0 -251
- /atomicshop/{addons/mains → a_mains}/FACT/factw_fact_extractor_docker_image_main_sudo.py +0 -0
- /atomicshop/{addons → a_mains/addons}/PlayWrightCodegen.cmd +0 -0
- /atomicshop/{addons → a_mains/addons}/ScriptExecution.cmd +0 -0
- /atomicshop/{addons/mains → a_mains/addons}/inits/init_to_import_all_modules.py +0 -0
- /atomicshop/{addons → a_mains/addons}/process_list/ReadMe.txt +0 -0
- /atomicshop/{addons/mains → a_mains}/search_for_hyperlinks_in_docx.py +0 -0
- /atomicshop/{archiver → etws}/__init__.py +0 -0
- /atomicshop/{etw → etws/traces}/__init__.py +0 -0
- /atomicshop/{monitor/checks/hash_checks → mitm/statistic_analyzer_helper}/__init__.py +0 -0
- /atomicshop/{wrappers/nodejsw → permissions}/__init__.py +0 -0
- /atomicshop/wrappers/pywin32w/{wmi_win32process.py → wmis/win32process.py} +0 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.dist-info/licenses}/LICENSE.txt +0 -0
- {atomicshop-2.11.47.dist-info → atomicshop-3.10.5.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
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
import psutil
|
|
5
|
+
|
|
6
|
+
from ...print_api import print_api
|
|
7
|
+
from ..ctyping import file_details_winapi
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def wait_for_process(pid: int):
|
|
11
|
+
"""
|
|
12
|
+
Wait for the process with the given PID to finish.
|
|
13
|
+
:param pid: int, PID of the process to wait for.
|
|
14
|
+
:return:
|
|
15
|
+
"""
|
|
16
|
+
try:
|
|
17
|
+
# Create a process object for the given PID
|
|
18
|
+
process = psutil.Process(pid)
|
|
19
|
+
|
|
20
|
+
# Wait for the process to terminate
|
|
21
|
+
while process.is_running():
|
|
22
|
+
print(f"Process with PID {pid} is still running...")
|
|
23
|
+
time.sleep(1) # Sleep for 1 second before checking again
|
|
24
|
+
|
|
25
|
+
# Refresh process status and get the exit code
|
|
26
|
+
process.wait()
|
|
27
|
+
print(f"Process with PID [{pid}] has finished.")
|
|
28
|
+
except psutil.NoSuchProcess:
|
|
29
|
+
print(f"No process found with PID {pid}")
|
|
30
|
+
except psutil.AccessDenied:
|
|
31
|
+
print(f"Access denied to process with PID {pid}")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def kill_process_by_pid(pid: int, print_kwargs: dict = None):
|
|
35
|
+
try:
|
|
36
|
+
print_api(f"Terminating process: {pid}.", **(print_kwargs or {}))
|
|
37
|
+
proc = psutil.Process(pid)
|
|
38
|
+
proc.terminate() # or proc.kill() if you want to forcefully kill it
|
|
39
|
+
proc.wait(timeout=5) # Wait up to 5 seconds for the process to terminate
|
|
40
|
+
except psutil.NoSuchProcess:
|
|
41
|
+
# print(f"No process found with PID {pid}.")
|
|
42
|
+
pass
|
|
43
|
+
except psutil.AccessDenied:
|
|
44
|
+
# print(f"Access denied to terminate process with PID {pid}.")
|
|
45
|
+
pass
|
|
46
|
+
except psutil.TimeoutExpired:
|
|
47
|
+
# print(f"Process {pid} did not terminate in time.")
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def get_running_processes_with_exe_info() -> list[dict]:
|
|
52
|
+
"""
|
|
53
|
+
Retrieve information about all running processes on the system.
|
|
54
|
+
"""
|
|
55
|
+
processes_info: list[dict] = []
|
|
56
|
+
|
|
57
|
+
for proc in psutil.process_iter(attrs=["pid", "name", "exe"]):
|
|
58
|
+
try:
|
|
59
|
+
pid = proc.info["pid"]
|
|
60
|
+
name = proc.info["name"]
|
|
61
|
+
exe = proc.info["exe"]
|
|
62
|
+
|
|
63
|
+
if exe and os.path.isfile(exe):
|
|
64
|
+
# Get file properties
|
|
65
|
+
file_properties = file_details_winapi.get_file_properties(exe)
|
|
66
|
+
|
|
67
|
+
# Add process info to the list
|
|
68
|
+
processes_info.append({
|
|
69
|
+
"PID": pid,
|
|
70
|
+
"Name": name,
|
|
71
|
+
"FilePath": exe,
|
|
72
|
+
"FileDescription": file_properties["FileDescription"],
|
|
73
|
+
"FileVersion": file_properties["FileVersion"],
|
|
74
|
+
"ProductName": file_properties["ProductName"],
|
|
75
|
+
"ProductVersion": file_properties["ProductVersion"],
|
|
76
|
+
})
|
|
77
|
+
except (psutil.AccessDenied, psutil.NoSuchProcess, psutil.ZombieProcess):
|
|
78
|
+
# Skip processes that cannot be accessed
|
|
79
|
+
continue
|
|
80
|
+
|
|
81
|
+
return processes_info
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
from typing import Union
|
|
2
|
+
import shlex
|
|
3
|
+
import socket
|
|
4
|
+
|
|
5
|
+
import psutil
|
|
6
|
+
|
|
7
|
+
from ... import networks
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_process_using_port(ip_port: str) -> Union[dict, None]:
|
|
11
|
+
"""
|
|
12
|
+
Function to find the process using the port.
|
|
13
|
+
:param ip_port: string, Listening IP and port number. Example: '192.168.0.1:443'
|
|
14
|
+
:return: dict['pid', 'name', 'cmdline'] or None.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
ip_address, port = ip_port.split(':')
|
|
18
|
+
port = int(port)
|
|
19
|
+
|
|
20
|
+
for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
|
|
21
|
+
try:
|
|
22
|
+
connections = proc.connections(kind='inet')
|
|
23
|
+
for conn in connections:
|
|
24
|
+
# if conn.laddr.port == port:
|
|
25
|
+
# Status LISTEN is for TCP sockets and NONE is for UDP sockets.
|
|
26
|
+
# Sometimes after socket close, the port will be in TIME_WAIT state.
|
|
27
|
+
if (conn.laddr.port == port and (conn.status == 'LISTEN' or conn.status == 'NONE')) and conn.laddr.ip == ip_address:
|
|
28
|
+
cmdline = proc.info['cmdline']
|
|
29
|
+
if not cmdline:
|
|
30
|
+
cmdline = '<EMPTY: TRY RUNNING AS ADMIN>'
|
|
31
|
+
else:
|
|
32
|
+
cmdline = shlex.join(cmdline)
|
|
33
|
+
return {
|
|
34
|
+
'pid': proc.info['pid'],
|
|
35
|
+
'name': proc.info['name'],
|
|
36
|
+
'cmdline': cmdline
|
|
37
|
+
}
|
|
38
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
|
39
|
+
pass
|
|
40
|
+
return None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def get_processes_using_port_list(ips_ports: list) -> Union[dict, None]:
|
|
44
|
+
"""
|
|
45
|
+
Function to find the process using the port.
|
|
46
|
+
:param ips_ports: List of listening ips and port numbers. Example:
|
|
47
|
+
['192.168.0.1:443', '192.168.0.2:443']
|
|
48
|
+
:return: dict[port: {'pid', 'name', 'cmdline'}] or None.
|
|
49
|
+
"""
|
|
50
|
+
port_process_map = {}
|
|
51
|
+
for ip_port in ips_ports:
|
|
52
|
+
process_info = get_process_using_port(ip_port)
|
|
53
|
+
if process_info:
|
|
54
|
+
port_process_map[ip_port] = process_info
|
|
55
|
+
|
|
56
|
+
return port_process_map
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def get_default_connection_name() -> Union[dict, None]:
|
|
60
|
+
"""
|
|
61
|
+
Function to get the default network interface.
|
|
62
|
+
:return: dict[interface_name: details] or None.
|
|
63
|
+
"""
|
|
64
|
+
# Get all interfaces.
|
|
65
|
+
interfaces: dict = psutil.net_if_addrs()
|
|
66
|
+
default_ip_address: str = networks.get_default_internet_ipv4()
|
|
67
|
+
|
|
68
|
+
for interface, details in interfaces.items():
|
|
69
|
+
for address in details:
|
|
70
|
+
# Check if the address is an IPv4 address (AF_INET) and not a loopback (127.0.0.1)
|
|
71
|
+
if address.family == socket.AF_INET and not address.address.startswith('127.'):
|
|
72
|
+
# Check if the address is the default IP address.
|
|
73
|
+
if address.address == default_ip_address:
|
|
74
|
+
return {interface: details}
|
|
75
|
+
|
|
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
|
|
@@ -164,6 +164,15 @@ def filter_processes_with_present_connections(processes) -> list:
|
|
|
164
164
|
|
|
165
165
|
|
|
166
166
|
class PsutilProcesses:
|
|
167
|
+
"""
|
|
168
|
+
Class to get all the current processes.
|
|
169
|
+
|
|
170
|
+
Example get current running processes as dicts as
|
|
171
|
+
{'<pid'>: {'name': '<process_name>', 'cmdline': '<process_cmdline>'}}:
|
|
172
|
+
from atomicshop.wrappers.psutilw import psutilw
|
|
173
|
+
processes = psutilw.PsutilProcesses().get_processes_as_dict(
|
|
174
|
+
attrs=['pid', 'name', 'cmdline'], cmdline_to_string=True)
|
|
175
|
+
"""
|
|
167
176
|
def __init__(self):
|
|
168
177
|
self.processes = None
|
|
169
178
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
from secrets import randbits
|
|
2
2
|
from OpenSSL import crypto
|
|
3
3
|
|
|
4
4
|
from .. import certificates
|
|
@@ -121,7 +121,14 @@ def generate_server_certificate_empty(
|
|
|
121
121
|
"""
|
|
122
122
|
|
|
123
123
|
cert = crypto.X509()
|
|
124
|
-
|
|
124
|
+
|
|
125
|
+
# RFC 5280: serial must be positive and non-zero
|
|
126
|
+
# 1 … 2⁶⁴-1
|
|
127
|
+
cert.set_serial_number(randbits(64))
|
|
128
|
+
current_serial = cert.get_serial_number()
|
|
129
|
+
if current_serial <= 0:
|
|
130
|
+
raise RuntimeError(f"Refusing to create a certificate with non-positive serial: {str(current_serial)}")
|
|
131
|
+
|
|
125
132
|
cert.get_subject().CN = certname
|
|
126
133
|
|
|
127
134
|
cert.set_version(2)
|
|
File without changes
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
import win32crypt as wcrypt
|
|
3
|
+
|
|
4
|
+
from ...print_api import print_api
|
|
5
|
+
from ... import certificates
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# lpszStoreProvider
|
|
9
|
+
CERT_STORE_PROV_SYSTEM = 0x0000000A
|
|
10
|
+
# dwFlags
|
|
11
|
+
CERT_SYSTEM_STORE_LOCAL_MACHINE = 0x00020000
|
|
12
|
+
CERT_SYSTEM_STORE_CURRENT_USER = 0x00010000
|
|
13
|
+
CERT_CLOSE_STORE_FORCE_FLAG = 0x00000001
|
|
14
|
+
CRYPT_STRING_BASE64HEADER = 0x00000000
|
|
15
|
+
X509_ASN_ENCODING = 0x00000001
|
|
16
|
+
CERT_STORE_ADD_REPLACE_EXISTING = 3
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
STORE_LOCATION_TO_CERT_SYSTEM_STORE: dict = {
|
|
20
|
+
"ROOT": CERT_SYSTEM_STORE_LOCAL_MACHINE,
|
|
21
|
+
"CA": CERT_SYSTEM_STORE_LOCAL_MACHINE,
|
|
22
|
+
"MY": CERT_SYSTEM_STORE_CURRENT_USER
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def delete_certificate_by_issuer_name(
|
|
27
|
+
issuer_name: str,
|
|
28
|
+
store_location: Literal[
|
|
29
|
+
"ROOT",
|
|
30
|
+
"CA",
|
|
31
|
+
"MY"] = "ROOT",
|
|
32
|
+
print_kwargs: dict = None
|
|
33
|
+
):
|
|
34
|
+
"""
|
|
35
|
+
NEED ADMIN RIGHTS.
|
|
36
|
+
The function will remove all certificates with the specified issuer name.
|
|
37
|
+
There can be several certificates with this name.
|
|
38
|
+
|
|
39
|
+
:param issuer_name: string, issuer name to search for.
|
|
40
|
+
:param store_location: string, store location to search in. Default is "ROOT".
|
|
41
|
+
:param print_kwargs: dict, print_api kwargs.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
"""
|
|
45
|
+
WinAPI doesn't like to do 2 actions in one iteration. So, first we will collect all certificates to remove,
|
|
46
|
+
and in the second iteration remove them.
|
|
47
|
+
|
|
48
|
+
Full Explanation:
|
|
49
|
+
When you iterate with for cert in store.CertEnumCertificatesInStore(): and call
|
|
50
|
+
cert.CertDeleteCertificateFromStore() inside that loop, you’re modifying the underlying certificate store
|
|
51
|
+
while its internal enumeration is still active. This can lead to a segmentation fault (access violation 0xC0000005).
|
|
52
|
+
By collecting the certificates in the first pass, you freeze the iteration so the store
|
|
53
|
+
doesn’t get mutated mid-enumeration.
|
|
54
|
+
In the second pass, when you actually remove them, you’re no longer in the middle of enumerating.
|
|
55
|
+
This prevents the store’s pointer from becoming invalid.
|
|
56
|
+
|
|
57
|
+
This approach should stop the Process finished with exit code -1073741819 (0xC0000005) issue.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
store = wcrypt.CertOpenStore(
|
|
61
|
+
CERT_STORE_PROV_SYSTEM,
|
|
62
|
+
0,
|
|
63
|
+
None,
|
|
64
|
+
STORE_LOCATION_TO_CERT_SYSTEM_STORE[store_location],
|
|
65
|
+
store_location
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# Collect all matching certificates in a list
|
|
69
|
+
certs_to_remove = []
|
|
70
|
+
for cert in store.CertEnumCertificatesInStore():
|
|
71
|
+
# Certificate properties.
|
|
72
|
+
# cert.CertEnumCertificateContextProperties()
|
|
73
|
+
subject_string: str = wcrypt.CertNameToStr(cert.Subject)
|
|
74
|
+
if subject_string == issuer_name:
|
|
75
|
+
# Remove the certificate.
|
|
76
|
+
certs_to_remove.append(cert)
|
|
77
|
+
|
|
78
|
+
# Remove all certificates from the list.
|
|
79
|
+
for cert in certs_to_remove:
|
|
80
|
+
cert.CertDeleteCertificateFromStore()
|
|
81
|
+
print_api(f"Removed the Certificate from store [{store_location}] with issuer [{issuer_name}]", **(print_kwargs or {}))
|
|
82
|
+
|
|
83
|
+
# There is an exception about store close.
|
|
84
|
+
# store.CertCloseStore()
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def install_certificate_file(
|
|
88
|
+
file_path: str,
|
|
89
|
+
store_location: Literal[
|
|
90
|
+
"ROOT", "CA", "MY"] = "ROOT",
|
|
91
|
+
print_kwargs: dict = None
|
|
92
|
+
):
|
|
93
|
+
"""
|
|
94
|
+
NEED ADMIN RIGHTS.
|
|
95
|
+
The function will install the certificate from the file to the specified store location.
|
|
96
|
+
|
|
97
|
+
:param file_path: string, full file path to the certificate file.
|
|
98
|
+
:param store_location: string, store location to install the certificate. Default is "ROOT".
|
|
99
|
+
:param print_kwargs: dict, print_api kwargs.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
with open(file_path, 'r') as f:
|
|
103
|
+
certificate_string = f.read()
|
|
104
|
+
|
|
105
|
+
certificate_pem = certificates.get_pem_certificate_from_string(certificate_string)
|
|
106
|
+
|
|
107
|
+
certificate_bytes = wcrypt.CryptStringToBinary(certificate_pem, CRYPT_STRING_BASE64HEADER)[0]
|
|
108
|
+
|
|
109
|
+
store = wcrypt.CertOpenStore(
|
|
110
|
+
CERT_STORE_PROV_SYSTEM, 0, None, STORE_LOCATION_TO_CERT_SYSTEM_STORE[store_location], store_location)
|
|
111
|
+
|
|
112
|
+
store.CertAddEncodedCertificateToStore(X509_ASN_ENCODING, certificate_bytes, CERT_STORE_ADD_REPLACE_EXISTING)
|
|
113
|
+
store.CertCloseStore(CERT_CLOSE_STORE_FORCE_FLAG)
|
|
114
|
+
|
|
115
|
+
message = f"Certificate installed to the store: [{store_location}] from file: [{file_path}]"
|
|
116
|
+
print_api(message, **(print_kwargs or {}))
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import win32api
|
|
2
|
+
import win32con
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ConsoleHandler:
|
|
6
|
+
"""
|
|
7
|
+
This class is used to handle console events.
|
|
8
|
+
Currently used to handle the 'CTRL_CLOSE_EVENT' event - Meaning what to do when the user closes the console by
|
|
9
|
+
clicking on X in the top right corner.
|
|
10
|
+
"""
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
cleanup_action: callable = None,
|
|
14
|
+
args: tuple = None,
|
|
15
|
+
kwargs: dict = None
|
|
16
|
+
):
|
|
17
|
+
"""
|
|
18
|
+
:param cleanup_action: The action to run when user closes the console.
|
|
19
|
+
:param args: The arguments to pass to the cleanup action.
|
|
20
|
+
:param kwargs: The keyword arguments to pass to the cleanup action.
|
|
21
|
+
"""
|
|
22
|
+
self.cleanup_action = cleanup_action
|
|
23
|
+
self.args = args
|
|
24
|
+
self.kwargs = kwargs
|
|
25
|
+
|
|
26
|
+
def _console_handler(self, event):
|
|
27
|
+
if event == win32con.CTRL_CLOSE_EVENT:
|
|
28
|
+
if self.cleanup_action and callable(self.cleanup_action):
|
|
29
|
+
self.cleanup_action(*self.args, **self.kwargs)
|
|
30
|
+
return True
|
|
31
|
+
return False
|
|
32
|
+
|
|
33
|
+
def register_handler(self):
|
|
34
|
+
win32api.SetConsoleCtrlHandler(self._console_handler, True)
|
|
File without changes
|
|
@@ -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)}
|