From 53e44d3310506368cde9e22546d88c10f8fe49e6 Mon Sep 17 00:00:00 2001 From: fariss Date: Wed, 18 Dec 2024 14:24:36 +0100 Subject: [PATCH] vm.common: add -iconLocation param to VM-Install-From-Zip function --- .../capa-explorer-web.vm.nuspec | 2 +- .../tools/chocolateyinstall.ps1 | 3 +- packages/common.vm/common.vm.nuspec | 2 +- .../common.vm/tools/vm.common/vm.common.psm1 | 11 +- .../event-log-explorer.vm.nuspec | 2 +- .../tools/chocolateyinstall.ps1 | 2 +- packages/fakenet-ng.vm/fakenet-ng.vm.nuspec | 2 +- packages/fakenet-ng.vm/tools/default.ini | 6 +- .../ida.plugin.capa.vm.nuspec | 2 +- .../tools/chocolateyinstall.ps1 | 13 +- .../tools/chocolateyuninstall.ps1 | 4 +- .../ida.plugin.xrefer.vm.nuspec | 14 ++ .../tools/chocolateyinstall.ps1 | 6 + .../tools/chocolateyuninstall.ps1 | 5 + .../internet_detector.vm.nuspec | 4 +- .../tools/chocolateyinstall.ps1 | 11 +- .../tools/internet_detector.pyw | 148 +++++++++++++----- .../libraries-extra.python3.vm.nuspec | 13 -- .../libraries.python3.vm.nuspec | 2 +- .../libraries.python3.vm/tools/modules.xml | 1 + packages/regcool.vm/regcool.vm.nuspec | 2 +- .../regcool.vm/tools/chocolateyinstall.ps1 | 2 +- packages/vcredist140.vm/vcredist140.vm.nuspec | 4 +- scripts/test/lint.py | 2 +- 24 files changed, 179 insertions(+), 84 deletions(-) create mode 100644 packages/ida.plugin.xrefer.vm/ida.plugin.xrefer.vm.nuspec rename packages/{libraries-extra.python3.vm => ida.plugin.xrefer.vm}/tools/chocolateyinstall.ps1 (51%) create mode 100644 packages/ida.plugin.xrefer.vm/tools/chocolateyuninstall.ps1 delete mode 100644 packages/libraries-extra.python3.vm/libraries-extra.python3.vm.nuspec diff --git a/packages/capa-explorer-web.vm/capa-explorer-web.vm.nuspec b/packages/capa-explorer-web.vm/capa-explorer-web.vm.nuspec index 272096ffe..6ad7f026b 100644 --- a/packages/capa-explorer-web.vm/capa-explorer-web.vm.nuspec +++ b/packages/capa-explorer-web.vm/capa-explorer-web.vm.nuspec @@ -2,7 +2,7 @@ capa-explorer-web.vm - 1.0.0 + 1.0.0.20241218 Soufiane Fariss Web interface for exploring and understanding capa results diff --git a/packages/capa-explorer-web.vm/tools/chocolateyinstall.ps1 b/packages/capa-explorer-web.vm/tools/chocolateyinstall.ps1 index c8ed31c8c..51ca1d90d 100644 --- a/packages/capa-explorer-web.vm/tools/chocolateyinstall.ps1 +++ b/packages/capa-explorer-web.vm/tools/chocolateyinstall.ps1 @@ -7,4 +7,5 @@ $zipUrl = 'https://github.com/mandiant/capa/raw/refs/heads/master/web/explorer/r $zipSha256 = '3a7cf6927b0e8595f08b685669b215ef779eade622efd5e8d33efefadd849025' $executableName = "index.html" -VM-Install-From-Zip $toolName $category $zipUrl $zipSha256 -executableName $executableName -withoutBinFile -innerFolder $true +$iconName = "favicon.ico" +VM-Install-From-Zip $toolName $category $zipUrl $zipSha256 -executableName $executableName -iconLocation $iconName -withoutBinFile -innerFolder $true diff --git a/packages/common.vm/common.vm.nuspec b/packages/common.vm/common.vm.nuspec index 1f8934e6b..9b5de88e3 100755 --- a/packages/common.vm/common.vm.nuspec +++ b/packages/common.vm/common.vm.nuspec @@ -2,7 +2,7 @@ common.vm - 0.0.0.20241209 + 0.0.0.20241218 Common libraries for VM-packages Mandiant diff --git a/packages/common.vm/tools/vm.common/vm.common.psm1 b/packages/common.vm/tools/vm.common/vm.common.psm1 index 9f8325a5f..338cb0bc9 100755 --- a/packages/common.vm/tools/vm.common/vm.common.psm1 +++ b/packages/common.vm/tools/vm.common/vm.common.psm1 @@ -402,7 +402,9 @@ function VM-Install-From-Zip { # $powershellCommand = "Get-Content README.md" # $powershellCommand = "Import-Module module.ps1; Get-Help Main-Function" [Parameter(Mandatory=$false)] - [string] $powershellCommand + [string] $powershellCommand, + [Parameter(Mandatory=$false)] + [string] $iconLocation ) try { $toolDir = Join-Path ${Env:RAW_TOOLS_DIR} $toolName @@ -432,7 +434,7 @@ function VM-Install-From-Zip { if ($powershellCommand) { $executablePath = $toolDir - VM-Install-Shortcut -toolName $toolName -category $category -arguments $powershellCommand -executableDir $executablePath -powershell + VM-Install-Shortcut -toolName $toolName -category $category -arguments $powershellCommand -executableDir $executablePath -powershell -iconLocation $iconLocation } elseif ($withoutBinFile) { # Used when tool does not have an associated executable if (-Not $executableName) { # Tool is located in $toolDir (c3.vm for example) @@ -440,12 +442,12 @@ function VM-Install-From-Zip { } else { # Tool is in a specific directory (pma-labs.vm for example) $executablePath = Join-Path $toolDir $executableName -Resolve } - VM-Install-Shortcut -toolName $toolName -category $category -executablePath $executablePath + VM-Install-Shortcut -toolName $toolName -category $category -executablePath $executablePath -iconLocation $iconLocation } else { if (-Not $executableName) { $executableName = "$toolName.exe" } $executablePath = Join-Path $toolDir $executableName -Resolve - VM-Install-Shortcut -toolName $toolName -category $category -executablePath $executablePath -consoleApp $consoleApp -arguments $arguments + VM-Install-Shortcut -toolName $toolName -category $category -executablePath $executablePath -consoleApp $consoleApp -arguments $arguments -iconLocation $iconLocation Install-BinFile -Name $toolName -Path $executablePath } return ,@($toolDir, $executablePath) @@ -1828,6 +1830,7 @@ function VM-Create-Ico { # Delete extracted ZIPS after unzipping them. # Useful to extract zipped labs downloaded from GDrive keeping the folder structure. function VM-Unzip-Recursively { + $ErrorActionPreference = 'Continue' $desktop = Join-Path ${Env:UserProfile} "Desktop" $zip = Get-Item "$desktop\drive-download*.zip" if (-Not (Test-Path $zip)) { diff --git a/packages/event-log-explorer.vm/event-log-explorer.vm.nuspec b/packages/event-log-explorer.vm/event-log-explorer.vm.nuspec index 39510b9a8..196302e74 100644 --- a/packages/event-log-explorer.vm/event-log-explorer.vm.nuspec +++ b/packages/event-log-explorer.vm/event-log-explorer.vm.nuspec @@ -2,7 +2,7 @@ event-log-explorer.vm - 5.5.2.20240908 + 5.6.0.20241212 FSPro Labs Software solution for viewing, analyzing and monitoring events recorded in Microsoft Windows event logs. diff --git a/packages/event-log-explorer.vm/tools/chocolateyinstall.ps1 b/packages/event-log-explorer.vm/tools/chocolateyinstall.ps1 index e60a52320..aa2500df3 100644 --- a/packages/event-log-explorer.vm/tools/chocolateyinstall.ps1 +++ b/packages/event-log-explorer.vm/tools/chocolateyinstall.ps1 @@ -5,7 +5,7 @@ $toolName = 'Event Log Explorer' $category = 'Forensic' $exeUrl = 'https://eventlogxp.com/download/elex_setup.exe' -$exeSha256 = '8dc2c9d4a620bf421dac9c9bce2ab690798005edbf5d7ccb202717a14f8cc894' +$exeSha256 = '5049c96130396f407197a74fa571f10e4106bd0c13858e717fc11c535fded678' $toolDir = Join-Path ${Env:ProgramFiles(x86)} $toolName $executablePath = Join-Path $toolDir "elex.exe" diff --git a/packages/fakenet-ng.vm/fakenet-ng.vm.nuspec b/packages/fakenet-ng.vm/fakenet-ng.vm.nuspec index e054ed8b7..dacce7012 100755 --- a/packages/fakenet-ng.vm/fakenet-ng.vm.nuspec +++ b/packages/fakenet-ng.vm/fakenet-ng.vm.nuspec @@ -2,7 +2,7 @@ fakenet-ng.vm - 3.3 + 3.3.0.20241124 FakeNet-NG is a dynamic network analysis tool. Mandiant diff --git a/packages/fakenet-ng.vm/tools/default.ini b/packages/fakenet-ng.vm/tools/default.ini index ec6c82a10..59ba9e134 100644 --- a/packages/fakenet-ng.vm/tools/default.ini +++ b/packages/fakenet-ng.vm/tools/default.ini @@ -114,7 +114,7 @@ DefaultUDPListener: ProxyUDPListener # NOTE: This setting is only honored when 'RedirectAllTraffic' is enabled. BlackListPortsTCP: 139 -BlackListPortsUDP: 67, 68, 137, 138, 443, 1900, 5355, 53 +BlackListPortsUDP: 67, 68, 137, 138, 443, 1900, 5355 # Specify processes to ignore when diverting traffic. Windows example used # here. @@ -275,6 +275,7 @@ Listener: HTTPListener UseSSL: No Webroot: defaultFiles/ Timeout: 10 +#ProcessBlackList: dmclient.exe, OneDrive.exe, svchost.exe, backgroundTaskHost.exe, GoogleUpdate.exe, chrome.exe DumpHTTPPosts: Yes DumpHTTPPostsFilePrefix: http Hidden: False @@ -345,5 +346,4 @@ Port: 110 Protocol: TCP Listener: POPListener UseSSL: No -Hidden: False - +Hidden: False \ No newline at end of file diff --git a/packages/ida.plugin.capa.vm/ida.plugin.capa.vm.nuspec b/packages/ida.plugin.capa.vm/ida.plugin.capa.vm.nuspec index 09e6732af..018d2dd0e 100755 --- a/packages/ida.plugin.capa.vm/ida.plugin.capa.vm.nuspec +++ b/packages/ida.plugin.capa.vm/ida.plugin.capa.vm.nuspec @@ -2,7 +2,7 @@ ida.plugin.capa.vm - 7.0.1.20240425 + 8.0.1 capa explorer is an IDAPython plugin that integrates capa with IDA Pro. @mike-hunhoff, @williballenthin, @mr-tz diff --git a/packages/ida.plugin.capa.vm/tools/chocolateyinstall.ps1 b/packages/ida.plugin.capa.vm/tools/chocolateyinstall.ps1 index da3cf92e5..072c5d0e4 100755 --- a/packages/ida.plugin.capa.vm/tools/chocolateyinstall.ps1 +++ b/packages/ida.plugin.capa.vm/tools/chocolateyinstall.ps1 @@ -3,19 +3,20 @@ Import-Module vm.common -Force -DisableNameChecking try { # Install dependency: capa Python library - VM-Pip-Install "flare-capa" + $version = "8.0.1" + VM-Pip-Install "flare-capa==$version" # Install plugin $pluginName = "capa_explorer.py" - $pluginUrl = "https://raw.githubusercontent.com/mandiant/capa/v7.0.1/capa/ida/plugin/capa_explorer.py" - $pluginSha256 = "a9a60d9066c170c4e18366eb442f215009433bcfe277d3c6d0c4c9860824a7d3" + $pluginUrl = "https://raw.githubusercontent.com/mandiant/capa/v$version/capa/ida/plugin/capa_explorer.py" + $pluginSha256 = "bf6c9a0e5fd2c75a93bb3c19e0221c36cda441c878af3c23ea3aafef4fecf3e9" VM-Install-IDA-Plugin -pluginName $pluginName -pluginUrl $pluginUrl -pluginSha256 $pluginSha256 # Download capa rules $pluginsDir = VM-Get-IDA-Plugins-Dir - $rulesUrl = "https://github.com/mandiant/capa-rules/archive/refs/tags/v7.0.1.zip" - $rulesSha256 = "f4ed60bcf342007935215ea76175dddfbcbfb3f97d95387543858e0c1ecf8bcd" + $rulesUrl = "https://github.com/mandiant/capa-rules/archive/refs/tags/v$version.zip" + $rulesSha256 = "7c5f932b1da4e18eed50add117e7fc55c14dc51487495cb31e33e0b44c522fbc" $packageArgs = @{ packageName = ${Env:ChocolateyPackageName} unzipLocation = $pluginsDir @@ -24,7 +25,7 @@ try { checksumType = 'sha256' } Install-ChocolateyZipPackage @packageArgs - $rulesDir = Join-Path $pluginsDir "capa-rules-7.0.1" -Resolve + $rulesDir = Join-Path $pluginsDir "capa-rules-$version" -Resolve # Set capa rules in the capa plugin $registryPath = 'HKCU:\SOFTWARE\IDAPython\IDA-Settings\capa' diff --git a/packages/ida.plugin.capa.vm/tools/chocolateyuninstall.ps1 b/packages/ida.plugin.capa.vm/tools/chocolateyuninstall.ps1 index 88ca6b57e..dd2dc3590 100755 --- a/packages/ida.plugin.capa.vm/tools/chocolateyuninstall.ps1 +++ b/packages/ida.plugin.capa.vm/tools/chocolateyuninstall.ps1 @@ -8,8 +8,8 @@ $pluginPath = Join-Path $pluginsDir "capa_explorer.py" Remove-Item $pluginPath # Delete capa rules -$rulesDir = Join-Path $pluginsDir "capa-rules-6.1.0" -Remove-Item $rulesDir +$rulesDir = Get-ChildItem "$pluginsDir\capa-rules-*" +Remove-Item $rulesDir -Recurse # Delete registry information Remove-Item 'HKCU:\SOFTWARE\IDAPython\IDA-Settings\capa' diff --git a/packages/ida.plugin.xrefer.vm/ida.plugin.xrefer.vm.nuspec b/packages/ida.plugin.xrefer.vm/ida.plugin.xrefer.vm.nuspec new file mode 100644 index 000000000..4f48a0516 --- /dev/null +++ b/packages/ida.plugin.xrefer.vm/ida.plugin.xrefer.vm.nuspec @@ -0,0 +1,14 @@ + + + + ida.plugin.xrefer.vm + 1.0.0 + Custom navigation interface within IDA. + Muhammad Umair + + + + + + + diff --git a/packages/libraries-extra.python3.vm/tools/chocolateyinstall.ps1 b/packages/ida.plugin.xrefer.vm/tools/chocolateyinstall.ps1 similarity index 51% rename from packages/libraries-extra.python3.vm/tools/chocolateyinstall.ps1 rename to packages/ida.plugin.xrefer.vm/tools/chocolateyinstall.ps1 index 21698fdb7..9a44aedc0 100644 --- a/packages/libraries-extra.python3.vm/tools/chocolateyinstall.ps1 +++ b/packages/ida.plugin.xrefer.vm/tools/chocolateyinstall.ps1 @@ -4,6 +4,12 @@ Import-Module vm.common -Force -DisableNameChecking try { $dependencies = "asciinet,bs4,flare_capa,langchain,langchain_google_genai,langchain_openai,networkx,python-statemachine,requests,tabulate,tenacity" VM-Pip-Install $dependencies + + $pluginName = 'xrefer.py' + $pluginUrl = 'https://github.com/mandiant/xrefer/archive/refs/tags/v1.0.0.zip' + $pluginSha256 = '8c1b5cee59674e104e0bac20f908e9b3cf17af25b18b3ed80a845b62b257e7f1' + + VM-Install-IDA-Plugin -pluginName $pluginName -pluginUrl $pluginUrl -pluginSha256 $pluginSha256 } catch { VM-Write-Log-Exception $_ } diff --git a/packages/ida.plugin.xrefer.vm/tools/chocolateyuninstall.ps1 b/packages/ida.plugin.xrefer.vm/tools/chocolateyuninstall.ps1 new file mode 100644 index 000000000..e509e5880 --- /dev/null +++ b/packages/ida.plugin.xrefer.vm/tools/chocolateyuninstall.ps1 @@ -0,0 +1,5 @@ +$ErrorActionPreference = 'Continue' +Import-Module vm.common -Force -DisableNameChecking + +$pluginName = 'xrefer.py' +VM-Uninstall-IDA-Plugin -pluginName $pluginName diff --git a/packages/internet_detector.vm/internet_detector.vm.nuspec b/packages/internet_detector.vm/internet_detector.vm.nuspec index 05c975724..6dfbbf8b8 100644 --- a/packages/internet_detector.vm/internet_detector.vm.nuspec +++ b/packages/internet_detector.vm/internet_detector.vm.nuspec @@ -2,13 +2,13 @@ internet_detector.vm - 1.0.0.20241112 + 1.0.0.20241217 Elliot Chernofsky and Ana Martinez Gomez Tool that changes the background and a taskbar icon if it detects internet connectivity - + diff --git a/packages/internet_detector.vm/tools/chocolateyinstall.ps1 b/packages/internet_detector.vm/tools/chocolateyinstall.ps1 index 5169f9ef0..13f3835cd 100644 --- a/packages/internet_detector.vm/tools/chocolateyinstall.ps1 +++ b/packages/internet_detector.vm/tools/chocolateyinstall.ps1 @@ -21,10 +21,9 @@ Start-Process -FilePath 'cmd.exe' -WorkingDirectory $toolDir -ArgumentList "/c p $imagesPath = Join-Path $packageToolDir "images" Copy-Item "$imagesPath\*" ${Env:VM_COMMON_DIR} -Force -VM-Install-Shortcut -toolName $toolName -category $category -executablePath "$toolDir/$toolName.exe" +VM-Install-Shortcut -toolName $toolName -category $category -executablePath "$toolDir\$toolName.exe" -# TODO - Uncomment when FakeNet BlackList for DNS is fixed/addressed. https://github.com/mandiant/flare-fakenet-ng/issues/190 -# # Create scheduled task for tool to run every 2 minutes. -# $action = New-ScheduledTaskAction -Execute $rawToolPath -# $trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 2) -# Register-ScheduledTask -Action $action -Trigger $trigger -TaskName 'Internet Detector' -Force +# Create scheduled task for tool to run every 2 minutes. +$action = New-ScheduledTaskAction -Execute "$toolDir\$toolName.exe" +$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 1) +Register-ScheduledTask -Action $action -Trigger $trigger -TaskName 'Internet Detector' -Force \ No newline at end of file diff --git a/packages/internet_detector.vm/tools/internet_detector.pyw b/packages/internet_detector.vm/tools/internet_detector.pyw index 3b22c25ed..c21733bf8 100644 --- a/packages/internet_detector.vm/tools/internet_detector.pyw +++ b/packages/internet_detector.vm/tools/internet_detector.pyw @@ -12,20 +12,22 @@ VERSION = "1.0.0" TOOL_NAME = "internet_detector" -import threading -import requests +import win32event import win32api import win32gui import win32con -import urllib3 +import winerror import winreg + +import threading +import requests +import urllib3 import signal import ctypes import time import os import re - # Define constants CHECK_INTERVAL = 2 # Seconds CONNECT_TEST_URL_AND_RESPONSES = { @@ -45,6 +47,7 @@ ICON_INDICATOR_ON = os.path.join(os.environ.get("VM_COMMON_DIR"), "indicator_on. ICON_INDICATOR_OFF = os.path.join(os.environ.get("VM_COMMON_DIR"), "indicator_off.ico") DEFAULT_BACKGROUND = os.path.join(os.environ.get("VM_COMMON_DIR"), "background.png") INTERNET_BACKGROUND = os.path.join(os.environ.get("VM_COMMON_DIR"), "background-internet.png") +REGISTRY_PATH = r"Software\InternetDetector" # Global variables tray_icon = None @@ -59,10 +62,21 @@ default_palette = None # Win32 API icon handles hicon_indicator_off = None hicon_indicator_on = None +mutex = None +def is_already_running(): + global mutex + # Try to create a mutex with a unique name. + mutex_name = f"{{{os.path.basename(__file__).replace('.py', '')}}}" # Use filename as part of mutex name + try: + mutex = win32event.CreateMutex(None, False, mutex_name) # False means don't acquire initially + return winerror.ERROR_ALREADY_EXISTS == win32api.GetLastError() + except Exception as e: + print(f"Mutex creation error: {e}") + return False # Assume not running if error def signal_handler(sig, frame): - global check_thread, tray_icon_thread, tray_icon + global check_thread, tray_icon_thread, tray_icon, mutex print("Ctrl+C detected. Exiting...") stop_event.set() # Signal the background thread to stop if check_thread: @@ -70,10 +84,14 @@ def signal_handler(sig, frame): if tray_icon_thread: tray_icon_thread.join() if tray_icon: - del tray_icon + try: + del tray_icon + except Exception as e: + print(f"Error destroying tray icon: {e}") + if mutex: + win32api.CloseHandle(mutex) exit(0) - def load_icon(icon_path): try: return win32gui.LoadImage(None, icon_path, win32con.IMAGE_ICON, 0, 0, win32con.LR_LOADFROMFILE) @@ -81,12 +99,12 @@ def load_icon(icon_path): print(f"Error loading indicator icon: {e}") return None - class SysTrayIcon: def __init__(self, hwnd, icon, tooltip): self.hwnd = hwnd self.icon = icon self.tooltip = tooltip + self.valid = True # System tray icon data structure self.nid = ( self.hwnd, @@ -97,9 +115,14 @@ class SysTrayIcon: self.tooltip, ) # Add the icon to the system tray - win32gui.Shell_NotifyIcon(win32gui.NIM_ADD, self.nid) + try: + win32gui.Shell_NotifyIcon(win32gui.NIM_ADD, self.nid) + except Exception as e: + print(f"Error creating tray icon: {e}") + self.valid = False def set_tooltip(self, new_tooltip): + if not self.valid: return self.tooltip = new_tooltip self.nid = ( self.hwnd, @@ -109,9 +132,14 @@ class SysTrayIcon: self.icon, self.tooltip, ) - win32gui.Shell_NotifyIcon(win32gui.NIM_MODIFY, self.nid) + try: + win32gui.Shell_NotifyIcon(win32gui.NIM_MODIFY, self.nid) + except Exception as e: + print(f"Error modifying tray icon tooltip: {e}") + self.valid = False def set_icon(self, icon): + if not self.valid: return self.icon = icon self.nid = ( self.hwnd, @@ -121,12 +149,20 @@ class SysTrayIcon: self.icon, self.tooltip, ) - win32gui.Shell_NotifyIcon(win32gui.NIM_MODIFY, self.nid) + try: + win32gui.Shell_NotifyIcon(win32gui.NIM_MODIFY, self.nid) + except Exception as e: + print(f"Error modifying tray icon image: {e}") + self.valid = False def __del__(self): # Remove the icon from the system tray when the object is destroyed - win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, self.nid) - + if not self.valid: return + try: + win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, self.nid) + except Exception as e: + print(f"Error deleting tray icon: {e}") + self.valid = False def get_current_color_prevalence(): try: @@ -145,7 +181,6 @@ def get_current_color_prevalence(): print("Error accessing registry.") return None - # Reads color palette binary data from a registry key and returns it as a hex string. def get_current_color_palette(): try: @@ -165,7 +200,6 @@ def get_current_color_palette(): print("Error accessing registry.") return None - # Attempts to get the current taskbar color based on user personalization settings and returns it in hex format. def get_current_taskbar_color(): try: @@ -190,7 +224,6 @@ def get_current_taskbar_color(): print("Error accessing registry.") return None - def set_taskbar_accent_color(hex_color, hex_color_palette, color_prevalence): """ Sets the accent color location in the Windows registry. @@ -235,7 +268,6 @@ def set_taskbar_accent_color(hex_color, hex_color_palette, color_prevalence): except WindowsError as e: print(f"Error accessing or modifying registry: {e}") - def get_transparency_effects(): try: key = winreg.OpenKey( @@ -251,7 +283,6 @@ def get_transparency_effects(): except WindowsError as e: print(f"Error accessing or modifying registry: {e}") - def set_transparency_effects(value): try: key = winreg.OpenKey( @@ -266,7 +297,6 @@ def set_transparency_effects(value): except WindowsError as e: print(f"Error accessing or modifying registry: {e}") - # Attempt to extract a known good value in response. def extract_title(data): match = re.search(r"(.*?)", data) @@ -275,7 +305,6 @@ def extract_title(data): else: return None - def check_internet(): for url, expected_response in CONNECT_TEST_URL_AND_RESPONSES.items(): try: @@ -288,7 +317,6 @@ def check_internet(): pass return False - def check_internet_and_update_tray_icon(): global tray_icon, hicon_indicator_off, hicon_indicator_on, default_color if check_internet(): @@ -308,12 +336,28 @@ def check_internet_and_update_tray_icon(): if get_wallpaper_path() != DEFAULT_BACKGROUND: # Checked so program isn't continuously setting the wallpaper set_wallpaper(DEFAULT_BACKGROUND) - def check_internet_loop(): + global tray_icon while not stop_event.is_set(): - check_internet_and_update_tray_icon() - time.sleep(CHECK_INTERVAL) - + if tray_icon and tray_icon.valid: + check_internet_and_update_tray_icon() + time.sleep(CHECK_INTERVAL) + else: + print("Tray icon is invalid. Exiting check_internet_loop.") + stop_event.set() + if tray_icon: + del tray_icon + tray_icon = None + + # Restart the tray icon and check_internet threads + tray_icon_thread = threading.Thread(target=tray_icon_loop) + tray_icon_thread.start() + # Wait for the tray icon to finish initializing + while tray_icon is None: + time.sleep(0.1) + check_thread = threading.Thread(target=check_internet_loop) + check_thread.start() + return def tray_icon_loop(): global hwnd, tray_icon, hicon_indicator_off, hicon_indicator_on, stop_event @@ -332,13 +376,13 @@ def tray_icon_loop(): tray_icon = SysTrayIcon(hwnd, hicon_indicator_off, "Internet Detector") while not stop_event.is_set(): - msg = win32gui.PeekMessage(hwnd, 0, 0, 0) - if msg and len(msg) == 6: + # Use PeekMessage to avoid blocking and allow thread exit + ret, msg = win32gui.PeekMessage(hwnd, 0, 0, win32con.PM_REMOVE) + if ret != 0: win32gui.TranslateMessage(msg) win32gui.DispatchMessage(msg) time.sleep(0.1) - def get_wallpaper_path(): """Attempts to retrieve the path to the current wallpaper image.""" # Try to get the path from the registry (for wallpapers set through Windows settings) @@ -365,7 +409,6 @@ def get_wallpaper_path(): # If all else fails, return None return None - def set_wallpaper(image_path): """Sets the desktop wallpaper to the image at the specified path.""" print(f"Setting wallpaper to: {image_path}") @@ -375,9 +418,40 @@ def set_wallpaper(image_path): if not result: print("Error setting wallpaper. Make sure the image path is correct.") +def save_default_settings(): + """Saves the default color, palette, and color prevalence to the registry.""" + try: + key = winreg.CreateKey(winreg.HKEY_CURRENT_USER, REGISTRY_PATH) + winreg.SetValueEx(key, "DefaultColor", 0, winreg.REG_SZ, default_color) + winreg.SetValueEx(key, "DefaultPalette", 0, winreg.REG_SZ, default_palette) + winreg.SetValueEx(key, "DefaultColorPrevalence", 0, winreg.REG_DWORD, default_color_prevalence) + winreg.CloseKey(key) + print("Default settings saved to registry.") + except WindowsError as e: + print(f"Error saving default settings to registry: {e}") + +def load_default_settings(): + """Loads the default color, palette, and color prevalence from the registry.""" + global default_color, default_palette, default_color_prevalence + try: + key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, REGISTRY_PATH, 0, winreg.KEY_READ) + default_color, _ = winreg.QueryValueEx(key, "DefaultColor") + default_palette, _ = winreg.QueryValueEx(key, "DefaultPalette") + default_color_prevalence, _ = winreg.QueryValueEx(key, "DefaultColorPrevalence") + winreg.CloseKey(key) + print("Default settings loaded from registry.") + return True + except WindowsError: + print("No saved default settings found in registry.") + return False def main_loop(): - global stop_event, check_thread, tray_icon_thread, tray_icon + global stop_event, check_thread, tray_icon_thread, tray_icon, mutex + + if is_already_running(): + print("Another instance is already running. Exiting.") + return + # Create and start the threads tray_icon_thread = threading.Thread(target=tray_icon_loop) check_thread = threading.Thread(target=check_internet_loop) @@ -392,14 +466,18 @@ def main_loop(): while not stop_event.is_set(): time.sleep(1) - if __name__ == "__main__": signal.signal(signal.SIGINT, signal_handler) urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) default_transparency = get_transparency_effects() - default_color_prevalence = get_current_color_prevalence() - default_color = get_current_taskbar_color() - default_palette = get_current_color_palette() + + # Try to load default settings from the registry + if not load_default_settings(): + # If not found, get the current settings and save them as defaults + default_color_prevalence = get_current_color_prevalence() + default_color = get_current_taskbar_color() + default_palette = get_current_color_palette() + save_default_settings() # Create a hidden window to receive messages (required for system tray icons) def wndProc(hwnd, msg, wparam, lparam): @@ -422,4 +500,4 @@ if __name__ == "__main__": print(f"Current wallpaper: {get_wallpaper_path()}") print(f"Current color: {default_color}") - main_loop() + main_loop() \ No newline at end of file diff --git a/packages/libraries-extra.python3.vm/libraries-extra.python3.vm.nuspec b/packages/libraries-extra.python3.vm/libraries-extra.python3.vm.nuspec deleted file mode 100644 index 34826c1ac..000000000 --- a/packages/libraries-extra.python3.vm/libraries-extra.python3.vm.nuspec +++ /dev/null @@ -1,13 +0,0 @@ - - - - libraries-extra.python3.vm - 0.0.0.20241029 - Install extra Python useful libraries - Several, check in pypi.org for every of the libraries - - - - - - diff --git a/packages/libraries.python3.vm/libraries.python3.vm.nuspec b/packages/libraries.python3.vm/libraries.python3.vm.nuspec index 0f1bc7464..c3d08de89 100644 --- a/packages/libraries.python3.vm/libraries.python3.vm.nuspec +++ b/packages/libraries.python3.vm/libraries.python3.vm.nuspec @@ -2,7 +2,7 @@ libraries.python3.vm - 0.0.0.20240726 + 0.0.0.20241213 Metapackage to install common Python libraries Several, check in pypi.org for every of the libraries diff --git a/packages/libraries.python3.vm/tools/modules.xml b/packages/libraries.python3.vm/tools/modules.xml index 7553273af..17c1cea1b 100644 --- a/packages/libraries.python3.vm/tools/modules.xml +++ b/packages/libraries.python3.vm/tools/modules.xml @@ -1,6 +1,7 @@ + diff --git a/packages/regcool.vm/regcool.vm.nuspec b/packages/regcool.vm/regcool.vm.nuspec index 21d30e9cf..ab9bc1570 100644 --- a/packages/regcool.vm/regcool.vm.nuspec +++ b/packages/regcool.vm/regcool.vm.nuspec @@ -2,7 +2,7 @@ regcool.vm - 2.015 + 2.019 Kurt Zimmermann In addition to all the features that you can find in RegEdit and RegEdt32, RegCool adds many powerful features that allow you to work faster and more efficiently with registry related tasks diff --git a/packages/regcool.vm/tools/chocolateyinstall.ps1 b/packages/regcool.vm/tools/chocolateyinstall.ps1 index 015d91be3..72137109d 100644 --- a/packages/regcool.vm/tools/chocolateyinstall.ps1 +++ b/packages/regcool.vm/tools/chocolateyinstall.ps1 @@ -5,6 +5,6 @@ $toolName = 'RegCool' $category = 'Registry' $zipUrl = 'https://kurtzimmermann.com/files/RegCoolX64.zip' -$zipSha256 = '8fde37cf66024eb68be3c0e34125540f855626935f1cffc0fb7409f3ba343870' +$zipSha256 = 'df3c80da807cab5b1612f0697373317523142643c4346ad618c3ec69d16db33e' VM-Install-From-Zip $toolName $category $zipUrl -zipSha256 $zipSha256 -consoleApp $false -innerFolder $false diff --git a/packages/vcredist140.vm/vcredist140.vm.nuspec b/packages/vcredist140.vm/vcredist140.vm.nuspec index 0e8e2ad49..e5dc1fa9f 100644 --- a/packages/vcredist140.vm/vcredist140.vm.nuspec +++ b/packages/vcredist140.vm/vcredist140.vm.nuspec @@ -2,12 +2,12 @@ vcredist140.vm - 0.0.0.20231019 + 0.0.0.20241213 Metapackage for Python 3 to ensure all packages use the same Python version. Mandiant - + diff --git a/scripts/test/lint.py b/scripts/test/lint.py index 09c140a02..f510313e7 100644 --- a/scripts/test/lint.py +++ b/scripts/test/lint.py @@ -354,7 +354,7 @@ def check(self, path): # utf-8-sig ignores BOM file_content = open(path, "r", encoding="utf-8-sig").read() - match = re.search("\$category = ['\"](?P[\w &/]+)['\"]", file_content) + match = re.search(r"\$category = ['\"](?P[\w &/]+)['\"]", file_content) if not match or match.group("category") not in self.CATEGORIES: return True return False