From 85e78135391c28c60a7d597eae2e9393eba4ed81 Mon Sep 17 00:00:00 2001 From: 2Shirt <1923621+2Shirt@users.noreply.github.com> Date: Tue, 2 Oct 2018 22:09:17 -0600 Subject: [PATCH] Check Secure Boot status during system checklist * Fixes issue #60 --- .bin/Scripts/functions/common.py | 26 ++++++++++---- .bin/Scripts/functions/diags.py | 59 +++++++++++++++++++++++++++++--- .bin/Scripts/system_checklist.py | 16 ++++++--- 3 files changed, 85 insertions(+), 16 deletions(-) diff --git a/.bin/Scripts/functions/common.py b/.bin/Scripts/functions/common.py index dc427157..9bc4732d 100644 --- a/.bin/Scripts/functions/common.py +++ b/.bin/Scripts/functions/common.py @@ -64,12 +64,24 @@ class NotInstalledError(Exception): class NoProfilesError(Exception): pass +class OSInstalledLegacyError(Exception): + pass + class PathNotFoundError(Exception): pass class UnsupportedOSError(Exception): pass +class SecureBootDisabledError(Exception): + pass + +class SecureBootNotAvailError(Exception): + pass + +class SecureBootUnknownError(Exception): + pass + # General functions def abort(): """Abort script.""" @@ -271,7 +283,7 @@ def human_readable_size(size, decimals=0): units = 'Kb' else: units = ' b' - + # Return return '{size:>{width}.{decimals}f} {units}'.format( size=size, width=width, decimals=decimals, units=units) @@ -462,7 +474,7 @@ def run_program(cmd, args=[], check=True, pipe=True, shell=False): def set_title(title='~Some Title~'): """Set title. - + Used for window title and menu titles.""" global_vars['Title'] = title os.system('title {}'.format(title)) @@ -566,7 +578,7 @@ def try_and_print(message='Trying...', def upload_crash_details(): """Upload log and runtime data to the CRASH_SERVER. - + Intended for uploading to a public Nextcloud share.""" if not ENABLED_UPLOAD_DATA: raise GenericError @@ -648,7 +660,7 @@ def init_global_vars(): def check_os(): """Set OS specific variables.""" tmp = {} - + # Query registry path = r'SOFTWARE\Microsoft\Windows NT\CurrentVersion' with winreg.OpenKey(HKLM, path) as key: @@ -697,7 +709,7 @@ def check_os(): tmp['DisplayName'] = '{} x{}'.format(tmp['Name'], tmp['Arch']) if tmp['Notes']: tmp['DisplayName'] += ' ({})'.format(tmp['Notes']) - + global_vars['OS'] = tmp def check_tools(): @@ -714,7 +726,7 @@ def check_tools(): def clean_env_vars(): """Remove conflicting global_vars and env variables. - + This fixes an issue where both global_vars and global_vars['Env'] are expanded at the same time.""" for key in global_vars.keys(): @@ -768,7 +780,7 @@ def set_common_vars(): def set_linux_vars(): """Set common variables in a Linux environment. - + These assume we're running under a WK-Linux build.""" result = run_program(['mktemp', '-d']) global_vars['TmpDir'] = result.stdout.decode().strip() diff --git a/.bin/Scripts/functions/diags.py b/.bin/Scripts/functions/diags.py index 0deaead5..47991680 100644 --- a/.bin/Scripts/functions/diags.py +++ b/.bin/Scripts/functions/diags.py @@ -1,5 +1,7 @@ # Wizard Kit: Functions - Diagnostics +import ctypes + from functions.common import * # STATIC VARIABLES @@ -30,12 +32,59 @@ def check_connection(): result = try_and_print(message='Ping test...', function=ping, cs='OK') if result['CS']: break + if not ask('ERROR: System appears offline, try again?'): + if ask('Continue anyway?'): + break + else: + abort() + +def check_secure_boot_status(): + """Checks UEFI Secure Boot status via PowerShell.""" + boot_mode = get_boot_mode() + cmd = ['PowerShell', '-Command', 'Confirm-SecureBootUEFI'] + result = run_program(cmd, check=False) + + # Check results + if result.returncode == 0: + out = result.stdout.decode() + if 'True' in out: + # It's on, do nothing + return + elif 'False' in out: + raise SecureBootDisabledError else: - if not ask('ERROR: System appears offline, try again?'): - if ask('Continue anyway?'): - break - else: - abort() + raise SecureBootUnknownError + else: + if boot_mode != 'UEFI': + raise OSInstalledLegacyError + else: + # Check error message + err = result.stderr.decode() + if 'Cmdlet not supported' in err: + raise SecureBootNotAvailError + else: + raise GenericError + +def get_boot_mode(): + """Check if Windows is booted in UEFI or Legacy mode, returns str.""" + kernel = ctypes.windll.kernel32 + firmware_type = ctypes.c_uint() + + # Get value from kernel32 API + try: + kernel.GetFirmwareType(ctypes.byref(firmware_type)) + except: + # Just set to zero + firmware_type = ctypes.c_uint(0) + + # Set return value + type_str = 'Unknown' + if firmware_type.value == 1: + type_str = 'Legacy' + elif firmware_type.value == 2: + type_str = 'UEFI' + + return type_str def run_autoruns(): """Run AutoRuns in the background with VirusTotal checks enabled.""" diff --git a/.bin/Scripts/system_checklist.py b/.bin/Scripts/system_checklist.py index 73410d92..72bb82bf 100644 --- a/.bin/Scripts/system_checklist.py +++ b/.bin/Scripts/system_checklist.py @@ -24,11 +24,17 @@ if __name__ == '__main__': ticket_number = get_ticket_number() other_results = { 'Error': { - 'CalledProcessError': 'Unknown Error', - 'BIOSKeyNotFoundError': 'BIOS key not found', - 'FileNotFoundError': 'File not found', + 'BIOSKeyNotFoundError': 'BIOS key not found', + 'CalledProcessError': 'Unknown Error', + 'FileNotFoundError': 'File not found', + 'GenericError': 'Unknown Error', + 'SecureBootDisabledError': 'Disabled', }, - 'Warning': {}} + 'Warning': { + 'OSInstalledLegacyError': 'OS installed Legacy', + 'SecureBootNotAvailError': 'Not available', + 'SecureBootUnknownError': 'Unknown', + }} if ENABLED_TICKET_NUMBERS: print_info('Starting System Checklist for Ticket #{}\n'.format( ticket_number)) @@ -76,6 +82,8 @@ if __name__ == '__main__': try_and_print(message='BIOS Activation:', function=activate_with_bios, other_results=other_results) + try_and_print(message='Secure Boot Status:', + function=check_secure_boot_status, other_results=other_results) try_and_print(message='Installed RAM:', function=show_installed_ram, ns='Unknown', silent_function=False) show_free_space()