From e4b7ea64eb93992bae671c63c8a8449682113917 Mon Sep 17 00:00:00 2001 From: Alexander Neff Date: Thu, 29 Aug 2024 18:58:06 -0400 Subject: [PATCH 1/5] Increase plaintext&hash login speeds, also only evaluate smbv1 at initialisaion --- nxc/connection.py | 1 + nxc/protocols/smb.py | 36 ++++++++++++++++++++++++++---------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/nxc/connection.py b/nxc/connection.py index 2cf587de9..c6d57ad63 100755 --- a/nxc/connection.py +++ b/nxc/connection.py @@ -482,6 +482,7 @@ def try_credentials(self, domain, username, owned, secret, cred_type, data=None) value = jitter[0] if jitter[0] == jitter[1] else random.choice(range(jitter[0], jitter[1])) self.logger.debug(f"Throttle authentications: sleeping {value} second(s)") sleep(value) + with sem: if cred_type == "plaintext": diff --git a/nxc/protocols/smb.py b/nxc/protocols/smb.py index 6a9186701..287d0836d 100755 --- a/nxc/protocols/smb.py +++ b/nxc/protocols/smb.py @@ -309,10 +309,9 @@ def print_host_info(self): return True def kerberos_login(self, domain, username, password="", ntlm_hash="", aesKey="", kdcHost="", useCache=False): - logging.getLogger("impacket").disabled = True # Re-connect since we logged off - self.logger.debug(f"KDC set to: {kdcHost}") self.create_conn_obj() + self.logger.debug(f"KDC set to: {kdcHost}") lmhash = "" nthash = "" @@ -370,9 +369,6 @@ def kerberos_login(self, domain, username, password="", ntlm_hash="", aesKey="", if self.args.continue_on_success and self.signing: with contextlib.suppress(Exception): self.conn.logoff() - - self.create_conn_obj() - return True except SessionKeyDecryptionError: # success for now, since it's a vulnerability - previously was an error @@ -405,7 +401,6 @@ def kerberos_login(self, domain, username, password="", ntlm_hash="", aesKey="", def plaintext_login(self, domain, username, password): # Re-connect since we logged off - self.create_conn_obj() try: self.password = password self.username = username @@ -451,14 +446,15 @@ def plaintext_login(self, domain, username, password): return False except (ConnectionResetError, NetBIOSTimeout, NetBIOSError) as e: self.logger.fail(f"Connection Error: {e}") + self.create_conn_obj() return False except BrokenPipeError: self.logger.fail("Broken Pipe Error while attempting to login") + self.create_conn_obj() return False def hash_login(self, domain, username, ntlm_hash): # Re-connect since we logged off - self.create_conn_obj() lmhash = "" nthash = "" try: @@ -515,12 +511,15 @@ def hash_login(self, domain, username, ntlm_hash): return False except (ConnectionResetError, NetBIOSTimeout, NetBIOSError) as e: self.logger.fail(f"Connection Error: {e}") + self.create_conn_obj() return False except BrokenPipeError: self.logger.fail("Broken Pipe Error while attempting to login") + self.create_conn_obj() return False def create_smbv1_conn(self): + self.logger.debug(f"Creating SMBv1 connection to {self.host}") try: self.conn = SMBConnection( self.remoteName, @@ -538,10 +537,10 @@ def create_smbv1_conn(self): except (Exception, NetBIOSTimeout) as e: self.logger.info(f"Error creating SMBv1 connection to {self.host}: {e}") return False - return True def create_smbv3_conn(self): + self.logger.debug(f"Creating SMBv3 connection to {self.host}") try: self.conn = SMBConnection( self.remoteName, @@ -564,8 +563,25 @@ def create_smbv3_conn(self): return False return True - def create_conn_obj(self): - return bool(self.create_smbv1_conn() or self.create_smbv3_conn()) + def create_conn_obj(self, no_smbv1=False): + """ + Tries to create a connection object to the target host. + On first try, it will try to create a SMBv1 connection. + On further tries, it will remember which SMB version is supported and create a connection object accordingly. + + :param no_smbv1: If True, it will not try to create a SMBv1 connection + """ + # Initial negotiation + if not no_smbv1 and self.smbv1 is None: + self.smbv1 = self.create_smbv1_conn() + if self.smbv1: + return True + else: + return self.create_smbv3_conn() + elif not no_smbv1 and self.smbv1: + return self.create_smbv1_conn() + else: + return self.create_smbv3_conn() def check_if_admin(self): self.logger.debug(f"Checking if user is admin on {self.host}") From 425ad8ea2327db2e47ef9fdf846d7063b63f84e2 Mon Sep 17 00:00:00 2001 From: Alexander Neff Date: Fri, 30 Aug 2024 14:18:14 -0400 Subject: [PATCH 2/5] Remove unnecessary new line --- nxc/connection.py | 1 - 1 file changed, 1 deletion(-) diff --git a/nxc/connection.py b/nxc/connection.py index c6d57ad63..2cf587de9 100755 --- a/nxc/connection.py +++ b/nxc/connection.py @@ -482,7 +482,6 @@ def try_credentials(self, domain, username, owned, secret, cred_type, data=None) value = jitter[0] if jitter[0] == jitter[1] else random.choice(range(jitter[0], jitter[1])) self.logger.debug(f"Throttle authentications: sleeping {value} second(s)") sleep(value) - with sem: if cred_type == "plaintext": From cafa670113b0c5a5767b83f993e064caf50de068 Mon Sep 17 00:00:00 2001 From: Alexander Neff Date: Sun, 1 Sep 2024 07:28:02 -0400 Subject: [PATCH 3/5] Create new connection object if we want to log in --- nxc/protocols/smb.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nxc/protocols/smb.py b/nxc/protocols/smb.py index 287d0836d..4b83d242f 100755 --- a/nxc/protocols/smb.py +++ b/nxc/protocols/smb.py @@ -302,6 +302,10 @@ def enum_host_info(self): self.kdcHost = result["host"] if result else None self.logger.info(f"Resolved domain: {self.domain} with dns, kdcHost: {self.kdcHost}") + # If we want to authenticate we should create another connection object, because we already logged in + if self.args.username or self.args.cred_id or self.kerberos: + self.create_conn_obj() + def print_host_info(self): signing = colored(f"signing:{self.signing}", host_info_colors[0], attrs=["bold"]) if self.signing else colored(f"signing:{self.signing}", host_info_colors[1], attrs=["bold"]) smbv1 = colored(f"SMBv1:{self.smbv1}", host_info_colors[2], attrs=["bold"]) if self.smbv1 else colored(f"SMBv1:{self.smbv1}", host_info_colors[3], attrs=["bold"]) From 7070305e6c122622fb8c39e1548d8e00b6733f2a Mon Sep 17 00:00:00 2001 From: Alexander Neff Date: Sun, 1 Sep 2024 07:28:30 -0400 Subject: [PATCH 4/5] Add faster login for kerberos --- nxc/protocols/smb.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nxc/protocols/smb.py b/nxc/protocols/smb.py index 4b83d242f..8b6a5ec9b 100755 --- a/nxc/protocols/smb.py +++ b/nxc/protocols/smb.py @@ -313,8 +313,6 @@ def print_host_info(self): return True def kerberos_login(self, domain, username, password="", ntlm_hash="", aesKey="", kdcHost="", useCache=False): - # Re-connect since we logged off - self.create_conn_obj() self.logger.debug(f"KDC set to: {kdcHost}") lmhash = "" nthash = "" @@ -373,6 +371,7 @@ def kerberos_login(self, domain, username, password="", ntlm_hash="", aesKey="", if self.args.continue_on_success and self.signing: with contextlib.suppress(Exception): self.conn.logoff() + self.create_conn_obj() return True except SessionKeyDecryptionError: # success for now, since it's a vulnerability - previously was an error From 85b2b6e0840be816d1471e18745f82977cb24314 Mon Sep 17 00:00:00 2001 From: Alexander Neff Date: Fri, 4 Oct 2024 16:11:02 -0400 Subject: [PATCH 5/5] Add --use-kcache to commands that require a new conn object --- nxc/protocols/smb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nxc/protocols/smb.py b/nxc/protocols/smb.py index 8b6a5ec9b..ed5c4378d 100755 --- a/nxc/protocols/smb.py +++ b/nxc/protocols/smb.py @@ -303,7 +303,7 @@ def enum_host_info(self): self.logger.info(f"Resolved domain: {self.domain} with dns, kdcHost: {self.kdcHost}") # If we want to authenticate we should create another connection object, because we already logged in - if self.args.username or self.args.cred_id or self.kerberos: + if self.args.username or self.args.cred_id or self.kerberos or self.args.use_kcache: self.create_conn_obj() def print_host_info(self):