def test_Registry_security(self): security_information = win32security.OWNER_SECURITY_INFORMATION | win32security.DACL_SECURITY_INFORMATION key = registry.registry(TEST_KEY) security = key.security(security_information) sd = win32security.GetSecurityInfo( win32api.RegOpenKey(win32con.HKEY_CURRENT_USER, r"software\winsys"), win32security.SE_REGISTRY_KEY, security_information) self.assertEqual( security.as_string(), win32security.ConvertSecurityDescriptorToStringSecurityDescriptor( sd, win32security.SDDL_REVISION_1, security_information))
def PrintWnfRuntimeStatus(StateName, CheckSd, DumpSd, MaxSize, DumpData): exists = 2 read, changeStamp, dataBuffer, bufferSize = ReadWnfData(StateName) write = CheckWriteAccess(StateName) if write: # see if anyone is listening for notifications on this state name. exists = QueryWnfInfoClass(StateName, 'WnfInfoSubscribersPresent') internalName = WNF_STATE_NAME_INTERNAL() internalName.value = StateName ^ WNF_STATE_KEY if not CheckInternalName(internalName): return False if internalName.b.NameLifetime == WNF_STATE_NAME_LIFETIME[ 'WnfWellKnownStateName'].value: name = GetWnfName(StateName) if name == "": char3 = format(internalName.b.Unique >> 37 & 0xff, 'c') char4 = format(internalName.b.Unique >> 45 & 0xff, 'c') char3 = char3 if char3.isprintable() else " " char4 = char4 if char4.isprintable() else " " name = "{:c}{:c}{}{}.{:0>3} 0x{:x}".format( internalName.b.Unique >> 21 & 0xff, internalName.b.Unique >> 29 & 0xff, char3, char4, internalName.b.Unique & 0xFFFFF, StateName) else: name = "0x{:x}".format(StateName) print("| {:<64}| {} | {} | {} | {} | {} | {:^7} | {:^7} | {:^7} |".format( name, WnfDataScopeStrings[internalName.b.DataScope][0], WnfLifetimeStrings[internalName.b.NameLifetime][0], 'Y' if internalName.b.PermanentData else 'N', ("RW" if write else "RO") if read else ("WO" if write else "NA"), 'A' if exists == 1 else 'U' if exists == 2 else 'I', bufferSize, MaxSize, changeStamp)) if DumpSd != False and CheckSd != None: strSd = win32security.ConvertSecurityDescriptorToStringSecurityDescriptor( CheckSd, win32security.SDDL_REVISION_1, win32security.DACL_SECURITY_INFORMATION | win32security.SACL_SECURITY_INFORMATION | win32security.LABEL_SECURITY_INFORMATION) print("\n\t{}".format(strSd)) if DumpData != False and read != False and bufferSize != 0: print("\n") hexdump(dataBuffer.raw[0:bufferSize]) print("\n") return True
def get_file_security(path, info): # Windows API call descriptor = win32security.GetFileSecurity(path, info) # Extract SDDL sddl = win32security.ConvertSecurityDescriptorToStringSecurityDescriptor( descriptor, win32security.SDDL_REVISION_1, win32security.OWNER_SECURITY_INFORMATION | win32security.GROUP_SECURITY_INFORMATION | win32security.DACL_SECURITY_INFORMATION | win32security.SACL_SECURITY_INFORMATION, ) return {"Sddl": sddl}
def get_access_control_string(self, information=SecurityInformation.OWNER | SecurityInformation.GROUP | SecurityInformation.DACL): ''' fi.get_access_control_string([information]) -> int or a SECURITY string Gets a string thats represent the access control for the file or directory described by the current FileInfo object. If non-WinNT system, return os.stat() of self.original_path, else return SECURITY string, returned by GetFileSecurity(self.original_path, information) api function 'information' defaults to SecurityInformation.OWNER | SecurityInformation.GROUP | SecurityInformation.DACL ''' if os.path.exists(self.original_path): if isinstance(information, SecurityInformation): information = information.value if os.name != "nt": return os.stat(self.original_path) else: try: import win32security except: raise NotSupportedException("you need pywin modules") try: security = win32security.GetFileSecurity( self.original_path, information) return win32security.ConvertSecurityDescriptorToStringSecurityDescriptor(security, win32security.SDDL_REVISION_1, information) except win32security.error as err: raise UnauthorizedAccessException(err) raise FileNotFoundException("'%s' not found" % self.original_path)
def get_registry_key_acl_procmon(self, path_dict): try: ''' cmd = { "proc_name" : proc_name, "orig_cmd" : orig_cmd, "clean_cmd" : clean_cmd, "operation" : operation, "integrity" : integrity } ''' registry_dict = dict( path_dict ) # A dictionary object containing all information regarding a single key r_path = registry_dict[ "clean_cmd"] # The cleaned registry key path - ready for DACL enumeration # HKLM support if "hklm" in r_path: try: path = r_path.split(":\\")[1] except: path = r_path.split("hklm\\")[1] key = win32api.RegOpenKey( con.HKEY_LOCAL_MACHINE, path, 0, con.KEY_ENUMERATE_SUB_KEYS | con.KEY_QUERY_VALUE | con.KEY_READ, ) # HKCU Support if "hkcu" in r_path: try: path = r_path.split(":\\")[1] except: path = r_path.split("hkcu\\")[1] key = win32api.RegOpenKey( con.HKEY_CURRENT_USER, path, 0, con.KEY_ENUMERATE_SUB_KEYS | con.KEY_QUERY_VALUE | con.KEY_READ, ) # HKCR Support if "hkcr" in r_path: try: path = r_path.split(":\\")[1] except: path = r_path.split("hkcr\\")[1] key = win32api.RegOpenKey( con.HKEY_CLASSES_ROOT, path, 0, con.KEY_ENUMERATE_SUB_KEYS | con.KEY_QUERY_VALUE | con.KEY_READ, ) sd = win32api.RegGetKeySecurity( # Obtain a Registry Security Object key, win32security.DACL_SECURITY_INFORMATION | win32security.OWNER_SECURITY_INFORMATION) dacl = sd.GetSecurityDescriptorDacl() # Registry Security DACL owner_sid = sd.GetSecurityDescriptorOwner( ) # Registry Security Owner sddl_string = win32security.ConvertSecurityDescriptorToStringSecurityDescriptor( sd, win32security.SDDL_REVISION_1, win32security.DACL_SECURITY_INFORMATION ) # Gives us an SDDL String we can now parse. all_permissions = dict(self.__sddl_dacl_parse(sddl_string)) keys = all_permissions.keys() acls = "" # Enumerate all the keys (registry paths) and ACLS for key in keys: acls += f"{key}: {all_permissions[key]}\n" acl_dict = { "process_name": path_dict["proc_name"], "integrity": path_dict["integrity"], "operation": path_dict["operation"], "original_cmd": path_dict["orig_cmd"], "path": r_path, "acls": acls } return acl_dict except Exception as e: error = str(e).lower() if ("find the path specified" in error or "find the file specified" in error or "access is denied" in error or "ace type 9" in error): final_dict = { "key_path": r_path, "acls": "ERROR", "error": error } return final_dict elif "no mapping" in error: note = """Possibly VULNERABLE: No mapping between account names and SID's Account used to set GPO may have been removed Account name may be typed incorrectly INFO: https://www.rebeladmin.com/2016/01/how-to-fix-error-no-mapping-between-account-names-and-security-ids-in-active-directory/""" final_dict = {"key_path": r_path, "acls": note, "error": error} return final_dict else: self.__write_error(r_path + "\n" + all_permissions) self.__print_exception() exit(0)
def get_registry_key_acl(self, root_key): try: r_path = root_key.lower() all_permissions = "" # HKLM support if "hklm" in r_path: try: path = r_path.split(":\\")[1] except: path = r_path.split("hklm\\")[1] key = win32api.RegOpenKey( con.HKEY_LOCAL_MACHINE, path, 0, con.KEY_ENUMERATE_SUB_KEYS | con.KEY_QUERY_VALUE | con.KEY_READ, ) # HKCU Support if "hkcu" in r_path: try: path = r_path.split(":\\")[1] except: path = r_path.split("hkcu\\")[1] key = win32api.RegOpenKey( con.HKEY_CURRENT_USER, path, 0, con.KEY_ENUMERATE_SUB_KEYS | con.KEY_QUERY_VALUE | con.KEY_READ, ) # HKCR Support if "hkcr" in r_path: try: path = r_path.split(":\\")[1] except: path = r_path.split("hkcr\\")[1] key = win32api.RegOpenKey( con.HKEY_CLASSES_ROOT, path, 0, con.KEY_ENUMERATE_SUB_KEYS | con.KEY_QUERY_VALUE | con.KEY_READ, ) sd = win32api.RegGetKeySecurity( key, win32security.DACL_SECURITY_INFORMATION | win32security.OWNER_SECURITY_INFORMATION, ) dacl = sd.GetSecurityDescriptorDacl() owner_sid = sd.GetSecurityDescriptorOwner() sddl_string = win32security.ConvertSecurityDescriptorToStringSecurityDescriptor( sd, win32security.SDDL_REVISION_1, win32security.DACL_SECURITY_INFORMATION, ) all_permissions = dict(self.__sddl_dacl_parse(sddl_string)) keys = all_permissions.keys() acls = "" for key in keys: acls += f"{key}: {all_permissions[key]}\n" final_dict = {"key_path": r_path, "acls": acls, "error": None} return final_dict except Exception as e: error = str(e).lower() if ("find the path specified" in error or "find the file specified" in error or "access is denied" in error or "ace type 9" in error): final_dict = {"key_path": r_path, "acls": None, "error": error} return final_dict elif "no mapping" in error: note = """Possibly VULNERABLE: No mapping between account names and SID's Account used to set GPO may have been removed Account name may be typed incorrectly INFO: https://www.rebeladmin.com/2016/01/how-to-fix-error-no-mapping-between-account-names-and-security-ids-in-active-directory/""" final_dict = {"key_path": r_path, "acls": note, "error": error} return final_dict else: self.__write_error(r_path + "\n" + all_permissions) self.__print_exception() exit(0)
def get_acl_list_procmon(self, path_dict): try: ''' cmd = { "proc_name" : proc_name, "orig_cmd" : orig_cmd, "clean_cmd" : clean_cmd, "operation" : operation, "integrity" : integrity } ''' path_dict = dict(path_dict) r_path = path_dict["clean_cmd"] # Support of HKLM Keys if "hklm" in r_path: try: path = r_path.split(":\\")[1] except: path = r_path.split("hklm\\")[1] # Support for HKCU Keys if "hkcu" in r_path: try: path = r_path.split(":\\")[1] except: path = r_path.split("hkcu\\")[1] key = win32api.RegOpenKey( con.HKEY_LOCAL_MACHINE, path, 0, con.KEY_ENUMERATE_SUB_KEYS | con.KEY_QUERY_VALUE | con.KEY_READ, ) sd = win32api.RegGetKeySecurity( key, win32security.DACL_SECURITY_INFORMATION | win32security.OWNER_SECURITY_INFORMATION, ) dacl = sd.GetSecurityDescriptorDacl() owner_sid = sd.GetSecurityDescriptorOwner() sddl_string = win32security.ConvertSecurityDescriptorToStringSecurityDescriptor( sd, win32security.SDDL_REVISION_1, win32security.DACL_SECURITY_INFORMATION, ) all_permissions = dict(self.sddl_dacl_parse(sddl_string)) keys = all_permissions.keys() acls = "" for key in keys: acls += f"{key}: {all_permissions[key]}\n" data = f""" Process_Name: {path_dict["proc_name"]} Integrity: {path_dict["integrity"]} Operation: {path_dict["operation"]} Original_Cmd: {path_dict["orig_cmd"]} Path: {r_path} Access: {acls} """ self.__write_acl(data) except Exception as e: error = str(e).lower() if ("find the path specified" in error or "find the file specified" in error or "access is denied" in error or "ace type 9" in error): data = f"\nPath: {r_path}\n{str(e)}\n" self.__write_acl(data) pass elif "no mapping" in error: note = """Possibly VULNERABLE: No mapping between account names and SID's Account used to set GPO may have been removed Account name may be typed incorrectly INFO: https://www.rebeladmin.com/2016/01/how-to-fix-error-no-mapping-between-account-names-and-security-ids-in-active-directory/""" data = f"\nPath: {r_path}\n{note}\n" self.__write_acl(data) pass else: print(r_path) self.__write_error(r_path + "\n" + all_permissions) self.__print_exception() exit(0)
def as_string(sd): return win32security.ConvertSecurityDescriptorToStringSecurityDescriptor( sd, win32security.SDDL_REVISION_1, OPTIONS)
import win32security as w32s # ---------------------------------- Some global constants OWNER_SEC_INF = 0x00000001 GROUP_SEC_INF = 0x00000002 DACL_SEC_INF = 0x00000004 SACL_SEC_INF = 0x00000008 LABEL_SEC_INF = 0x00000010 SDDL_REVISION_1 = 1 # ---------------------------------- def Usage(): print(__doc__) sys.exit(0) if len(sys.argv) < 2: Usage() else: PATH = sys.argv[1] sd = w32s.GetFileSecurity(PATH, w32s.DACL_SECURITY_INFORMATION) security_information = OWNER_SEC_INF | GROUP_SEC_INF | DACL_SEC_INF | SACL_SEC_INF ststr = w32s.ConvertSecurityDescriptorToStringSecurityDescriptor( sd, SDDL_REVISION_1, security_information) print(ststr)