NetExec/cme/protocols/smb/passpol.py

134 lines
5.0 KiB
Python
Raw Normal View History

import sys
import codecs
import logging
from impacket.nt_errors import STATUS_MORE_ENTRIES
from impacket.dcerpc.v5 import transport, samr
from impacket.dcerpc.v5.rpcrt import DCERPCException
from time import strftime, gmtime
class PassPolDump:
KNOWN_PROTOCOLS = {
'139/SMB': (r'ncacn_np:%s[\pipe\samr]', 139),
'445/SMB': (r'ncacn_np:%s[\pipe\samr]', 445),
}
def __init__(self, connection):
self.logger = connection.logger
self.addr = connection.host
self.protocol = connection.args.smb_port
self.username = connection.username
self.password = connection.password
self.domain = connection.domain
self.hash = connection.hash
self.lmhash = ''
self.nthash = ''
self.aesKey = None
self.doKerberos = False
if self.hash is not None:
self.lmhash, self.nthash = self.hash.split(':')
if self.password is None:
self.password = ''
def enum(self):
#logging.info('Retrieving endpoint list from %s' % addr)
entries = []
protodef = PassPolDump.KNOWN_PROTOCOLS['{}/SMB'.format(self.protocol)]
port = protodef[1]
logging.info("Trying protocol %s..." % self.protocol)
rpctransport = transport.SMBTransport(self.addr, port, r'\samr', self.username, self.password, self.domain, self.lmhash, self.nthash, self.aesKey, doKerberos = self.doKerberos)
dce = rpctransport.get_dce_rpc()
dce.connect()
dce.bind(samr.MSRPC_UUID_SAMR)
resp = samr.hSamrConnect(dce)
serverHandle = resp['ServerHandle']
resp = samr.hSamrEnumerateDomainsInSamServer(dce, serverHandle)
domains = resp['Buffer']['Buffer']
resp = samr.hSamrLookupDomainInSamServer(dce, serverHandle, domains[0]['Name'])
resp = samr.hSamrOpenDomain(dce, serverHandle = serverHandle, domainId = resp['DomainId'])
domainHandle = resp['DomainHandle']
self.logger.success('Dumping password policy')
self.get_pass_pol(self.addr, rpctransport, dce, domainHandle)
def convert(self, low, high, no_zero):
if low == 0 and hex(high) == "-0x80000000":
return "Not Set"
if low == 0 and high == 0:
return "None"
if no_zero: # make sure we have a +ve vale for the unsined int
if (low != 0):
high = 0 - (high+1)
else:
high = 0 - (high)
low = 0 - low
tmp = low + (high)*16**8 # convert to 64bit int
tmp *= (1e-7) # convert to seconds
try:
minutes = int(strftime("%M", gmtime(tmp))) # do the conversion to human readable format
except ValueError, e:
return "BAD TIME:"
hours = int(strftime("%H", gmtime(tmp)))
days = int(strftime("%j", gmtime(tmp)))-1
time = ""
if days > 1:
time = str(days) + " days "
elif days == 1:
time = str(days) + " day "
if hours > 1:
time += str(hours) + " hours "
elif hours == 1:
time = str(days) + " hour "
if minutes > 1:
time += str(minutes) + " minutes"
elif minutes == 1:
time = str(days) + " minute "
return time
def get_pass_pol(self, host, rpctransport, dce, domainHandle):
try:
resp = samr.hSamrQueryInformationDomain(dce, domainHandle, samr.DOMAIN_INFORMATION_CLASS.DomainPasswordInformation)
min_pass_len = resp['Buffer']['Password']['MinPasswordLength']
pass_hst_len = resp['Buffer']['Password']['PasswordHistoryLength']
self.logger.highlight('Minimum password length: {}'.format(min_pass_len))
self.logger.highlight('Password history length: {}'.format(pass_hst_len))
max_pass_age = self.convert(resp['Buffer']['Password']['MaxPasswordAge']['LowPart'],
resp['Buffer']['Password']['MaxPasswordAge']['HighPart'],
1)
min_pass_age = self.convert(resp['Buffer']['Password']['MinPasswordAge']['LowPart'],
resp['Buffer']['Password']['MinPasswordAge']['HighPart'],
1)
self.logger.highlight('Maximum password age: {}'.format(max_pass_age))
self.logger.highlight('Minimum password age: {}'.format(min_pass_age))
resp = samr.hSamrQueryInformationDomain2(dce, domainHandle,samr.DOMAIN_INFORMATION_CLASS.DomainLockoutInformation)
lock_threshold = int(resp['Buffer']['Lockout']['LockoutThreshold'])
self.logger.highlight("Account lockout threshold: {}".format(lock_threshold))
lock_duration = None
if lock_threshold != 0: lock_duration = int(resp['Buffer']['Lockout']['LockoutDuration']) / -600000000
self.logger.highlight("Account lockout duration: {}".format(lock_duration))
except Exception as e:
self.logger.error("{}".format(e))