diff --git a/scripts/check_av.ps1 b/scripts/check_av.ps1 new file mode 100644 index 00000000..b65a7c52 --- /dev/null +++ b/scripts/check_av.ps1 @@ -0,0 +1,13 @@ +# WizardKit: Check Antivirus + +#Requires -Version 3.0 +if (Test-Path Env:\DEBUG) { + Set-PSDebug -Trace 1 +} +$Host.UI.RawUI.WindowTitle = "WizardKit: Check Antivirus" +$Host.UI.RawUI.BackgroundColor = "black" +$Host.UI.RawUI.ForegroundColor = "white" +$ProgressPreference = "SilentlyContinue" + +# Main +Get-CimInstance -Namespace "root\SecurityCenter2" -ClassName AntivirusProduct | select displayName,productState | ConvertTo-Json diff --git a/scripts/check_partition_alignment.ps1 b/scripts/check_partition_alignment.ps1 new file mode 100644 index 00000000..564351bd --- /dev/null +++ b/scripts/check_partition_alignment.ps1 @@ -0,0 +1,13 @@ +# WizardKit: Check Partition Alignment + +#Requires -Version 3.0 +if (Test-Path Env:\DEBUG) { + Set-PSDebug -Trace 1 +} +$Host.UI.RawUI.WindowTitle = "WizardKit: Check Partition Alignment" +$Host.UI.RawUI.BackgroundColor = "black" +$Host.UI.RawUI.ForegroundColor = "white" +$ProgressPreference = "SilentlyContinue" + +# Main +Get-CimInstance -Query "Select * from Win32_DiskPartition" | select Name,Size,StartingOffset | ConvertTo-Json diff --git a/scripts/disable_password_expiration.ps1 b/scripts/disable_password_expiration.ps1 new file mode 100644 index 00000000..f0ecff9c --- /dev/null +++ b/scripts/disable_password_expiration.ps1 @@ -0,0 +1,13 @@ +# WizardKit: Disable Password Expiration (Local Accounts) + +#Requires -Version 3.0 +if (Test-Path Env:\DEBUG) { + Set-PSDebug -Trace 1 +} +$Host.UI.RawUI.WindowTitle = "Disable Password Expiration" +$Host.UI.RawUI.BackgroundColor = "black" +$Host.UI.RawUI.ForegroundColor = "white" +$ProgressPreference = "SilentlyContinue" + +# Main +Get-LocalUser | Set-LocalUser -PasswordNeverExpires $true diff --git a/scripts/wk/cfg/setup.py b/scripts/wk/cfg/setup.py index 2ed1b714..71f72bb8 100644 --- a/scripts/wk/cfg/setup.py +++ b/scripts/wk/cfg/setup.py @@ -29,6 +29,14 @@ REG_CHROME_UBLOCK_ORIGIN = { ) }, } +REG_WINDOWS_BSOD_MINIDUMPS = { + 'HKLM': { + # Enable small memory dumps + r'SYSTEM\CurrentControlSet\Control\CrashControl': ( + ('CrashDumpEnabled', 3, 'DWORD'), + ) + } + } REG_WINDOWS_EXPLORER = { 'HKLM': { # Allow password sign-in for MS accounts diff --git a/scripts/wk/os/win.py b/scripts/wk/os/win.py index fa99404c..f0309a19 100644 --- a/scripts/wk/os/win.py +++ b/scripts/wk/os/win.py @@ -6,7 +6,6 @@ import logging import os import pathlib import platform -import re from contextlib import suppress from typing import Any @@ -74,9 +73,6 @@ KNOWN_HIVE_NAMES = { RAM_OK = 5.5 * 1024**3 # ~6 GiB assuming a bit of shared memory RAM_WARNING = 3.5 * 1024**3 # ~4 GiB assuming a bit of shared memory REG_MSISERVER = r'HKLM\SYSTEM\CurrentControlSet\Control\SafeBoot\Network\MSIServer' -REGEX_4K_ALIGNMENT = re.compile( - r'^(?P.*?)\s+(?P\d+)\s+(?P\d+)', - ) SLMGR = pathlib.Path(f'{os.environ.get("SYSTEMROOT")}/System32/slmgr.vbs') SYSTEMDRIVE = os.environ.get('SYSTEMDRIVE') @@ -169,29 +165,23 @@ def set_timezone(zone) -> None: # Info Functions def check_4k_alignment(show_alert=False) -> list[str]: """Check if all partitions are 4K aligned, returns list.""" - cmd = ['WMIC', 'partition', 'get', 'Caption,Size,StartingOffset'] + script_path = find_kit_dir('Scripts').joinpath('check_partition_alignment.ps1') + cmd = ['PowerShell', '-ExecutionPolicy', 'Bypass', '-File', script_path] + json_data = get_json_from_command(cmd) report = [] show_alert = False # Check offsets - proc = run_program(cmd) - for line in proc.stdout.splitlines(): - line = line.strip() - if not line or not line.startswith('Disk'): - continue - match = REGEX_4K_ALIGNMENT.match(line) - if not match: - LOG.error('Failed to parse partition info for: %s', line) - continue - if int(match.group('offset')) % 4096 != 0: - report.append( - ansi.color_string( - f'{match.group("description")}' - f' ({bytes_to_string(match.group("size"), decimals=1)})' - , - 'RED' - ) - ) + for part in json_data: + if part['StartingOffset'] % 4096 != 0: + report.append( + ansi.color_string( + f'{part["Name"]}' + f' ({bytes_to_string(part["Size"], decimals=1)})' + , + 'RED' + ) + ) # Show alert if show_alert: @@ -203,6 +193,7 @@ def check_4k_alignment(show_alert=False) -> list[str]: 0, ansi.color_string('One or more partitions not 4K aligned', 'YELLOW'), ) + report.sort() return report @@ -224,45 +215,52 @@ def export_bitlocker_info() -> None: _f.write(f'{proc.stdout}\n\n') -def get_installed_antivirus() -> list[str]: - """Get list of installed antivirus programs, returns list.""" - cmd = [ - 'WMIC', r'/namespace:\\root\SecurityCenter2', - 'path', 'AntivirusProduct', - 'get', 'displayName', '/value', - ] - products = [] - report = [] +def get_installed_antivirus() -> dict[str, dict]: + """Get installed antivirus products and their status, returns dict.""" + script_path = find_kit_dir('Scripts').joinpath('check_av.ps1') + cmd = ['PowerShell', '-ExecutionPolicy', 'Bypass', '-File', script_path] + json_data = get_json_from_command(cmd) + products = {} - # Get list of products - proc = run_program(cmd) - for line in proc.stdout.splitlines(): - line = line.strip() - if '=' in line: - products.append(line.split('=')[1]) + # Check state and build dict + for p in json_data: + name = p['displayName'] + state = p['productState'] + enabled = ((state>>8) & 0x11) in (0x10, 0x11) # middle two hex digits + outdated = (state & 0x11) != 0x00 # last two hex digits + products[name] = { + 'Enabled': enabled, + 'Outdated': outdated, + 'State': state, + } + return products + + +def list_installed_antivirus() -> list[str]: + """Get list of installed antivirus programs, returns list.""" + products = get_installed_antivirus() + products_active = [] + products_inactive = [] # Check product(s) status - for product in sorted(products): - cmd = [ - 'WMIC', r'/namespace:\\root\SecurityCenter2', - 'path', 'AntivirusProduct', - 'where', f'displayName="{product}"', - 'get', 'productState', '/value', - ] - proc = run_program(cmd) - state = proc.stdout.split('=')[1] - state = hex(int(state)) - if str(state)[3:5] not in ['10', '11']: - report.append(ansi.color_string(f'[Disabled] {product}', 'YELLOW')) + for name, details in products.items(): + if details['Enabled']: + if details['Outdated']: + products_active.append(ansi.color_string(f'{name} [OUTDATED]', 'YELLOW')) + else: + products_active.append(name) else: - report.append(product) + # Disabled + products_inactive.append(ansi.color_string(f'[Disabled] {name}', 'YELLOW')) # Final check - if not report: - report.append(ansi.color_string('No products detected', 'RED')) + if not (products_active or products_inactive): + products_inactive.append(ansi.color_string('No products detected', 'RED')) # Done - return report + products_active.sort() + products_inactive.sort() + return products_active + products_inactive def get_installed_ram(as_list=False, raise_exceptions=False) -> list | str: diff --git a/scripts/wk/setup/win.py b/scripts/wk/setup/win.py index b6863a05..1dbb2f09 100644 --- a/scripts/wk/setup/win.py +++ b/scripts/wk/setup/win.py @@ -19,6 +19,7 @@ from wk.cfg.setup import ( REG_WINDOWS_EXPLORER, REG_OPEN_SHELL_SETTINGS, REG_OPEN_SHELL_LOW_POWER_IDLE, + REG_WINDOWS_BSOD_MINIDUMPS, UBLOCK_ORIGIN_URLS, ) from wk.exe import kill_procs, run_program, popen_program @@ -36,7 +37,6 @@ from wk.os.win import ( OS_VERSION, activate_with_bios, check_4k_alignment, - get_installed_antivirus, get_installed_ram, get_os_activation, get_os_name, @@ -45,6 +45,7 @@ from wk.os.win import ( get_volume_usage, is_activated, is_secure_boot_enabled, + list_installed_antivirus, reg_set_value, reg_write_settings, stop_service, @@ -520,7 +521,7 @@ def auto_show_4k_alignment_check() -> None: def auto_show_installed_antivirus() -> None: """Display installed antivirus.""" - TRY_PRINT.run('Virus Protection...', get_installed_antivirus) + TRY_PRINT.run('Virus Protection...', list_installed_antivirus) def auto_show_installed_ram() -> None: @@ -629,14 +630,14 @@ def disable_chrome_notifications() -> None: def disable_password_expiration() -> None: """Disable password expiration for all users.""" - cmd = ['wmic', 'UserAccount', 'set', 'PasswordExpires=False'] + script_path = find_kit_dir('Scripts').joinpath('disable_password_expiration.ps1') + cmd = ['PowerShell', '-ExecutionPolicy', 'Bypass', '-File', script_path] run_program(cmd) def enable_bsod_minidumps() -> None: """Enable saving minidumps during BSoDs.""" - cmd = ['wmic', 'RECOVEROS', 'set', 'DebugInfoType', '=', '3'] - run_program(cmd) + reg_write_settings(REG_WINDOWS_BSOD_MINIDUMPS) def enable_ublock_origin() -> None: