Skip to content

Commit 354641f

Browse files
authored
Merge pull request #36 from cddmp/dev
Update from dev
2 parents 880bc9a + 5fbf7a4 commit 354641f

File tree

1 file changed

+150
-19
lines changed

1 file changed

+150
-19
lines changed

enum4linux-ng.py

Lines changed: 150 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,136 @@ def set_domain(self, domain):
477477
def as_dict(self):
478478
return {'credentials':OrderedDict({'auth_method':self.auth_method, 'user':self.user, 'password':self.pw, 'domain':self.domain, 'ticket_file':self.ticket_file, 'nthash':self.nthash, 'random_user':self.random_user})}
479479

480+
class SmbConnection():
481+
def __init__(self, target, creds=Credentials(), dialect=None):
482+
self.target = target
483+
self.creds = creds
484+
self.dialect = dialect
485+
self._conn = None
486+
487+
self.connect()
488+
489+
def connect(self):
490+
self._conn = smbconnection.SMBConnection(self.target.host, self.target.host, sess_port=self.target.port, timeout=self.target.timeout, preferredDialect=self.dialect)
491+
492+
def login(self):
493+
creds = self.creds
494+
495+
# Take a backup of the environment, in case we modify it for Kerberos
496+
env = os.environ.copy()
497+
try:
498+
if creds.ticket_file:
499+
# Currently we let impacket extract user and domain from the ticket
500+
os.environ['KRB5CCNAME'] = creds.ticket_file
501+
self._conn.kerberosLogin('', creds.pw, domain='', useCache=True)
502+
elif creds.nthash:
503+
self._conn.login(creds.user, creds.pw, domain=creds.domain, nthash=creds.nthash)
504+
else:
505+
self._conn.login(creds.user, creds.pw, creds.domain)
506+
except Exception as e:
507+
#FIXME: Might need adjustment
508+
return Result((None, None), process_impacket_smb_exception(e, self.target))
509+
finally:
510+
# Restore environment in any case
511+
os.environ.clear()
512+
os.environ.update(env)
513+
514+
def close(self):
515+
self._conn.close()
516+
517+
def get_dialect(self):
518+
return self._conn.getDialect()
519+
520+
def is_signing_required(self):
521+
return self._conn.isSigningRequired()
522+
523+
def get_raw(self):
524+
return self._conn
525+
526+
def get_server_lanman(self):
527+
return self._conn.getSMBServer().get_server_lanman()
528+
529+
def get_server_os(self):
530+
return self._conn.getSMBServer().get_server_os()
531+
532+
def get_server_os_major(self):
533+
return self._conn.getServerOSMajor()
534+
535+
def get_server_os_minor(self):
536+
return self._conn.getServerOSMinor()
537+
538+
def get_server_os_build(self):
539+
return self._conn.getServerOSBuild()
540+
541+
def get_server_domain(self):
542+
return self._conn.getServerDomain()
543+
544+
def get_server_name(self):
545+
return self._conn.getServerName()
546+
547+
def get_server_dns_hostname(self):
548+
return self._conn.getServerDNSHostName()
549+
550+
def get_server_dns_domainname(self):
551+
return self._conn.getServerDNSDomainName()
552+
553+
class DceRpc():
554+
def __init__(self, smb_conn):
555+
self._smb_conn = smb_conn
556+
self.dce = None
557+
self.filename = None
558+
self.msrpc_uuid = None
559+
560+
if isinstance(self, SAMR):
561+
self.filename = r'\samr'
562+
self.msrpc_uuid = samr.MSRPC_UUID_SAMR
563+
564+
self._connect()
565+
566+
def _connect(self):
567+
rpctransport = transport.SMBTransport(smb_connection=self._smb_conn.get_raw(), filename=self.filename, remoteName=self._smb_conn.target.host)
568+
self.dce = DCERPC_v5(rpctransport)
569+
self.dce.connect()
570+
self.dce.bind(self.msrpc_uuid)
571+
572+
class SAMR(DceRpc):
573+
def __init__(self, smb_conn=None):
574+
super().__init__(smb_conn)
575+
576+
self._server_handle = self._get_server_handle()
577+
578+
def _get_server_handle(self):
579+
resp = samr.hSamrConnect(self.dce)
580+
return resp['ServerHandle']
581+
582+
def get_domains(self):
583+
resp = samr.hSamrEnumerateDomainsInSamServer(self.dce, self._server_handle)
584+
domains = resp['Buffer']['Buffer']
585+
domain_names = []
586+
for domain in domains:
587+
domain_names.append(domain['Name'])
588+
return domain_names
589+
590+
def get_domain_handle(self, domain_name):
591+
resp = samr.hSamrLookupDomainInSamServer(self.dce, self._server_handle, domain_name)
592+
resp = samr.hSamrOpenDomain(self.dce, serverHandle = self._server_handle, domainId = resp['DomainId'])
593+
return resp['DomainHandle']
594+
595+
def get_domain_password_information(self, domain_handle):
596+
resp = samr.hSamrQueryInformationDomain2(self.dce, domainHandle=domain_handle, domainInformationClass=samr.DOMAIN_INFORMATION_CLASS.DomainPasswordInformation)
597+
return resp['Buffer']['Password']
598+
599+
def get_domain_lockout_information(self, domain_handle):
600+
resp = samr.hSamrQueryInformationDomain2(self.dce, domainHandle=domain_handle, domainInformationClass=samr.DOMAIN_INFORMATION_CLASS.DomainLockoutInformation)
601+
return resp['Buffer']['Lockout']
602+
603+
def get_domain_logoff_information(self, domain_handle):
604+
resp = samr.hSamrQueryInformationDomain2(self.dce, domainHandle=domain_handle, domainInformationClass=samr.DOMAIN_INFORMATION_CLASS.DomainLogoffInformation)
605+
return resp['Buffer']['Logoff']
606+
607+
def query_display_information(self, domain_handle):
608+
resp = samr.hSamrQueryDisplayInformation(self.dce, domainHandle=domain_handle)
609+
return resp['Buffer']['UserInformation']['Buffer']
480610

481611
class SambaTool():
482612
'''
@@ -971,7 +1101,7 @@ def check_smb_dialects(self):
9711101
last_supported_dialect = None
9721102
for dialect in smb_dialects:
9731103
try:
974-
smb_conn = smbconnection.SMBConnection(self.target.host, self.target.host, sess_port=self.target.port, timeout=self.target.timeout, preferredDialect=dialect)
1104+
smb_conn = SmbConnection(self.target, dialect=dialect)
9751105
smb_conn.close()
9761106
supported[SMB_DIALECTS[dialect]] = True
9771107
last_supported_dialect = dialect
@@ -990,10 +1120,10 @@ def check_smb_dialects(self):
9901120
preferred_dialect = last_supported_dialect
9911121

9921122
try:
993-
smb_conn = smbconnection.SMBConnection(self.target.host, self.target.host, sess_port=self.target.port, timeout=self.target.timeout, preferredDialect=preferred_dialect)
994-
preferred_dialect = smb_conn.getDialect()
1123+
smb_conn = SmbConnection(self.target, dialect=preferred_dialect)
1124+
preferred_dialect = smb_conn.get_dialect()
9951125
# Check whether SMB signing is required or optional - since this seems to be a global setting, we check it only for the preferred dialect
996-
output["SMB signing required"] = smb_conn.isSigningRequired()
1126+
output["SMB signing required"] = smb_conn.is_signing_required()
9971127
smb_conn.close()
9981128

9991129
output["Preferred dialect"] = SMB_DIALECTS[preferred_dialect]
@@ -1286,8 +1416,8 @@ def enum_from_smb(self):
12861416

12871417
smb_conn = None
12881418
try:
1289-
smb_conn = smbconnection.SMBConnection(remoteName=self.target.host, remoteHost=self.target.host, sess_port=self.target.port, timeout=self.target.timeout, preferredDialect=self.target.smb_preferred_dialect)
1290-
smb_conn.login("", "", "")
1419+
smb_conn = SmbConnection(self.target, Credentials(), dialect=self.target.smb_preferred_dialect)
1420+
smb_conn.login()
12911421
except Exception as e:
12921422
error_msg = process_impacket_smb_exception(e, self.target)
12931423
# STATUS_ACCESS_DENIED is the only error we can safely ignore. It basically tells us that a
@@ -1298,10 +1428,10 @@ def enum_from_smb(self):
12981428
# For SMBv1 we can typically find Domain in the "Session Setup AndX Response" packet.
12991429
# For SMBv2 and later we find additional information like the DNS name and the DNS FQDN.
13001430
try:
1301-
smb_domain_info["NetBIOS domain name"] = smb_conn.getServerDomain()
1302-
smb_domain_info["NetBIOS computer name"] = smb_conn.getServerName()
1303-
smb_domain_info["FQDN"] = smb_conn.getServerDNSHostName().rstrip('\x00')
1304-
smb_domain_info["DNS domain"] = smb_conn.getServerDNSDomainName().rstrip('\x00')
1431+
smb_domain_info["NetBIOS domain name"] = smb_conn.get_server_domain()
1432+
smb_domain_info["NetBIOS computer name"] = smb_conn.get_server_name()
1433+
smb_domain_info["FQDN"] = smb_conn.get_server_dns_hostname().rstrip('\x00')
1434+
smb_domain_info["DNS domain"] = smb_conn.get_server_dns_domainname().rstrip('\x00')
13051435
except:
13061436
pass
13071437

@@ -1591,8 +1721,8 @@ def enum_from_smb(self):
15911721
if self.target.smb1_supported:
15921722
smb_conn = None
15931723
try:
1594-
smb_conn = smbconnection.SMBConnection(remoteName=self.target.host, remoteHost=self.target.host, sess_port=self.target.port, timeout=self.target.timeout, preferredDialect=SMB_DIALECT)
1595-
smb_conn.login("", "", "")
1724+
smb_conn = SmbConnection(self.target, dialect=SMB_DIALECT)
1725+
smb_conn.login()
15961726
except Exception as e:
15971727
error_msg = process_impacket_smb_exception(e, self.target)
15981728
if not "STATUS_ACCESS_DENIED" in error_msg:
@@ -1603,11 +1733,11 @@ def enum_from_smb(self):
16031733
os_info["OS release"] = "not supported"
16041734

16051735
try:
1606-
native_lanman = smb_conn.getSMBServer().get_server_lanman()
1736+
native_lanman = smb_conn.get_server_lanman()
16071737
if native_lanman:
16081738
os_info["Native LAN manager"] = f"{native_lanman}"
16091739

1610-
native_os = smb_conn.getSMBServer().get_server_os()
1740+
native_os = smb_conn.get_server_os()
16111741
if native_os:
16121742
os_info["Native OS"] = f"{native_os}"
16131743
match = re.search(r"Windows ([0-9])\.([0-9])", native_os)
@@ -1623,8 +1753,8 @@ def enum_from_smb(self):
16231753
if not self.target.smb1_only:
16241754
smb_conn = None
16251755
try:
1626-
smb_conn = smbconnection.SMBConnection(remoteName=self.target.host, remoteHost=self.target.host, sess_port=self.target.port, timeout=self.target.timeout, preferredDialect=self.target.smb_preferred_dialect)
1627-
smb_conn.login("", "", "")
1756+
smb_conn = SmbConnection(self.target, dialect=self.target.smb_preferred_dialect)
1757+
smb_conn.login()
16281758
except Exception as e:
16291759
error_msg = process_impacket_smb_exception(e, self.target)
16301760
if not "STATUS_ACCESS_DENIED" in error_msg:
@@ -1635,13 +1765,13 @@ def enum_from_smb(self):
16351765
os_info["Native OS"] = "not supported"
16361766

16371767
try:
1638-
os_major = smb_conn.getServerOSMajor()
1639-
os_minor = smb_conn.getServerOSMinor()
1768+
os_major = smb_conn.get_server_os_major()
1769+
os_minor = smb_conn.get_server_os_minor()
16401770
except:
16411771
pass
16421772

16431773
try:
1644-
os_build = smb_conn.getServerOSBuild()
1774+
os_build = smb_conn.get_server_os_build()
16451775
if os_build is not None:
16461776
os_info["OS build"] = f"{os_build}"
16471777
if str(os_build) in OS_RELEASE:
@@ -2350,6 +2480,7 @@ def check_access(self, share):
23502480
return Result({"mapping":"denied", "listing":"n/a"}, "Mapping: DENIED, Listing: N/A")
23512481

23522482
if "NT_STATUS_INVALID_INFO_CLASS" in result.retmsg\
2483+
or "NT_STATUS_CONNECTION_REFUSED listing" in result.retmsg\
23532484
or "NT_STATUS_NETWORK_ACCESS_DENIED" in result.retmsg\
23542485
or "NT_STATUS_NOT_A_DIRECTORY" in result.retmsg\
23552486
or "NT_STATUS_NO_SUCH_FILE" in result.retmsg:

0 commit comments

Comments
 (0)