Skip to content

Commit cf53c80

Browse files
authored
Merge pull request #38 from cddmp/dev
Update from dev
2 parents e53d125 + 08ebdc4 commit cf53c80

File tree

1 file changed

+27
-81
lines changed

1 file changed

+27
-81
lines changed

enum4linux-ng.py

Lines changed: 27 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)