From fbe9c9f3d98870d488c302cc1784578919980a15 Mon Sep 17 00:00:00 2001 From: XiaoliChan <2209553467@qq.com> Date: Sun, 8 Oct 2023 17:10:04 +0800 Subject: [PATCH] [connection.py] add 'self.port' & improve gethost_addrinfo Signed-off-by: XiaoliChan <2209553467@qq.com> --- nxc/connection.py | 28 ++++++++++++++-------------- nxc/protocols/ftp.py | 9 +++++---- nxc/protocols/ldap.py | 19 ++++++++++--------- nxc/protocols/mssql.py | 5 +++-- nxc/protocols/rdp.py | 7 ++++--- nxc/protocols/smb.py | 17 +++++++++-------- nxc/protocols/ssh.py | 11 ++++++----- nxc/protocols/vnc.py | 5 +++-- nxc/protocols/wmi.py | 5 +++-- 9 files changed, 57 insertions(+), 49 deletions(-) diff --git a/nxc/connection.py b/nxc/connection.py index 2322f8959..b990ae226 100755 --- a/nxc/connection.py +++ b/nxc/connection.py @@ -3,13 +3,12 @@ import random import socket -from socket import AF_INET, AF_INET6, SOCK_DGRAM, IPPROTO_IP, AI_CANONNAME -from socket import getaddrinfo from os.path import isfile from threading import BoundedSemaphore from functools import wraps from time import sleep from ipaddress import ip_address +from socket import AF_UNSPEC, SOCK_DGRAM, IPPROTO_IP, AI_CANONNAME, getaddrinfo from nxc.config import pwned_label from nxc.helpers.logger import highlight @@ -22,17 +21,17 @@ global_failed_logins = 0 user_failed_logins = {} - def gethost_addrinfo(hostname): - try: - for res in getaddrinfo( hostname, None, AF_INET6, SOCK_DGRAM, IPPROTO_IP, AI_CANONNAME): - af, socktype, proto, canonname, sa = res - host = canonname if ip_address(sa[0]).is_link_local else sa[0] - except socket.gaierror: - for res in getaddrinfo( hostname, None, AF_INET, SOCK_DGRAM, IPPROTO_IP, AI_CANONNAME): - af, socktype, proto, canonname, sa = res - host = sa[0] if sa[0] else canonname - return host + is_ipv6 = False + is_link_local_ipv6 = False + for res in getaddrinfo( hostname, None, AF_UNSPEC, SOCK_DGRAM, IPPROTO_IP, AI_CANONNAME): + af, socktype, proto, canonname, sa = res + if ip_address(sa[0]).version == 6: + is_ipv6 = True + host, is_link_local_ipv6 = (canonname, True) if ip_address(sa[0]).is_link_local else (sa[0], False) + else: + host = sa[0] + return host, is_ipv6, is_link_local_ipv6 def requires_admin(func): def _decorator(self, *args, **kwargs): @@ -76,6 +75,7 @@ def __init__(self, args, db, host): self.args = args self.db = db self.hostname = host + self.port = None self.conn = None self.admin_privs = False self.password = "" @@ -89,10 +89,10 @@ def __init__(self, args, db, host): self.logger = nxc_logger try: - self.host = gethost_addrinfo(self.hostname) + self.host, self.is_ipv6, self.is_link_local_ipv6 = gethost_addrinfo(self.hostname) if self.args.kerberos: self.host = self.hostname - self.logger.info(f"Socket info: host={self.host}, hostname={self.hostname}, kerberos={ 'True' if self.args.kerberos else 'False' }") + self.logger.info(f"Socket info: host={self.host}, hostname={self.hostname}, kerberos={ 'True' if self.args.kerberos else 'False' }, ipv6={self.is_ipv6}, link-local ipv6={self.is_link_local_ipv6}") except Exception as e: self.logger.info(f"Error resolving hostname {self.hostname}: {e}") return diff --git a/nxc/protocols/ftp.py b/nxc/protocols/ftp.py index 98dfc7d93..d8995c137 100644 --- a/nxc/protocols/ftp.py +++ b/nxc/protocols/ftp.py @@ -14,11 +14,12 @@ def __init__(self, args, db, host): super().__init__(args, db, host) def proto_logger(self): + self.port = self.args.port self.logger = NXCAdapter( extra={ "protocol": "FTP", "host": self.host, - "port": self.args.port, + "port": self.port, "hostname": self.hostname, } ) @@ -45,7 +46,7 @@ def print_host_info(self): def create_conn_obj(self): self.conn = FTP() try: - self.conn.connect(host=self.host, port=self.args.port) + self.conn.connect(host=self.host, port=self.port) except error_reply: return False except error_temp: @@ -72,8 +73,8 @@ def plaintext_login(self, username, password): # 230 is "User logged in, proceed" response, ftplib raises an exception on failed login if "230" in resp: - self.logger.debug(f"Host: {self.host} Port: {self.args.port}") - self.db.add_host(self.host, self.args.port, self.remote_version) + self.logger.debug(f"Host: {self.host} Port: {self.port}") + self.db.add_host(self.host, self.port, self.remote_version) cred_id = self.db.add_credential(username, password) diff --git a/nxc/protocols/ldap.py b/nxc/protocols/ldap.py index 3bb613a5e..71add1e76 100644 --- a/nxc/protocols/ldap.py +++ b/nxc/protocols/ldap.py @@ -154,18 +154,19 @@ def __init__(self, args, db, host): def proto_logger(self): # self.logger = nxc_logger + self.port = self.args.port self.logger = NXCAdapter( extra={ "protocol": "LDAP", "host": self.host, - "port": self.args.port, + "port": self.port, "hostname": self.hostname, } ) def get_ldap_info(self, host): try: - proto = "ldaps" if (self.args.gmsa or self.args.port == 636) else "ldap" + proto = "ldaps" if (self.args.gmsa or self.port == 636) else "ldap" ldap_url = f"{proto}://{host}" self.logger.info(f"Connecting to {ldap_url} with no baseDN") try: @@ -360,7 +361,7 @@ def kerberos_login( try: # Connect to LDAP - proto = "ldaps" if (self.args.gmsa or self.args.port == 636) else "ldap" + proto = "ldaps" if (self.args.gmsa or self.port == 636) else "ldap" ldap_url = f"{proto}://{self.target}" self.logger.info(f"Connecting to {ldap_url} - {self.baseDN} [1]") self.ldapConnection = ldap_impacket.LDAPConnection(ldap_url, self.baseDN) @@ -386,7 +387,7 @@ def kerberos_login( # out = f"{domain}\\{self.username}{' from ccache' if useCache else ':%s' % (kerb_pass if not self.config.get('nxc', 'audit_mode') else self.config.get('nxc', 'audit_mode') * 8)} {highlight('({})'.format(self.config.get('nxc', 'pwn3d_label')) if self.admin_privs else '')}" self.logger.extra["protocol"] = "LDAP" - self.logger.extra["port"] = "636" if (self.args.gmsa or self.args.port == 636) else "389" + self.logger.extra["port"] = "636" if (self.args.gmsa or self.port == 636) else "389" self.logger.success(out) if not self.args.local_auth: @@ -484,7 +485,7 @@ def plaintext_login(self, domain, username, password): try: # Connect to LDAP - proto = "ldaps" if (self.args.gmsa or self.args.port == 636) else "ldap" + proto = "ldaps" if (self.args.gmsa or self.port == 636) else "ldap" ldap_url = f"{proto}://{self.target}" self.logger.debug(f"Connecting to {ldap_url} - {self.baseDN} [3]") self.ldapConnection = ldap_impacket.LDAPConnection(ldap_url, self.baseDN) @@ -495,7 +496,7 @@ def plaintext_login(self, domain, username, password): out = f"{domain}\\{self.username}:{process_secret(self.password)} {self.mark_pwned()}" self.logger.extra["protocol"] = "LDAP" - self.logger.extra["port"] = "636" if (self.args.gmsa or self.args.port == 636) else "389" + self.logger.extra["port"] = "636" if (self.args.gmsa or self.port == 636) else "389" self.logger.success(out) if not self.args.local_auth: @@ -575,7 +576,7 @@ def hash_login(self, domain, username, ntlm_hash): try: # Connect to LDAP - proto = "ldaps" if (self.args.gmsa or self.args.port == 636) else "ldap" + proto = "ldaps" if (self.args.gmsa or self.port == 636) else "ldap" ldaps_url = f"{proto}://{self.target}" self.logger.info(f"Connecting to {ldaps_url} - {self.baseDN}") self.ldapConnection = ldap_impacket.LDAPConnection(ldaps_url, self.baseDN) @@ -585,7 +586,7 @@ def hash_login(self, domain, username, ntlm_hash): # Prepare success credential text out = f"{domain}\\{self.username}:{process_secret(self.nthash)} {self.mark_pwned()}" self.logger.extra["protocol"] = "LDAP" - self.logger.extra["port"] = "636" if (self.args.gmsa or self.args.port == 636) else "389" + self.logger.extra["port"] = "636" if (self.args.gmsa or self.port == 636) else "389" self.logger.success(out) if not self.args.local_auth: @@ -1409,7 +1410,7 @@ def bloodhound(self): self.logger.highlight("Using kerberos auth from ccache") timestamp = datetime.now().strftime("%Y-%m-%d_%H%M%S") + "_" - bloodhound = BloodHound(ad, self.hostname, self.host, self.args.port) + bloodhound = BloodHound(ad, self.hostname, self.host, self.port) bloodhound.connect() bloodhound.run( diff --git a/nxc/protocols/mssql.py b/nxc/protocols/mssql.py index d288e5a34..97d87d59d 100755 --- a/nxc/protocols/mssql.py +++ b/nxc/protocols/mssql.py @@ -50,11 +50,12 @@ def proto_flow(self): self.call_cmd_args() def proto_logger(self): + self.port = self.args.port self.logger = NXCAdapter( extra={ "protocol": "MSSQL", "host": self.host, - "port": self.args.port, + "port": self.port, "hostname": "None", } ) @@ -121,7 +122,7 @@ def print_host_info(self): def create_conn_obj(self): try: - self.conn = tds.MSSQL(self.host, self.args.port) + self.conn = tds.MSSQL(self.host, self.port) self.conn.connect() except socket.error as e: self.logger.debug(f"Error connecting to MSSQL: {e}") diff --git a/nxc/protocols/rdp.py b/nxc/protocols/rdp.py index 1fca17f6f..78b85088b 100644 --- a/nxc/protocols/rdp.py +++ b/nxc/protocols/rdp.py @@ -94,11 +94,12 @@ def __init__(self, args, db, host): # self.call_cmd_args() def proto_logger(self): + self.port = self.args.port self.logger = NXCAdapter( extra={ "protocol": "RDP", "host": self.host, - "port": self.args.port, + "port": self.port, "hostname": self.hostname, } ) @@ -112,7 +113,7 @@ def print_host_info(self): return True def create_conn_obj(self): - self.target = RDPTarget(ip=self.host, domain="FAKE", port=self.args.port, timeout=self.args.rdp_timeout) + self.target = RDPTarget(ip=self.host, domain="FAKE", port=self.port, timeout=self.args.rdp_timeout) self.auth = NTLMCredential(secret="pass", username="user", domain="FAKE", stype=asyauthSecret.PASS) self.check_nla() @@ -154,7 +155,7 @@ def create_conn_obj(self): self.target = RDPTarget( ip=self.host, hostname=self.hostname, - port=self.args.port, + port=self.port, domain=self.domain, dc_ip=self.domain, timeout=self.args.rdp_timeout, diff --git a/nxc/protocols/smb.py b/nxc/protocols/smb.py index 2f1c760fb..1f5d74b1f 100755 --- a/nxc/protocols/smb.py +++ b/nxc/protocols/smb.py @@ -173,11 +173,12 @@ def __init__(self, args, db, host): connection.__init__(self, args, db, host) def proto_logger(self): + self.port = self.args.port self.logger = NXCAdapter( extra={ "protocol": "SMB", "host": self.host, - "port": self.args.port, + "port": self.port, "hostname": self.hostname, } ) @@ -592,7 +593,7 @@ def create_smbv1_conn(self, kdc=""): self.host if not kdc else kdc, self.host if not kdc else kdc, None, - self.args.port, + self.port, preferredDialect=SMB_DIALECT, timeout=self.args.smb_timeout, ) @@ -613,7 +614,7 @@ def create_smbv3_conn(self, kdc=""): self.host if not kdc else kdc, self.host if not kdc else kdc, None, - self.args.port, + self.port, timeout=self.args.smb_timeout, ) self.smbv1 = False @@ -755,7 +756,7 @@ def execute(self, payload=None, get_output=False, methods=None): self.host if not self.kerberos else self.hostname + "." + self.domain, self.smb_share_name, self.conn, - self.args.port, + self.port, self.username, self.password, self.domain, @@ -764,7 +765,7 @@ def execute(self, payload=None, get_output=False, methods=None): self.kdcHost, self.hash, self.args.share, - self.args.port, + self.port, self.logger, self.args.get_output_tries ) @@ -1320,12 +1321,12 @@ def rid_brute(self, max_rid=None): try: full_hostname = self.host if not self.kerberos else self.hostname + "." + self.domain - string_binding = KNOWN_PROTOCOLS[self.args.port]["bindstr"] + string_binding = KNOWN_PROTOCOLS[self.port]["bindstr"] logging.debug(f"StringBinding {string_binding}") rpc_transport = transport.DCERPCTransportFactory(string_binding) - rpc_transport.set_dport(self.args.port) + rpc_transport.set_dport(self.port) - if KNOWN_PROTOCOLS[self.args.port]["set_host"]: + if KNOWN_PROTOCOLS[self.port]["set_host"]: rpc_transport.setRemoteHost(full_hostname) if hasattr(rpc_transport, "set_credentials"): diff --git a/nxc/protocols/ssh.py b/nxc/protocols/ssh.py index d602fdf5b..24b8bf19a 100644 --- a/nxc/protocols/ssh.py +++ b/nxc/protocols/ssh.py @@ -24,11 +24,12 @@ def __init__(self, args, db, host): super().__init__(args, db, host) def proto_logger(self): + self.port = self.args.port self.logger = NXCAdapter( extra={ "protocol": "SSH", "host": self.host, - "port": self.args.port, + "port": self.port, "hostname": self.hostname, } ) @@ -46,14 +47,14 @@ def enum_host_info(self): stdin, stdout, stderr = self.conn.exec_command("uname -r") self.server_os = stdout.read().decode("utf-8") self.logger.debug(f"OS retrieved: {self.server_os}") - self.db.add_host(self.host, self.args.port, self.remote_version, os=self.server_os) + self.db.add_host(self.host, self.port, self.remote_version, os=self.server_os) def create_conn_obj(self): self.conn = paramiko.SSHClient() self.conn.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: - self.conn.connect(self.host, port=self.args.port) + self.conn.connect(self.host, port=self.port) except AuthenticationException: return True except SSHException: @@ -91,7 +92,7 @@ def plaintext_login(self, username, password, private_key=None): self.logger.debug(f"Logging in with key") self.conn.connect( self.host, - port=self.args.port, + port=self.port, username=username, passphrase=password if password != "" else None, pkey=pkey, @@ -118,7 +119,7 @@ def plaintext_login(self, username, password, private_key=None): self.logger.debug(f"Logging in with password") self.conn.connect( self.host, - port=self.args.port, + port=self.port, username=username, password=password, look_for_keys=False, diff --git a/nxc/protocols/vnc.py b/nxc/protocols/vnc.py index 5891b5a6e..fa4ccae8a 100644 --- a/nxc/protocols/vnc.py +++ b/nxc/protocols/vnc.py @@ -39,11 +39,12 @@ def proto_flow(self): self.call_cmd_args() def proto_logger(self): + self.port = self.args.port self.logger = NXCAdapter( extra={ "protocol": "VNC", "host": self.host, - "port": self.args.port, + "port": self.port, "hostname": self.hostname, } ) @@ -53,7 +54,7 @@ def print_host_info(self): def create_conn_obj(self): try: - self.target = RDPTarget(ip=self.host, port=self.args.port) + self.target = RDPTarget(ip=self.host, port=self.port) credential = UniCredential(protocol=asyauthProtocol.PLAIN, stype=asyauthSecret.NONE) self.conn = VNCConnection(target=self.target, credentials=credential, iosettings=self.iosettings) asyncio.run(self.connect_vnc(True)) diff --git a/nxc/protocols/wmi.py b/nxc/protocols/wmi.py index 68330035e..cab4cf9ce 100644 --- a/nxc/protocols/wmi.py +++ b/nxc/protocols/wmi.py @@ -51,16 +51,17 @@ def __init__(self, args, db, host): connection.__init__(self, args, db, host) def proto_logger(self): + self.port = self.args.port self.logger = NXCAdapter(extra={'protocol': 'WMI', 'host': self.host, - 'port': self.args.port, + 'port': self.port, 'hostname': self.hostname}) def create_conn_obj(self): if self.remoteName == '': self.remoteName = self.host try: - rpctansport = transport.DCERPCTransportFactory(r'ncacn_ip_tcp:{0}[{1}]'.format(self.remoteName, str(self.args.port))) + rpctansport = transport.DCERPCTransportFactory(r'ncacn_ip_tcp:{0}[{1}]'.format(self.remoteName, str(self.port))) rpctansport.set_credentials(username="", password="", domain="", lmhash="", nthash="", aesKey="") rpctansport.setRemoteHost(self.host) rpctansport.set_connect_timeout(self.args.rpc_timeout)