def init_device_list(refresh=False): # Build up the nic list if not refresh and len(NetworkDevices.NIC_LIST) > 0: # Don't rebuild it has been done return True n_list = [] n_list += NetworkDevices.default_microsoft_nics n_list += NetworkDevices.default_approved_nics # Load the value from the registry try: approved_nics_json = RegistrySettings.get_reg_value( app="OPEService", value_name="approved_nics", default="[]") nic_list = json.loads(approved_nics_json) for item in nic_list: # Add each item to the list # p("found nic " + str(item)) n_list.append(item) except Exception as ex: p("}}rbUnable to pull approved nics from registry!}}xx") # Set the current list NetworkDevices.NIC_LIST = n_list return True
def sync_time_w_ntp(): if not SystemTime.is_time_to_sync(): p("}}gnNot time to sync w NTP servers yet, skipping.}}xx", log_level=4) return True RegistrySettings.set_reg_value(value_name="last_ntp_sync", value=time.time()) smc_url = RegistrySettings.get_reg_value(value_name="smc_url", default="https://smc.ed") smc_host = smc_url.lower().replace("https://", "").replace("http://", "").replace("/", "") if ":" in smc_host: # port :8000 - remove it pos = smc_host.index(":") smc_host = smc_host[:pos] # Pull the current time from the SMC server and set it locally. # HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\DateTime\Servers # w32tm /stripchart /computer:smc.ed /dataonly /samples:5 # w32tm /query /peers # Add our time servers to the list os.system("w32tm /config /update /manualpeerlist:\"" + smc_host + " time.windows.com 202.5.222.1\"") # Force the update os.system("w32tm /resync /nowait") # /nowait return True
def elevate_process_privilege_to_backup_restore(): #add_privilege=ntsecuritycon.SE_RESTORE_NAME | #ntsecuritycon.SE_BACKUP_NAME ): try: se_backup_value = win32security.LookupPrivilegeValue( None, ntsecuritycon.SE_BACKUP_NAME) se_restore_value = win32security.LookupPrivilegeValue( None, ntsecuritycon.SE_RESTORE_NAME) flags = ntsecuritycon.TOKEN_ADJUST_PRIVILEGES \ | ntsecuritycon.TOKEN_QUERY proces_token = win32security.OpenProcessToken( win32api.GetCurrentProcess(), flags) # Add backup/restore privileges new_privs = [(se_backup_value, ntsecuritycon.SE_PRIVILEGE_ENABLED), (se_restore_value, ntsecuritycon.SE_PRIVILEGE_ENABLED) ] win32security.AdjustTokenPrivileges(proces_token, 0, new_privs) except Exception as ex: p("}}rbException - trying to elveate backup/restore privileges}}xx\n" + str(ex)) return False return True
def SvcOtherEx(self, control, event_type, data): # This is only showing a few of the extra events - see the MSDN # docs for "HandlerEx callback" for more info. if control == win32service.SERVICE_CONTROL_DEVICEEVENT: info = win32gui_struct.UnpackDEV_BROADCAST(data) msg = "A device event occurred (queued up running scan_nics): %x - %s" % ( event_type, info) OPEService._LAST_DEVICE_EVENT = time.time() OPEService._LAST_DEVICE_EVENT_PARAMS = (event_type, info) OPEService._DEVICE_EVENT_NEEDED = True # command will run when it is time p("-- Device Event Happended - queued device_event command for later " + msg, log_level=2) return elif control == win32service.SERVICE_CONTROL_HARDWAREPROFILECHANGE: msg = "A hardware profile changed: type=%s, data=%s" % (event_type, data) elif control == win32service.SERVICE_CONTROL_POWEREVENT: msg = "A power event: setting %s" % data self.run_command("device_event", (event_type, info), force_run=True) elif control == win32service.SERVICE_CONTROL_SESSIONCHANGE: # data is a single elt tuple, but this could potentially grow # in the future if the win32 struct does msg = "Session event: type=%s, data=%s" % (event_type, data) else: msg = "Other event: code=%d, type=%s, data=%s" \ % (control, event_type, data) p("-- Other Event " + msg, log_level=2)
def device_event(): # A device event happened (device plugged in?) # TODO - detect types of device events? # for now, just run scan nics which will kick off any bad devices p("}}ynDevice Event Detected! Scanning nics...}}xx") return NetworkDevices.scan_nics()
def apply_firewall_policy(): ret = True if RegistrySettings.is_debug(): p("}}rbDEBUG MODE ON - Skipping apply firewall policy}}xx") return True policy_file_name = util.get_param(2, "firewall_config.wfw") # Should be in RC sub folder under the app app_folder = util.get_app_folder() rc_path = os.path.join(app_folder, "rc") policy_file_path = os.path.join(rc_path, policy_file_name) # netsh advfirewall import "%~dp0rc\firewall_config.wfw" 2>NUL 1<NUL cmd = "%SystemRoot%\\system32\\netsh advfirewall import \"" + policy_file_path + "\"" returncode, output = ProcessManagement.run_cmd(cmd, attempts=5, require_return_code=0, cmd_timeout=15) if returncode == -2: # Error running command? p("}}rbError - Unable to reset firewall back to defaults?}}xx\n" + output) ret = False return ret
def reset_firewall_policy(): ret = True if RegistrySettings.is_debug(): p("}}rbDEBUG MODE ON - Skipping reset firewall policy}}xx") return True cmd = "%SystemRoot%\\system32\\netsh advfirewall reset" returncode, output = ProcessManagement.run_cmd(cmd, attempts=5, require_return_code=0, cmd_timeout=15) if returncode == -2: # Error running command? p("}}rbError - Unable to reset firewall back to defaults?}}xx\n" + output) ret = False # rem reset settings to default # netsh advfirewall reset # rem turn on all profiles # rem netsh advfirewall set allprofiles state on # rem turn on logging # rem netsh advfirewall set currentprofile logging filename "c:\programdata\ope\tmp\log\pfirewall.log" return ret
def run_tests(): p("}}gnRunning Tests...}}xx") #UserAccounts.disable_guest_account() #UserAccounts.disable_student_accounts() p(CredentialProcess.get_mgmt_version()) pass
def set_default_ope_folder_permissions(): # Set permissions on OPE folder so inmates can't change things # Load up the system goups/users FolderPermissions.init_win_user_accounts() # Make sure folders exits if not os.path.isdir(util.ROOT_FOLDER): os.makedirs(util.ROOT_FOLDER, exist_ok=True) if not os.path.isdir(util.TMP_FOLDER): os.makedirs(util.TMP_FOLDER, exist_ok=True) if not os.path.isdir(util.LOG_FOLDER): os.makedirs(util.LOG_FOLDER, exist_ok=True) if not os.path.isdir(util.SCREEN_SHOTS_FOLDER): os.makedirs(util.SCREEN_SHOTS_FOLDER, exist_ok=True) if not os.path.isdir(util.BINARIES_FOLDER): os.makedirs(util.BINARIES_FOLDER, exist_ok=True) if not os.path.isdir(util.GIT_FOLDER): os.makedirs(util.GIT_FOLDER, exist_ok=True) if not os.path.isdir(util.STUDENT_DATA_FOLDER): os.makedirs(util.STUDENT_DATA_FOLDER, exist_ok=True) # ---- ope-sshot.log ---- # Make sure the ope-sshot.log file exists so we can set permissions on it later if not os.path.isfile(os.path.join(util.LOG_FOLDER, "ope-sshot.log")): f = open(os.path.join(util.LOG_FOLDER, "ope-sshot.log"), "w") f.close() # ---- ope-mgmt.log ---- # Make sure the ope-sshot.log file exists so we can set permissions on it later if not os.path.isfile(os.path.join(util.LOG_FOLDER, "ope-mgmt.log")): f = open(os.path.join(util.LOG_FOLDER, "ope-mgmt.log"), "w") f.close() # App folder permissions are set based on this list # r - read/execute, n - none, c - create/append, a - appendonly, f - full app_folders = { util.ROOT_FOLDER: "r", util.BINARIES_FOLDER: "r", util.STUDENT_DATA_FOLDER: "r", util.TMP_FOLDER: "r", util.GIT_FOLDER: "r", # TODO - change to n when we can avoid security prompts util.LOG_FOLDER: "c", os.path.join(util.LOG_FOLDER, "ope-sshot.log"): "a", os.path.join(util.LOG_FOLDER, "ope-mgmt.log"): "a", util.SCREEN_SHOTS_FOLDER: "c", } for f in app_folders.keys(): everyone_rights = app_folders[f] p("}}gnSetting permissions on " + f + " (rights for everyone " + \ everyone_rights + ")}}xx", log_level=5) FolderPermissions.set_ope_folder_permissions( f, everyone_rights=everyone_rights) return True
def SvcStop(self): try: self.isAlive = False self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) win32event.SetEvent(self.hWaitStop) p("}}cnService Stop Event Recieved, Stopping Service", log_level=1) except Exception as ex: p("}}rbUnknown Exception: }}xx\n" + str(ex), log_level=1)
def disable_guest_account(): try: UserAccounts.disable_account("Guest") except Exception as ex: p("}}rbERROR disabling guest account " + str(ex) + "}}xx") return False # Run this to disable the guest account? # NET USER Guest /ACTIVE:no return True
def log_out_all_students(): # Get a list of users who are in the students group and log them out. students = UserAccounts.get_student_login_sessions() p("}}cb-- Logging out all student accounts ...}}xx") for student in students: p("}}cn-" + student + "}}xx", log_level=1) UserAccounts.log_out_user(student) return True
def finish_upgrade_process(): # If everything was successful, then # - Re-apply security # - lock_machine also re-enables credentialed account if succesful if not CredentialProcess.lock_machine(): p("}}rbERROR - Unable to lock machine after upgrade!}}xx") return False p("}}gbSUCCESS! - Machine locked and user account enabled.}}xx") return True
def is_version_newer(current_version, remote_version): # Parse the strings and see which version is newer ret = False # Split out the parts cv_parts = current_version.split(".") rv_parts = remote_version.split(".") cv_major = 0 cv_minor = 0 cv_revision = 0 try: cv_major = int(cv_parts[0]) except: pass try: cv_minor = int(cv_parts[1]) except: pass try: cv_revision = int(cv_parts[2]) except: pass rv_major = 0 rv_minor = 0 rv_revision = 0 try: rv_major = int(rv_parts[0]) except: pass try: rv_minor = int(rv_parts[1]) except: pass try: rv_revision = int(rv_parts[2]) except: pass p(str(cv_major) + "." + str(cv_minor) + "." + str(cv_revision) + " -> " + \ str(rv_major) + "." + str(rv_minor) + "." + str(rv_revision)) # Is major version bigger? if rv_major > cv_major: ret = True # Is minor version bigger? if rv_major == cv_major and rv_minor > cv_minor: ret = True # Is revision bigger? if rv_major == cv_major and rv_minor == cv_minor and rv_revision > cv_revision: ret = True return ret
def p(self, msg="", end=True, out=None, debug_level=0): if self.output_control is None: color.p(msg, end=end, out=out, debug_level=debug_level) return # Convert color codes? msg = color.translate_color_codes_to_markup(msg) if end is True: end = "\n" # Print to the label self.set_text(self.output_control, msg + end)
def remove_key(key_path): try: # Open the key key = registry.registry(key_path, access=REGISTRY_ACCESS.KEY_READ|REGISTRY_ACCESS.KEY_WOW64_64KEY) key.delete() except Exception as ex: p("}}rnError - couldn't remove registry key }}xx\n" + str(key_path) + "\n" + \ str(ex), debug_level=1) return False return True
def lock_screen_for_user(user_name=None): # Find the user in question and lock the workstation if user_name is None: user_name = util.get_param(2, None) if user_name is None: # Lock for the current user if no name return UserAccounts.lock_screen_for_current_user() p("}}ybLocking screen for other users - Not Implemented Yet!}}xx") # TODO - lock_workstation # Lookup the user specified and run this under their account return False
def disable_nic(interface_index): #w = wmi.WMI(namespace="StandardCimv2") w = Computer.get_wmi_connection(namespace="StandardCimv2") ifaces = w.MSFT_NetAdapter(InterfaceIndex=interface_index) for iface in ifaces: out = "" iface.Disable(out) if out != "": p("OUTPUT: " + str(out)) #iface.Lock() return True
def is_time_to_ping_smc(): # How long has it been since we talked to the SMC server? last_smc_ping_time = RegistrySettings.get_reg_value(value_name="last_smc_ping_time", default=0) curr_time = time.time() # Only need a successful ping every ? minutes min_time = 30 # TODO - Turn ping time back up 300 time_diff = curr_time - last_smc_ping_time if time_diff > min_time: return True p("}}ynNot time to ping yet - " + str(int(min_time - time_diff)) + " seconds left.}}xx", log_level=4) return False
def list_approved_nics(): # Show a list of approved nics NetworkDevices.init_device_list() # Get the specifically approved nics vs the default approved manually_approved_nics = [] # Load the value from the registry try: approved_nics_json = RegistrySettings.get_reg_value( app="OPEService", value_name="approved_nics", default="[]") manually_approved_nics = json.loads(approved_nics_json) except Exception as ex: p("}}rbUnable to pull approved nics from registry!}}xx") p("}}yn+ Pre-approved nics (can't remove)}}xx") p("}}mb* Nic manually added to approved list by admin}}xx\n") col1 = 45 col2 = 30 for item in NetworkDevices.NIC_LIST: m = " " if item in manually_approved_nics: m = "}}mb* }}xx" else: m = "}}yn+ }}xx" ips = str(item[1]) if ips == "-1": ips = "OK only if no IP (-1)" if ips == "*": ips = "Any IP Allowed (*)" p(m + item[0].ljust(col1) + ips.rjust(col2))
def RunAsTraceCollector(): import sys try: import win32api win32api.SetConsoleTitle("Python Trace Collector") except: pass # Oh well! win32trace.InitRead() p("Collecting Python Trace Output...", log_level=4) try: while 1: # a short timeout means ctrl+c works next time we wake... sys.stdout.write(win32trace.blockingread(500)) except KeyboardInterrupt: p("}}ybCtrl+C - quitting...}}xx", log_level=3)
def ping_smc(smc_url): json_response = RestClient.send_rest_call(server=smc_url, api_endpoint="lms/ping.json", ) if json_response is None: # If None - unable to communicate - likely offline p("}}ynNo response from smc server}}xx", log_level=4) return False server_time = util.get_dict_value(json_response, "server_time") p("}}mnPING - Got SMC Server time: " + str(server_time) + "}}xx") return True
def fix_path_variables(self, cmd): #p("util.BINARIES_FOLDER: " + util.BINARIES_FOLDER) # Replace variables such as %sshot% and %mgmt% w proper path mgmt_path = os.path.normpath( os.path.join(util.BINARIES_FOLDER, "mgmt/mgmt.exe")) sshot_path = os.path.normpath( os.path.join(util.BINARIES_FOLDER, "sshot/sshot.exe")) cmd = cmd.replace("%mgmt%", mgmt_path) cmd = cmd.replace("%sshot%", sshot_path) p("fix_path_variable: " + cmd, log_level=5) return cmd
def disable_account(account_name=None): if account_name is None: account_name = util.get_param(2, None) if account_name is None: p("}}enInvalid User name - not disabling account!}}xx") return False try: user_data = dict() user_data['flags'] = UserAccounts.DISABLE_ACCOUNT_FLAGS #win32netcon.UF_SCRIPT | win32netcon.UF_ACCOUNTDISABLE win32net.NetUserSetInfo(None, account_name, 1008, user_data) except Exception as ex: p("}}rnError - Unable to disable account: " + str(account_name) + "}}xx\n" + \ str(ex)) return False return True
def ListenForDeviceEvents(self): try: # register for a device notification - we pass our service handle # instead of a window handle. filter = win32gui_struct.PackDEV_BROADCAST_DEVICEINTERFACE( OPEService.GUID_DEVINTERFACE_USB_DEVICE) self.hdn = win32gui.RegisterDeviceNotification( self.ssh, filter, win32con.DEVICE_NOTIFY_SERVICE_HANDLE) p("}}cnService now listening for device events", log_level=3) except Exception as ex: p("Unknown Error listening for device events " + str(ex), log_level=1) return
def set_log_level(): # Set the log level parameter in the registry param = util.get_param(2) if param == "": p("}}rnInvalid Log Level Specified}}xx") return False log_level = 3 try: log_level = int(param) except: p("}}rnInvalid Log Level Specified}}xx") return False # Set the registry setting RegistrySettings.set_reg_value(app="OPEService", value_name="log_level", value=log_level) return True
def set_default_permissions_timer(): # Set how often to reset permissions in the registry param = util.get_param(2) if param == "": p("}}rnInvalid frequency Specified}}xx") return False frequency = 3600 try: frequency = int(param) except: p("}}rnInvalid frequency Specified}}xx") return False # Set the registry setting RegistrySettings.set_reg_value(app="OPEService", value_name="set_default_permissions_timer", value=frequency) return True
def set_scan_nics_timer(): # Set how often to reload scan nics param = util.get_param(2) if param == "": p("}}rnInvalid frequency Specified}}xx") return False frequency = 60 try: frequency = int(param) except: p("}}rnInvalid frequency Specified}}xx") return False # Set the registry setting RegistrySettings.set_reg_value(app="OPEService", value_name="scan_nics_timer", value=frequency) return True
def create_local_students_group(): # Make sure the group in question exists ret = False try: accounts.LocalGroup.create(UserAccounts.STUDENTS_GROUP) ret = True except Exception as ex: if ex.args[2] == "The specified local group already exists.": ret = True pass else: # Unexpected error p("}}rb" + str(ex) + "}}xx") ret = False return ret
def add_user_to_group(user_name, group_name): try: # Get the group grp = accounts.LocalGroup(accounts.group(group_name).sid) # Get the user user = accounts.user(user_name) grp.add(user) except Exception as ex: if ex.args[ 2] == "The specified account name is already a member of the group.": pass else: p("}}rbERROR - Unexpected exception trying to add user to group (" + \ user_name + "/" + group_name + "\n}}xx" + str(ex)) return False return True