From dc1436b325198c554627d856e99eb5d348a3bd9e Mon Sep 17 00:00:00 2001 From: Adrian Date: Mon, 25 Nov 2024 08:18:01 +0100 Subject: [PATCH 1/2] ldap: Add option to specify custom port --- impacket/ldap/ldap.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/impacket/ldap/ldap.py b/impacket/ldap/ldap.py index 73b638066d..39c9f1b021 100644 --- a/impacket/ldap/ldap.py +++ b/impacket/ldap/ldap.py @@ -68,7 +68,7 @@ class LDAPConnection: - def __init__(self, url, baseDN='', dstIp=None): + def __init__(self, url, baseDN='', dstIp=None, dstPort=None): """ LDAPConnection class @@ -85,16 +85,21 @@ def __init__(self, url, baseDN='', dstIp=None): self._baseDN = baseDN self._dstIp = dstIp + if dstPort is not None and not dstPort.isdigit(): + raise LDAPSessionError(errorString="Port is not a valid port: '%s'" % dstPort) + if dstPort is not None and 0 < int(dstPort) < 65535: + raise LDAPSessionError(errorString="Port is not in valid port range: '%s'" % dstPort) + if url.startswith('ldap://'): - self._dstPort = 389 + self._dstPort = 389 if dstPort is None else int(dstPort) self._SSL = False self._dstHost = url[7:] elif url.startswith('ldaps://'): - self._dstPort = 636 + self._dstPort = 636 if dstPort is None else int(dstPort) self._SSL = True self._dstHost = url[8:] elif url.startswith('gc://'): - self._dstPort = 3268 + self._dstPort = 3268 if dstPort is None else int(dstPort) self._SSL = False self._dstHost = url[5:] else: From c263d02b801629c2edd7b506365079ef402bad68 Mon Sep 17 00:00:00 2001 From: Adrian Date: Mon, 25 Nov 2024 08:19:41 +0100 Subject: [PATCH 2/2] examples: implement ldap custom port change --- examples/GetADComputers.py | 8 ++++++-- examples/GetADUsers.py | 7 +++++-- examples/GetLAPSPassword.py | 9 ++++++--- examples/GetNPUsers.py | 7 +++++-- examples/GetUserSPNs.py | 7 +++++-- examples/changepasswd.py | 6 +++++- examples/findDelegation.py | 7 +++++-- examples/secretsdump.py | 7 +++++-- 8 files changed, 42 insertions(+), 16 deletions(-) diff --git a/examples/GetADComputers.py b/examples/GetADComputers.py index 2ed1b5dd5d..fa8610f895 100644 --- a/examples/GetADComputers.py +++ b/examples/GetADComputers.py @@ -56,6 +56,7 @@ def __init__(self, username, password, domain, cmdLineOptions): self.__doKerberos = cmdLineOptions.k #[!] in this script the value of -dc-ip option is self.__kdcIP and the value of -dc-host option is self.__kdcHost self.__kdcIP = cmdLineOptions.dc_ip + self.__kdcPort = cmdLineOptions.dc_port self.__kdcHost = cmdLineOptions.dc_host self.__requestUser = cmdLineOptions.user self.__resolveIP = cmdLineOptions.resolveIP @@ -196,7 +197,7 @@ def run(self): # Connect to LDAP try: - ldapConnection = ldap.LDAPConnection('ldap://%s' % self.__target, self.baseDN, self.__kdcIP) + ldapConnection = ldap.LDAPConnection('ldap://%s:%s' % (self.__target, self.__kdcPort), self.baseDN, self.__kdcIP, self.__kdcPort) if self.__doKerberos is not True: ldapConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: @@ -205,7 +206,7 @@ def run(self): except ldap.LDAPSessionError as e: if str(e).find('strongerAuthRequired') >= 0: # We need to try SSL - ldapConnection = ldap.LDAPConnection('ldaps://%s' % self.__target, self.baseDN, self.__kdcIP) + ldapConnection = ldap.LDAPConnection('ldaps://%s:%s' % (self.__target, self.__kdcPort), self.baseDN, self.__kdcIP, self.__kdcPort) if self.__doKerberos is not True: ldapConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: @@ -267,6 +268,9 @@ def run(self): group.add_argument('-dc-ip', action='store', metavar='ip address', help='IP Address of the domain controller. If ' 'ommited it use the domain part (FQDN) ' 'specified in the target parameter') + + group.add_argument('-dc-port', action='store', metavar='port', help='Port of the domain controller. ' + 'Port used to communicate with the dc, instead of the default port') group.add_argument('-dc-host', action='store', metavar='hostname', help='Hostname of the domain controller to use. ' 'If ommited, the domain part (FQDN) ' 'specified in the account parameter will be used') diff --git a/examples/GetADUsers.py b/examples/GetADUsers.py index 06f9738609..d4a1982c5b 100755 --- a/examples/GetADUsers.py +++ b/examples/GetADUsers.py @@ -53,6 +53,7 @@ def __init__(self, username, password, domain, cmdLineOptions): self.__doKerberos = cmdLineOptions.k #[!] in this script the value of -dc-ip option is self.__kdcIP and the value of -dc-host option is self.__kdcHost self.__kdcIP = cmdLineOptions.dc_ip + self.__kdcPort = cmdLineOptions.dc_port self.__kdcHost = cmdLineOptions.dc_host self.__requestUser = cmdLineOptions.user self.__all = cmdLineOptions.all @@ -149,7 +150,7 @@ def run(self): # Connect to LDAP try: - ldapConnection = ldap.LDAPConnection('ldap://%s' % self.__target, self.baseDN, self.__kdcIP) + ldapConnection = ldap.LDAPConnection('ldap://%s:%s' % (self.__target, self.__kdcPort), self.baseDN, self.__kdcIP, self.__kdcPort) if self.__doKerberos is not True: ldapConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: @@ -158,7 +159,7 @@ def run(self): except ldap.LDAPSessionError as e: if str(e).find('strongerAuthRequired') >= 0: # We need to try SSL - ldapConnection = ldap.LDAPConnection('ldaps://%s' % self.__target, self.baseDN, self.__kdcIP) + ldapConnection = ldap.LDAPConnection('ldaps://%s:%s' % (self.__target, self.__kdcPort), self.baseDN, self.__kdcIP, self.__kdcPort) if self.__doKerberos is not True: ldapConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: @@ -229,6 +230,8 @@ def run(self): group.add_argument('-dc-ip', action='store', metavar='ip address', help='IP Address of the domain controller. If ' 'ommited it use the domain part (FQDN) ' 'specified in the target parameter') + group.add_argument('-dc-port', action='store', metavar='port', help='Port of the domain controller. ' + 'Port used to communicate with the dc, instead of the default port') group.add_argument('-dc-host', action='store', metavar='hostname', help='Hostname of the domain controller to use. ' 'If ommited, the domain part (FQDN) ' 'specified in the account parameter will be used') diff --git a/examples/GetLAPSPassword.py b/examples/GetLAPSPassword.py index 1008b7a50f..9004df1b40 100755 --- a/examples/GetLAPSPassword.py +++ b/examples/GetLAPSPassword.py @@ -76,6 +76,7 @@ def __init__(self, username, password, domain, cmdLineOptions): self.__aesKey = cmdLineOptions.aesKey self.__doKerberos = cmdLineOptions.k self.__kdcIP = cmdLineOptions.dc_ip + self.__kdcPort = cmdLineOptions.dc_port self.__kdcHost = cmdLineOptions.dc_host self.__targetComputer = cmdLineOptions.computer self.__outputFile = cmdLineOptions.outputfile @@ -199,7 +200,7 @@ def run(self): # Connect to LDAP try: - ldapConnection = ldap.LDAPConnection('ldap://%s' % self.__target, self.baseDN, self.__kdcIP) + ldapConnection = ldap.LDAPConnection('ldap://%s:%s' % (self.__target, self.__kdcPort), self.baseDN, self.__kdcIP, self.__kdcPort) if self.__doKerberos is not True: ldapConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: @@ -208,7 +209,7 @@ def run(self): except ldap.LDAPSessionError as e: if str(e).find('strongerAuthRequired') >= 0: # We need to try SSL - ldapConnection = ldap.LDAPConnection('ldaps://%s' % self.__target, self.baseDN, self.__kdcIP) + ldapConnection = ldap.LDAPConnection('ldaps://%s:%s' % (self.__target, self.__kdcPort), self.baseDN, self.__kdcIP, self.__kdcPort) if self.__doKerberos is not True: ldapConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: @@ -326,6 +327,8 @@ def run(self): group.add_argument('-dc-ip', action='store', metavar='ip address', help='IP Address of the domain controller. If ' 'ommited it use the domain part (FQDN) ' 'specified in the target parameter') + group.add_argument('-dc-port', action='store', metavar='port', help='Port of the domain controller. ' + 'Port used to communicate with the dc, instead of the default port') group.add_argument('-dc-host', action='store', metavar='hostname', help='Hostname of the domain controller to use. ' 'If ommited, the domain part (FQDN) ' 'specified in the account parameter will be used') @@ -366,4 +369,4 @@ def run(self): if logging.getLogger().level == logging.DEBUG: import traceback traceback.print_exc() - logging.error(str(e)) \ No newline at end of file + logging.error(str(e)) diff --git a/examples/GetNPUsers.py b/examples/GetNPUsers.py index 3b718f55c7..c45adb4eed 100755 --- a/examples/GetNPUsers.py +++ b/examples/GetNPUsers.py @@ -84,6 +84,7 @@ def __init__(self, username, password, domain, cmdLineOptions): self.__requestTGT = cmdLineOptions.request #[!] in this script the value of -dc-ip option is self.__kdcIP and the value of -dc-host option is self.__kdcHost self.__kdcIP = cmdLineOptions.dc_ip + self.__kdcPort = cmdLineOptions.dc_port self.__kdcHost = cmdLineOptions.dc_host if cmdLineOptions.hashes is not None: self.__lmhash, self.__nthash = cmdLineOptions.hashes.split(':') @@ -256,7 +257,7 @@ def run(self): # Connect to LDAP try: - ldapConnection = ldap.LDAPConnection('ldap://%s' % self.__target, self.baseDN, self.__kdcIP) + ldapConnection = ldap.LDAPConnection('ldap://%s:%s' % (self.__target, self.__kdcPort), self.baseDN, self.__kdcIP, self.__kdcPort) if self.__doKerberos is not True: ldapConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: @@ -265,7 +266,7 @@ def run(self): except ldap.LDAPSessionError as e: if str(e).find('strongerAuthRequired') >= 0: # We need to try SSL - ldapConnection = ldap.LDAPConnection('ldaps://%s' % self.__target, self.baseDN, self.__kdcIP) + ldapConnection = ldap.LDAPConnection('ldaps://%s:%s' % (self.__target, self.__kdcPort), self.baseDN, self.__kdcIP, self.__kdcPort) if self.__doKerberos is not True: ldapConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: @@ -413,6 +414,8 @@ def request_multiple_TGTs(self, usernames): group.add_argument('-dc-ip', action='store', metavar='ip address', help='IP Address of the domain controller. If ' 'ommited it use the domain part (FQDN) ' 'specified in the target parameter') + group.add_argument('-dc-port', action='store', metavar='port', help='Port of the domain controller. ' + 'Port used to communicate with the dc, instead of the default port') group.add_argument('-dc-host', action='store', metavar='hostname', help='Hostname of the domain controller to use. ' 'If ommited, the domain part (FQDN) ' 'specified in the account parameter will be used') diff --git a/examples/GetUserSPNs.py b/examples/GetUserSPNs.py index 5b477345e6..962ebd6d7b 100755 --- a/examples/GetUserSPNs.py +++ b/examples/GetUserSPNs.py @@ -88,6 +88,7 @@ def __init__(self, username, password, user_domain, target_domain, cmdLineOption self.__requestTGS = cmdLineOptions.request # [!] in this script the value of -dc-ip option is self.__kdcIP and the value of -dc-host option is self.__kdcHost self.__kdcIP = cmdLineOptions.dc_ip + self.__kdcPort = cmdLineOptions.dc_port self.__kdcHost = cmdLineOptions.dc_host self.__saveTGS = cmdLineOptions.save self.__requestUser = cmdLineOptions.request_user @@ -269,7 +270,7 @@ def run(self): # Connect to LDAP try: - ldapConnection = ldap.LDAPConnection('ldap://%s' % self.__target, self.baseDN, self.__kdcIP) + ldapConnection = ldap.LDAPConnection('ldap://%s:%s' % (self.__target, self.__kdcPort), self.baseDN, self.__kdcIP, self.__kdcPort) if self.__doKerberos is not True: ldapConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: @@ -279,7 +280,7 @@ def run(self): except ldap.LDAPSessionError as e: if str(e).find('strongerAuthRequired') >= 0: # We need to try SSL - ldapConnection = ldap.LDAPConnection('ldaps://%s' % self.__target, self.baseDN, self.__kdcIP) + ldapConnection = ldap.LDAPConnection('ldaps://%s:%s' % (self.__target, self.__kdcPort), self.baseDN, self.__kdcIP, self.__kdcPort) if self.__doKerberos is not True: ldapConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: @@ -525,6 +526,8 @@ def request_multiple_TGSs(self, usernames): 'ommited it use the domain part (FQDN) ' 'specified in the target parameter. Ignored' 'if -target-domain is specified.') + group.add_argument('-dc-port', action='store', metavar='port', help='Port of the domain controller. ' + 'Port used to communicate with the dc, instead of the default port') group.add_argument('-dc-host', action='store', metavar='hostname', help='Hostname of the domain controller to use. ' 'If ommited, the domain part (FQDN) ' 'specified in the account parameter will be used') diff --git a/examples/changepasswd.py b/examples/changepasswd.py index d18fcfdca2..322f885bc5 100755 --- a/examples/changepasswd.py +++ b/examples/changepasswd.py @@ -150,6 +150,7 @@ def __init__( doKerberos=False, aesKey="", kdcHost=None, + kdcPort=None, ): """ Instantiate password change or reset with the credentials of the account making the changes. @@ -602,7 +603,7 @@ def connect(self, targetDomain): logging.debug(f"Connecting to {ldapURI} as {self.domain}\\{self.username}") try: - ldapConnection = ldap.LDAPConnection(ldapURI, self.baseDN, self.address) + ldapConnection = ldap.LDAPConnection(ldapURI, self.baseDN, self.address, self.kdcPort) if not self.doKerberos: ldapConnection.login(self.username, self.password, self.domain, self.pwdHashLM, self.pwdHashNT) else: @@ -820,6 +821,8 @@ def parse_args(): "in the target parameter" ), ) + group.add_argument('-dc-port', action='store', metavar='port', help='Port of the domain controller. ' + 'Port used to communicate with the dc, instead of the default port') if len(sys.argv) == 1: parser.print_help() @@ -945,6 +948,7 @@ def parse_args(): doKerberos, options.aesKey, kdcHost=options.dc_ip, + kdcPort=options.dc_port, ) # Attempt the password change/reset diff --git a/examples/findDelegation.py b/examples/findDelegation.py index e194e190f3..b4dd2da868 100755 --- a/examples/findDelegation.py +++ b/examples/findDelegation.py @@ -89,6 +89,7 @@ def __init__(self, username, password, user_domain, target_domain, cmdLineOption self.__doKerberos = cmdLineOptions.k #[!] in this script the value of -dc-ip option is self.__kdcIP and the value of -dc-host option is self.__kdcHost self.__kdcIP = cmdLineOptions.dc_ip + self.__kdcPort = cmdLineOptions.dc_port self.__kdcHost = cmdLineOptions.dc_host if cmdLineOptions.hashes is not None: self.__lmhash, self.__nthash = cmdLineOptions.hashes.split(':') @@ -147,7 +148,7 @@ def run(self): # Connect to LDAP try: - ldapConnection = ldap.LDAPConnection('ldap://%s' % self.__target, self.baseDN, self.__kdcIP) + ldapConnection = ldap.LDAPConnection('ldap://%s:%s' % (self.__target, self.__kdcPort), self.baseDN, self.__kdcIP, self.__kdcPort) if self.__doKerberos is not True: ldapConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: @@ -156,7 +157,7 @@ def run(self): except ldap.LDAPSessionError as e: if str(e).find('strongerAuthRequired') >= 0: # We need to try SSL - ldapConnection = ldap.LDAPConnection('ldaps://%s' % self.__target, self.baseDN, self.__kdcIP) + ldapConnection = ldap.LDAPConnection('ldaps://%s:%s' % (self.__target, self.__kdcPort), self.baseDN, self.__kdcIP, self.__kdcPort) if self.__doKerberos is not True: ldapConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: @@ -300,6 +301,8 @@ def run(self): 'ommited it use the domain part (FQDN) ' 'specified in the target parameter. Ignored' 'if -target-domain is specified.') + group.add_argument('-dc-port', action='store', metavar='port', help='Port of the domain controller. ' + 'Port used to communicate with the dc, instead of the default port') group.add_argument('-dc-host', action='store', metavar='hostname', help='Hostname of the domain controller to use. ' 'If ommited, the domain part (FQDN) ' 'specified in the account parameter will be used') diff --git a/examples/secretsdump.py b/examples/secretsdump.py index 1ab5616ed1..63797b0194 100755 --- a/examples/secretsdump.py +++ b/examples/secretsdump.py @@ -115,6 +115,7 @@ def __init__(self, remoteName, username='', password='', domain='', options=None self.__resumeFileName = options.resumefile self.__canProcessSAMLSA = True self.__kdcHost = options.dc_ip + self.__kdcPort = options.dc_port self.__remoteSSMethod = options.use_remoteSSMethod self.__remoteSSMethodRemoteVolume = options.remoteSS_remote_volume self.__remoteSSMethodDownloadPath = options.remoteSS_local_path @@ -153,7 +154,7 @@ def ldapConnect(self): self.baseDN = self.baseDN[:-1] try: - self.__ldapConnection = LDAPConnection('ldap://%s' % self.__target, self.baseDN, self.__kdcHost) + self.__ldapConnection = LDAPConnection('ldap://%s:%s' % (self.__target, self.__kdcPort), self.baseDN, self.__kdcIP, self.__kdcPort) if self.__doKerberos is not True: self.__ldapConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: @@ -162,7 +163,7 @@ def ldapConnect(self): except LDAPSessionError as e: if str(e).find('strongerAuthRequired') >= 0: # We need to try SSL - self.__ldapConnection = LDAPConnection('ldaps://%s' % self.__target, self.baseDN, self.__kdcHost) + self.__ldapConnection = LDAPConnection('ldaps://%s:%s' % (self.__target, self.__kdcPort), self.baseDN, self.__kdcIP, self.__kdcPort) if self.__doKerberos is not True: self.__ldapConnection.login(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash) else: @@ -457,6 +458,8 @@ def cleanup(self): group = parser.add_argument_group('connection') group.add_argument('-dc-ip', action='store',metavar = "ip address", help='IP Address of the domain controller. If ' 'ommited it use the domain part (FQDN) specified in the target parameter') + group.add_argument('-dc-port', action='store', metavar='port', help='Port of the domain controller. ' + 'Port used to communicate with the dc, instead of the default port') group.add_argument('-target-ip', action='store', metavar="ip address", help='IP Address of the target machine. If omitted it will use whatever was specified as target. ' 'This is useful when target is the NetBIOS name and you cannot resolve it')