@@ -2596,23 +2596,23 @@ 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 )
2599+ smb_conn = SmbConnection (self .target , self .creds )
2600+ smb_conn .login ()
2601+ samr_object = SAMR (smb_conn )
2602+ domains = samr_object .get_domains ()
2603+ # FIXME: Gets policy for BULTIN domain
2604+ domain_handle = samr_object .get_domain_handle (domains [0 ])
26022605
2603- dce , domain_handle = result .retval
2604-
2605- # Password policy
26062606 try :
2607- domain_passwd = samr . DOMAIN_INFORMATION_CLASS . DomainPasswordInformation
2608- result = samr . hSamrQueryInformationDomain2 ( dce , domainHandle = domain_handle , domainInformationClass = domain_passwd )
2607+ result = samr_object . get_domain_password_information ( domain_handle )
2608+
26092609 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' ]))
2610+ policy ["Domain password information" ]["Password history length" ] = result ['PasswordHistoryLength' ] or "None"
2611+ policy ["Domain password information" ]["Minimum password length" ] = result ['MinPasswordLength' ] or "None"
2612+ policy ["Domain password information" ]["Maximum password age" ] = self .policy_to_human (int (result ['MinPasswordAge' ]['LowPart' ]), int (result ['MinPasswordAge' ]['HighPart' ]))
2613+ policy ["Domain password information" ]["Maximum password age" ] = self .policy_to_human (int (result ['MaxPasswordAge' ]['LowPart' ]), int (result ['MaxPasswordAge' ]['HighPart' ]))
26142614 policy ["Domain password information" ]["Password properties" ] = []
2615- pw_prop = result ['Buffer' ][ 'Password' ][ ' PasswordProperties' ]
2615+ pw_prop = result ['PasswordProperties' ]
26162616 for bitmask in DOMAIN_FIELDS :
26172617 if pw_prop & bitmask == bitmask :
26182618 policy ["Domain password information" ]["Password properties" ].append ({DOMAIN_FIELDS [bitmask ]:True })
@@ -2626,89 +2626,32 @@ def enum(self):
26262626
26272627 # Domain lockout
26282628 try :
2629- domain_lockout = samr . DOMAIN_INFORMATION_CLASS . DomainLockoutInformation
2630- result = samr . hSamrQueryInformationDomain2 ( dce , domainHandle = domain_handle , domainInformationClass = domain_lockout )
2629+ result = samr_object . get_domain_lockout_information ( domain_handle )
2630+
26312631 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"
2632+ policy ["Domain lockout information" ]["Lockout observation window" ] = self .policy_to_human (0 , result ['LockoutObservationWindow' ], lockout = True )
2633+ policy ["Domain lockout information" ]["Lockout duration" ] = self .policy_to_human (0 , result ['LockoutDuration' ], lockout = True )
2634+ policy ["Domain lockout information" ]["Lockout threshold" ] = result ['LockoutThreshold' ] or "None"
26352635 except Exception as e :
26362636 nt_status_error = nt_status_error_filter (str (e ))
26372637 if nt_status_error :
2638- return Result (None , f"Could not get domain_lockout policy: { nt_status_error } " )
2638+ return Result (None , f"Could not get domain lockout policy: { nt_status_error } " )
26392639 return Result (None , "Could not get domain lockout policy" )
26402640
26412641 # Domain logoff
26422642 try :
2643- domain_logoff = samr . DOMAIN_INFORMATION_CLASS . DomainLogoffInformation
2644- result = samr . hSamrQueryInformationDomain2 ( dce , domainHandle = domain_handle , domainInformationClass = domain_logoff )
2643+ result = samr_object . get_domain_logoff_information ( domain_handle )
2644+
26452645 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' ])
2646+ policy ["Domain logoff information" ]["Force logoff time" ] = self .policy_to_human (result ['ForceLogoff' ]['LowPart' ], result ['ForceLogoff' ]['HighPart' ])
26472647 except Exception as e :
26482648 nt_status_error = nt_status_error_filter (str (e ))
26492649 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" )
2650+ return Result (None , f"Could not get domain logoff policy: { nt_status_error } " )
2651+ return Result (None , "Could not get domain logoff policy" )
26522652
26532653 return Result (policy , f"Found policy:\n { yamlize (policy )} " )
26542654
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-
27122655 # This function is heavily based on this polenum fork: https://github.com/Wh1t3Fox/polenum
27132656 # The original polenum was written by Richard "deanx" Dean: https://labs.portcullis.co.uk/tools/polenum/
27142657 # All credits to Richard "deanx" Dean and Craig "Wh1t3Fox" West!
0 commit comments