@@ -197,13 +197,12 @@ def init_checks(self):
197197 ConfigCheck ('Powershell Execution Policy == "Restricted"' , 'Checks if the Powershell execution policy is set to "Restricted"' , checker_args = [[self , ("HKLM\\ SOFTWARE\\ Microsoft\\ PowerShell\\ 1\\ ShellIds\\ Microsoft.Powershell" , "ExecutionPolicy" , "Restricted\x00 " ), ("HKCU\\ SOFTWARE\\ Microsoft\\ PowerShell\\ 1\\ ShellIds\\ Microsoft.Powershell" , "ExecutionPolicy" , "Restricted\x00 " )]], checker_kwargs = [{"options" : {"KOIfMissing" : False , "lastWins" : True }}]),
198198 ConfigCheck ("Defender service running" , "Checks if defender service is enabled" , checkers = [self .check_defender_service ]),
199199 ConfigCheck ("Defender Tamper Protection enabled" , "Check if Defender Tamper Protection is enabled" , checker_args = [[self , ("HKLM\\ Software\\ Microsoft\\ Windows Defender\\ Features" , "TamperProtection" , 5 )]]),
200- ConfigCheck ("Defender RealTime Monitoring enabled" , "Check if Defender RealTime Monitoring is enabled" , checker_args = [[self , ("HKLM\\ Software\\ Microsoft\\ Windows Defender\\ Real-Time Protection" , "DisableRealtimeMonitoring" , 0 ), ("HKLM\\ Software\\ Policies\\ Microsoft\\ Windows Defender\\ Real-Time Protection" , "DisableRealtimeMonitoring" , 0 )]], checker_kwargs = [{"options" : {"KOIfMissing" : False , "lastWins" : True }}]),
201- ConfigCheck ("Defender IOAV Protection enabled" , "Check if Defender IOAV Protection is enabled" , checker_args = [[self , ("HKLM\\ Software\\ Microsoft\\ Windows Defender\\ Real-Time Protection" , "DisableIOAVProtection" , 0 ), ("HKLM\\ Software\\ Policies\\ Microsoft\\ Windows Defender\\ Real-Time Protection" , "DisableIOAVProtection" , 0 )]], checker_kwargs = [{"options" : {"KOIfMissing" : False , "lastWins" : True }}]),
202- ConfigCheck ("Defender Behaviour Monitoring enabled" , "Check if Defender Behaviour Monitoring is enabled" , checker_args = [[self , ("HKLM\\ Software\\ Microsoft\\ Windows Defender\\ Real-Time Protection" , "DisableBehaviourMonitoring" , 0 ), ("HKLM\\ Software\\ Policies\\ Microsoft\\ Windows Defender\\ Real-Time Protection" , "DisableBehaviourMonitoring" , 0 )]], checker_kwargs = [{"options" : {"KOIfMissing" : False , "lastWins" : True }}]),
203- ConfigCheck ("Defender Script Scanning enabled" , "Check if Defender Script Scanning is enabled" , checker_args = [[self , ("HKLM\\ Software\\ Microsoft\\ Windows Defender\\ Real-Time Protection" , "DisableScriptScanning" , 0 ), ("HKLM\\ SOFTWARE\\ Policies\\ Microsoft\\ Windows Defender\\ Real-Time Protection" , "DisableScriptScanning" , 0 )]], checker_kwargs = [{"options" : {"KOIfMissing" : False , "lastWins" : True }}]),
204- ConfigCheck ("Defender path exlusion path" , "Checks Defender path exlusion" , checkers = [self .check_defender_exclusion_path ]),
205- ConfigCheck ("Defender extension exlusion" , "Checks Defender extension exlusion" , checkers = [self .check_defender_exclusion_extension ])
206-
200+ ConfigCheck ("Defender RealTime Monitoring enabled" , "Check if Defender RealTime Monitoring is enabled" , checkers = [self .check_single_registry_with_policy ], checker_args = [("HKLM\\ Software\\ Microsoft\\ Windows Defender\\ Real-Time Protection" , "HKLM\\ Software\\ Policies\\ Microsoft\\ Windows Defender\\ Real-Time Protection" , "DisableRealtimeMonitoring" , 0 , True )]),
201+ ConfigCheck ("Defender IOAV Protection enabled" , "Check if Defender IOAV Protection is enabled" , checkers = [self .check_single_registry_with_policy ], checker_args = [("HKLM\\ Software\\ Microsoft\\ Windows Defender\\ Real-Time Protection" , "HKLM\\ Software\\ Policies\\ Microsoft\\ Windows Defender\\ Real-Time Protection" , "DisableIOAVProtection" , 0 , True )]),
202+ ConfigCheck ("Defender Behaviour Monitoring enabled" , "Check if Defender Behaviour Monitoring is enabled" , checkers = [self .check_single_registry_with_policy ], checker_args = [("HKLM\\ Software\\ Microsoft\\ Windows Defender\\ Real-Time Protection" , "HKLM\\ Software\\ Policies\\ Microsoft\\ Windows Defender\\ Real-Time Protection" , "DisableBehaviourMonitoring" , 0 , True )]),
203+ ConfigCheck ("Defender Script Scanning enabled" , "Check if Defender Script Scanning is enabled" , checkers = [self .check_single_registry_with_policy ], checker_args = [("HKLM\\ Software\\ Microsoft\\ Windows Defender\\ Real-Time Protection" , "HKLM\\ Software\\ Policies\\ Microsoft\\ Windows Defender\\ Real-Time Protection" , "DisableScriptScanning" , 0 , True )]),
204+ ConfigCheck ("Defender path exlusion path" , "Checks Defender path exlusion" , checkers = [self .check_defender_exclusion ], checker_args = [("HKLM\\ SOFTWARE\\ Policies\\ Microsoft\\ Windows Defender\\ Exclusions\\ Paths" , "HKLM\\ SOFTWARE\\ Microsoft\\ Windows Defender\\ Exclusions\\ Paths" )]),
205+ ConfigCheck ("Defender extension exlusion" , "Checks Defender extension exlusion" , checkers = [self .check_defender_exclusion ], checker_args = [("HKLM\\ SOFTWARE\\ Policies\\ Microsoft\\ Windows Defender\\ Exclusions\\ Extensions" , "HKLM\\ SOFTWARE\\ Microsoft\\ Windows Defender\\ Exclusions\\ Extensions" )])
207206 ]
208207
209208 # Add check to conf_checks table if missing
@@ -256,7 +255,7 @@ def check_config(self):
256255 if host_id is not None :
257256 self .connection .db .add_check_result (host_id , check .check_id , check .ok , ", " .join (check .reasons ).replace ("\x00 " , "" ))
258257
259- def check_registry (self , * specs , options = None ):
258+ def check_registry (self , * specs , options = None , stop_on_error = False ):
260259 """
261260 Perform checks that only require to compare values in the registry with expected values, according to the specs
262261 a spec may be either a 3-tuple: (key name, value name, expected value), or a 4-tuple (key name, value name, expected value, operation), where operation is a function that implements a comparison operator
@@ -274,6 +273,7 @@ def check_registry(self, *specs, options=None):
274273 try :
275274 if len (spec ) == 3 :
276275 (key , value_name , expected_value ) = spec
276+ op = operator .eq
277277 elif len (spec ) == 4 :
278278 (key , value_name , expected_value , op ) = spec
279279 else :
@@ -321,6 +321,9 @@ def check_registry(self, *specs, options=None):
321321 else :
322322 ok = False
323323 reasons .append (f"Error while retrieving value of { key } \\ { value_name } : { value } " )
324+ if stop_on_error :
325+ ok = None
326+ return ok , reasons
324327 continue
325328
326329 if op (value , expected_value ):
@@ -337,6 +340,37 @@ def check_registry(self, *specs, options=None):
337340
338341 return ok , reasons
339342
343+
344+ def check_single_registry_with_policy (self , * spec , options = None ):
345+ """
346+ Perform checks that only require to compare values in the registry with expected values, according to the spec
347+ The spec may be either a 5-tuple: (key name, policy key name, value name, expected value, default result), or a 6-tuple (key name, policy key name, value name, expected value, default result, operation), where operation is a function that implements a comparison operator
348+ """
349+ try :
350+ if len (spec ) == 5 :
351+ (key , policy_key , value_name , expected_value , default_result ) = spec
352+ op = operator .eq
353+ elif len (spec ) == 6 :
354+ (key , policy_key , value_name , expected_value , default_result , op ) = spec
355+ else :
356+ ok = False
357+ reasons = ["Check could not be performed (invalid specification provided)" ]
358+ return ok , reasons
359+ except Exception as e :
360+ ok , reasons = self .module .log .error (f"Check could not be performed. Details: specs={ specs } , dce={ self .dce } , error: { e } " )
361+ return ok , reasons
362+
363+ ok , reasons_p = self .check_registry ((policy_key , value_name , expected_value , op ), stop_on_error = True )
364+ reasons = [f"Policy: [{ ', ' .join (reasons_p )} ]" ]
365+ if ok is not None :
366+ return ok , reasons
367+ ok , reasons_k = self .check_registry ((key , value_name , expected_value , op ), stop_on_error = True )
368+ reasons .append (f"Specific: [{ ', ' .join (reasons_k )} ]" )
369+ if ok is not None :
370+ return ok , reasons
371+
372+ return default_result , reasons
373+
340374 def check_laps (self ):
341375 reasons = []
342376 success = False
@@ -492,41 +526,39 @@ def check_applocker(self):
492526
493527 return success , reasons
494528
495- def check_defender_exclusion_path (self ):
496- key_name = "HKLM\\ SOFTWARE\\ Microsoft\\ Windows Defender\\ Exclusions\\ Paths"
497- values = self .reg_query_value (self .dce , self .connection , key_name , valueName = None , all = True )
498- success = True
499- reasons = []
500- for value_type , value_name , value_data in values :
501- reasons .append (value_name )
502- key_name = "HKLM\\ SOFTWARE\\ Policies\\ Microsoft\\ Windows Defender\\ Exclusions\\ Paths"
529+ def get_exclusions (self , key_name ):
530+ exclusions = []
503531 try :
504532 values = self .reg_query_value (self .dce , self .connection , key_name , valueName = None , all = True )
505533 for value_type , value_name , value_data in values :
506- reasons .append (value_name )
534+ exclusions .append (value_name )
507535 except Exception :
508- self .context .log .debug ("No defender path exclusion policies" )
509-
510- if len (reasons ) > 0 :
511- success = False
536+ self .context .log .debug ("No defender exclusion policies" )
512537
513- return success , reasons
538+ return len (exclusions ), exclusions
539+
540+ def check_defender_exclusion (self , * spec , options = None ):
541+ try :
542+ if len (spec ) == 2 :
543+ (policy_key_name , key_name ) = spec
544+ else :
545+ ok = False
546+ reasons = ["Check could not be performed (invalid specification provided)" ]
547+ return ok , reasons
548+ except Exception as e :
549+ ok , reasons = self .module .log .error (f"Check could not be performed. Details: specs={ specs } , dce={ self .dce } , error: { e } " )
550+ return ok , reasons
514551
515- def check_defender_exclusion_extension (self ):
516- key_name = "HKLM\\ SOFTWARE\\ Microsoft\\ Windows Defender\\ Exclusions\\ Extensions"
517- values = self .reg_query_value (self .dce , self .connection , key_name , valueName = None , all = True )
518- success = True
519552 reasons = []
520- for value_type , value_name , value_data in values :
521- reasons .append (value_name )
522- key_name = "HKLM\\ SOFTWARE\\ Policies\\ Microsoft\\ Windows Defender\\ Exclusions\\ Extensions"
523- try :
524- values = self .reg_query_value (self .dce , self .connection , key_name , valueName = None , all = True )
525- for value_type , value_name , value_data in values :
526- reasons .append (value_name )
527- except Exception :
528- self .context .log .debug ("No defender extension exclusion policies" )
529- if len (reasons ) > 0 :
553+ success = True
554+
555+ count , exclusions_p = self .get_exclusions (policy_key_name )
556+ reasons = [f"Policy: [{ ', ' .join (exclusions_p )} ]" ]
557+ count_k , exclusions_k = self .get_exclusions (key_name )
558+ reasons .append (f"Specific: [{ ', ' .join (exclusions_k )} ]" )
559+ count += count_k
560+
561+ if count > 0 :
530562 success = False
531563
532564 return success , reasons
0 commit comments