@@ -2596,23 +2596,26 @@ def enum(self):
25962596 '''
25972597 policy = {}
25982598
2599- result = self .samr_init ()
2600- if result .retval [0 ] is None or result .retval [1 ] is None :
2601- return Result (None , result .retmsg )
2602-
2603- dce , domain_handle = result .retval
2599+ try :
2600+ smb_conn = SmbConnection (self .target , self .creds )
2601+ smb_conn .login ()
2602+ samr_object = SAMR (smb_conn )
2603+ domains = samr_object .get_domains ()
2604+ # FIXME: Gets policy for domain only, [1] stores the policy for BUILTIN
2605+ domain_handle = samr_object .get_domain_handle (domains [0 ])
2606+ except Exception as e :
2607+ return Result (None , process_impacket_smb_exception (e , self .target ))
26042608
2605- # Password policy
26062609 try :
2607- domain_passwd = samr . DOMAIN_INFORMATION_CLASS . DomainPasswordInformation
2608- result = samr . hSamrQueryInformationDomain2 ( dce , domainHandle = domain_handle , domainInformationClass = domain_passwd )
2610+ result = samr_object . get_domain_password_information ( domain_handle )
2611+
26092612 policy ["Domain password information" ] = {}
2610- policy ["Domain password information" ]["Password history length" ] = result ['Buffer' ][ 'Password' ][ ' PasswordHistoryLength' ] or "None"
2611- policy ["Domain password information" ]["Minimum password length" ] = result ['Buffer' ][ 'Password' ][ ' MinPasswordLength' ] or "None"
2612- policy ["Domain password information" ]["Maximum password age" ] = self .policy_to_human (int (result ['Buffer' ][ 'Password' ][ ' MinPasswordAge' ]['LowPart' ]), int (result [ 'Buffer' ][ 'Password' ] ['MinPasswordAge' ]['HighPart' ]))
2613- policy ["Domain password information" ]["Maximum password age" ] = self .policy_to_human (int (result ['Buffer' ][ 'Password' ][ ' MaxPasswordAge' ]['LowPart' ]), int (result [ 'Buffer' ][ 'Password' ] ['MaxPasswordAge' ]['HighPart' ]))
2613+ policy ["Domain password information" ]["Password history length" ] = result ['PasswordHistoryLength' ] or "None"
2614+ policy ["Domain password information" ]["Minimum password length" ] = result ['MinPasswordLength' ] or "None"
2615+ policy ["Domain password information" ]["Maximum password age" ] = self .policy_to_human (int (result ['MinPasswordAge' ]['LowPart' ]), int (result ['MinPasswordAge' ]['HighPart' ]))
2616+ policy ["Domain password information" ]["Maximum password age" ] = self .policy_to_human (int (result ['MaxPasswordAge' ]['LowPart' ]), int (result ['MaxPasswordAge' ]['HighPart' ]))
26142617 policy ["Domain password information" ]["Password properties" ] = []
2615- pw_prop = result ['Buffer' ][ 'Password' ][ ' PasswordProperties' ]
2618+ pw_prop = result ['PasswordProperties' ]
26162619 for bitmask in DOMAIN_FIELDS :
26172620 if pw_prop & bitmask == bitmask :
26182621 policy ["Domain password information" ]["Password properties" ].append ({DOMAIN_FIELDS [bitmask ]:True })
@@ -2626,89 +2629,32 @@ def enum(self):
26262629
26272630 # Domain lockout
26282631 try :
2629- domain_lockout = samr . DOMAIN_INFORMATION_CLASS . DomainLockoutInformation
2630- result = samr . hSamrQueryInformationDomain2 ( dce , domainHandle = domain_handle , domainInformationClass = domain_lockout )
2632+ result = samr_object . get_domain_lockout_information ( domain_handle )
2633+
26312634 policy ["Domain lockout information" ] = {}
2632- policy ["Domain lockout information" ]["Lockout observation window" ] = self .policy_to_human (0 , result ['Buffer' ][ 'Lockout' ][ ' LockoutObservationWindow' ], lockout = True )
2633- policy ["Domain lockout information" ]["Lockout duration" ] = self .policy_to_human (0 , result ['Buffer' ][ 'Lockout' ][ ' LockoutDuration' ], lockout = True )
2634- policy ["Domain lockout information" ]["Lockout threshold" ] = result ['Buffer' ][ 'Lockout' ][ ' LockoutThreshold' ] or "None"
2635+ policy ["Domain lockout information" ]["Lockout observation window" ] = self .policy_to_human (0 , result ['LockoutObservationWindow' ], lockout = True )
2636+ policy ["Domain lockout information" ]["Lockout duration" ] = self .policy_to_human (0 , result ['LockoutDuration' ], lockout = True )
2637+ policy ["Domain lockout information" ]["Lockout threshold" ] = result ['LockoutThreshold' ] or "None"
26352638 except Exception as e :
26362639 nt_status_error = nt_status_error_filter (str (e ))
26372640 if nt_status_error :
2638- return Result (None , f"Could not get domain_lockout policy: { nt_status_error } " )
2641+ return Result (None , f"Could not get domain lockout policy: { nt_status_error } " )
26392642 return Result (None , "Could not get domain lockout policy" )
26402643
26412644 # Domain logoff
26422645 try :
2643- domain_logoff = samr . DOMAIN_INFORMATION_CLASS . DomainLogoffInformation
2644- result = samr . hSamrQueryInformationDomain2 ( dce , domainHandle = domain_handle , domainInformationClass = domain_logoff )
2646+ result = samr_object . get_domain_logoff_information ( domain_handle )
2647+
26452648 policy ["Domain logoff information" ] = {}
2646- policy ["Domain logoff information" ]["Force logoff time" ] = self .policy_to_human (result ['Buffer' ][ 'Logoff' ][ ' ForceLogoff' ]['LowPart' ], result [ 'Buffer' ][ 'Logoff' ] ['ForceLogoff' ]['HighPart' ])
2649+ policy ["Domain logoff information" ]["Force logoff time" ] = self .policy_to_human (result ['ForceLogoff' ]['LowPart' ], result ['ForceLogoff' ]['HighPart' ])
26472650 except Exception as e :
26482651 nt_status_error = nt_status_error_filter (str (e ))
26492652 if nt_status_error :
2650- return Result (None , f"Could not get domain_lockout policy: { nt_status_error } " )
2651- return Result (None , "Could not get domain lockout policy" )
2653+ return Result (None , f"Could not get domain logoff policy: { nt_status_error } " )
2654+ return Result (None , "Could not get domain logoff policy" )
26522655
26532656 return Result (policy , f"Found policy:\n { yamlize (policy )} " )
26542657
2655- # This function is heavily based on this polenum fork: https://github.com/Wh1t3Fox/polenum
2656- # The original polenum was written by Richard "deanx" Dean: https://labs.portcullis.co.uk/tools/polenum/
2657- # All credits to Richard "deanx" Dean and Craig "Wh1t3Fox" West!
2658- def samr_init (self ):
2659- '''
2660- Tries to connect to the SAMR named pipe and get the domain handle.
2661- '''
2662-
2663- # Take a backup of the environment, in case we modify it for Kerberos
2664- env = os .environ .copy ()
2665- try :
2666- smb_conn = smbconnection .SMBConnection (remoteName = self .target .host , remoteHost = self .target .host , sess_port = self .target .port , timeout = self .target .timeout )
2667- if self .creds .ticket_file :
2668- os .environ ['KRB5CCNAME' ] = self .creds .ticket_file
2669- # Currently we let impacket extract user and domain from the ticket
2670- smb_conn .kerberosLogin ('' , self .creds .pw , domain = '' , useCache = True )
2671- elif self .creds .nthash :
2672- smb_conn .login (self .creds .user , self .creds .pw , domain = self .creds .domain , nthash = self .creds .nthash )
2673- else :
2674- smb_conn .login (self .creds .user , self .creds .pw , self .creds .domain )
2675-
2676- rpctransport = transport .SMBTransport (smb_connection = smb_conn , filename = r'\samr' , remoteName = self .target .host )
2677- dce = DCERPC_v5 (rpctransport )
2678- dce .connect ()
2679- dce .bind (samr .MSRPC_UUID_SAMR )
2680- except Exception as e :
2681- return Result ((None , None ), process_impacket_smb_exception (e , self .target ))
2682- finally :
2683- # Restore environment in any case
2684- os .environ .clear ()
2685- os .environ .update (env )
2686-
2687- try :
2688- resp = samr .hSamrConnect2 (dce )
2689- except Exception as e :
2690- return Result ((None , None ), process_impacket_smb_exception (e , self .target ))
2691-
2692- if resp ['ErrorCode' ] != 0 :
2693- return Result ((None , None ), f"SamrConnect2 call failed on port { self .target .port } /tcp" )
2694-
2695- resp2 = samr .hSamrEnumerateDomainsInSamServer (dce , serverHandle = resp ['ServerHandle' ], enumerationContext = 0 , preferedMaximumLength = 500 )
2696- if resp2 ['ErrorCode' ] != 0 :
2697- return Result ((None , None ), "SamrEnumerateDomainsinSamServer failed" )
2698-
2699- resp3 = samr .hSamrLookupDomainInSamServer (dce , serverHandle = resp ['ServerHandle' ], name = resp2 ['Buffer' ]['Buffer' ][0 ]['Name' ])
2700- if resp3 ['ErrorCode' ] != 0 :
2701- return Result ((None , None ), "SamrLookupDomainInSamServer failed" )
2702-
2703- resp4 = samr .hSamrOpenDomain (dce , serverHandle = resp ['ServerHandle' ], desiredAccess = samr .MAXIMUM_ALLOWED , domainId = resp3 ['DomainId' ])
2704- if resp4 ['ErrorCode' ] != 0 :
2705- return Result ((None , None ), "SamrOpenDomain failed" )
2706-
2707- #domains = resp2['Buffer']['Buffer']
2708- domain_handle = resp4 ['DomainHandle' ]
2709-
2710- return Result ((dce , domain_handle ), "" )
2711-
27122658 # This function is heavily based on this polenum fork: https://github.com/Wh1t3Fox/polenum
27132659 # The original polenum was written by Richard "deanx" Dean: https://labs.portcullis.co.uk/tools/polenum/
27142660 # All credits to Richard "deanx" Dean and Craig "Wh1t3Fox" West!
0 commit comments