1- import binascii
2- import hashlib
31from json import loads
42from pyasn1 .codec .der import decoder
53from pyasn1_modules import rfc5652
@@ -37,12 +35,13 @@ def __init__(self, host, port, hostname):
3735 def proto_logger (self , host , port , hostname ):
3836 self .logger = NXCAdapter (extra = {"protocol" : "LDAP" , "host" : host , "port" : port , "hostname" : hostname })
3937
40- def kerberos_login (self , domain , username , password = "" , ntlm_hash = "" , aesKey = "" , kdcHost = "" , useCache = False ):
38+ def kerberos_login (self , domain , username , password = "" , ntlm_hash = "" , aesKey = "" , kdcHost = "" , useCache = False , dns_server = "" ):
4139 lmhash = ""
4240 nthash = ""
4341
44- if kdcHost is None :
45- kdcHost = domain
42+ if kdcHost is None or domain not in kdcHost :
43+ self .logger .fail ("Please provide the FQDN of the domain controller with --kdcHost" )
44+ exit (1 )
4645
4746 # This checks to see if we didn't provide the LM Hash
4847 if ntlm_hash and ntlm_hash .find (":" ) != - 1 :
@@ -54,12 +53,13 @@ def kerberos_login(self, domain, username, password="", ntlm_hash="", aesKey="",
5453 baseDN = ""
5554 domainParts = domain .split ("." )
5655 for i in domainParts :
57- baseDN += f"dc ={ i } ,"
56+ baseDN += f"DC ={ i } ,"
5857 # Remove last ','
5958 baseDN = baseDN [:- 1 ]
6059
6160 try :
62- ldap_connection = ldap_impacket .LDAPConnection (f"ldap://{ kdcHost } " , baseDN )
61+ self .logger .info (f"Connecting to ldap://{ kdcHost } - { baseDN } - { domain } [1]" )
62+ ldap_connection = ldap_impacket .LDAPConnection (f"ldap://{ kdcHost } " , baseDN , dns_server if dns_server else domain )
6363 ldap_connection .kerberosLogin (
6464 username ,
6565 password ,
@@ -78,7 +78,7 @@ def kerberos_login(self, domain, username, password="", ntlm_hash="", aesKey="",
7878 if str (e ).find ("strongerAuthRequired" ) >= 0 :
7979 # We need to try SSL
8080 try :
81- ldap_connection = ldap_impacket .LDAPConnection (f"ldaps://{ kdcHost } " , baseDN )
81+ ldap_connection = ldap_impacket .LDAPConnection (f"ldaps://{ kdcHost } " , baseDN , dns_server if dns_server else domain )
8282 ldap_connection .login (
8383 username ,
8484 password ,
@@ -105,18 +105,14 @@ def kerberos_login(self, domain, username, password="", ntlm_hash="", aesKey="",
105105 color = "magenta" if error_code in ldap_error_status else "red" ,
106106 )
107107 return False
108-
109108 except OSError :
110109 self .logger .debug (f"{ domain } \\ { username } :{ password if password else ntlm_hash } { 'Error connecting to the domain, please add option --kdcHost with the FQDN of the domain controller' } " )
111110 return False
112111 except KerberosError as e :
113- self .logger .fail (
114- f"{ domain } \\ { username } :{ password if password else ntlm_hash } { e !s} " ,
115- color = "red" ,
116- )
112+ self .logger .fail (f"{ domain } \\ { username } :{ password if password else ntlm_hash } { e !s} " , color = "red" )
117113 return False
118114
119- def auth_login (self , domain , username , password , ntlm_hash ):
115+ def auth_login (self , domain , username , password , ntlm_hash , dns_server ):
120116 lmhash = ""
121117 nthash = ""
122118
@@ -135,7 +131,7 @@ def auth_login(self, domain, username, password, ntlm_hash):
135131 base_dn = base_dn [:- 1 ]
136132
137133 try :
138- ldap_connection = ldap_impacket .LDAPConnection (f"ldap://{ domain } " , base_dn , domain )
134+ ldap_connection = ldap_impacket .LDAPConnection (f"ldap://{ domain } " , base_dn , dns_server if dns_server else domain )
139135 ldap_connection .login (username , password , domain , lmhash , nthash )
140136
141137 # Connect to LDAP
@@ -148,7 +144,7 @@ def auth_login(self, domain, username, password, ntlm_hash):
148144 if str (e ).find ("strongerAuthRequired" ) >= 0 :
149145 # We need to try SSL
150146 try :
151- ldap_connection = ldap_impacket .LDAPConnection (f"ldaps://{ domain } " , base_dn , domain )
147+ ldap_connection = ldap_impacket .LDAPConnection (f"ldaps://{ domain } " , base_dn , dns_server if dns_server else domain )
152148 ldap_connection .login (username , password , domain , lmhash , nthash )
153149 self .logger .extra ["protocol" ] = "LDAPS"
154150 self .logger .extra ["port" ] = "636"
@@ -173,7 +169,7 @@ def auth_login(self, domain, username, password, ntlm_hash):
173169
174170
175171class LAPSv2Extract :
176- def __init__ (self , data , username , password , domain , ntlm_hash , do_kerberos , kdcHost , port ):
172+ def __init__ (self , data , username , password , domain , ntlm_hash , do_kerberos , kdcHost , port , dns_server ):
177173 if ntlm_hash .find (":" ) != - 1 :
178174 self .lmhash , self .nthash = ntlm_hash .split (":" )
179175 else :
@@ -187,6 +183,7 @@ def __init__(self, data, username, password, domain, ntlm_hash, do_kerberos, kdc
187183 self .do_kerberos = do_kerberos
188184 self .kdcHost = kdcHost
189185 self .logger = None
186+ self .dns_server = dns_server
190187 self .proto_logger (self .domain , port , self .domain )
191188
192189 def proto_logger (self , host , port , hostname ):
@@ -218,7 +215,7 @@ def run(self):
218215 gke = kds_cache [key_id ["RootKeyId" ]]
219216 else :
220217 # Connect on RPC over TCP to MS-GKDI to call opnum 0 GetKey
221- string_binding = hept_map (destHost = self .domain , remoteIf = MSRPC_UUID_GKDI , protocol = "ncacn_ip_tcp" )
218+ string_binding = hept_map (destHost = self .domain if not self . dns_server else self . dns_server , remoteIf = MSRPC_UUID_GKDI , protocol = "ncacn_ip_tcp" )
222219 rpc_transport = transport .DCERPCTransportFactory (string_binding )
223220 if hasattr (rpc_transport , "set_credentials" ):
224221 rpc_transport .set_credentials (username = self .username , password = self .password , domain = self .domain , lmhash = self .lmhash , nthash = self .nthash )
@@ -263,7 +260,7 @@ def run(self):
263260 return plaintext [:- 18 ].decode ("utf-16le" )
264261
265262
266- def laps_search (self , username , password , cred_type , domain ):
263+ def laps_search (self , username , password , cred_type , domain , dns_server ):
267264 prev_protocol = self .logger .extra ["protocol" ]
268265 prev_port = self .logger .extra ["port" ]
269266 self .logger .extra ["protocol" ] = "LDAP"
@@ -274,7 +271,7 @@ def laps_search(self, username, password, cred_type, domain):
274271 if self .kerberos :
275272 if self .kdcHost is None :
276273 self .logger .fail ("Add --kdcHost parameter to use laps with kerberos" )
277- return None , None , None , None
274+ return None , None , None
278275
279276 connection = ldapco .kerberos_login (
280277 domain [0 ],
@@ -283,18 +280,20 @@ def laps_search(self, username, password, cred_type, domain):
283280 password [0 ] if cred_type [0 ] == "hash" else "" ,
284281 kdcHost = self .kdcHost ,
285282 aesKey = self .aesKey ,
283+ dns_server = dns_server
286284 )
287285 else :
288286 connection = ldapco .auth_login (
289287 domain [0 ],
290288 username [0 ] if username else "" ,
291289 password [0 ] if cred_type [0 ] == "plaintext" else "" ,
292290 password [0 ] if cred_type [0 ] == "hash" else "" ,
291+ dns_server
293292 )
294293 if not connection :
295294 self .logger .fail (f"LDAP connection failed with account { username [0 ]} " )
296295
297- return None , None , None , None
296+ return None , None , None
298297
299298 search_filter = "(&(objectCategory=computer)(|(msLAPS-EncryptedPassword=*)(ms-MCS-AdmPwd=*)(msLAPS-Password=*))(name=" + self .hostname + "))"
300299 attributes = [
@@ -325,13 +324,14 @@ def laps_search(self, username, password, cred_type, domain):
325324 password [0 ] if cred_type [0 ] == "hash" else "" ,
326325 self .kerberos ,
327326 self .kdcHost ,
328- 339
327+ 339 ,
328+ dns_server
329329 )
330330 try :
331331 data = d .run ()
332332 except Exception as e :
333333 self .logger .fail (str (e ))
334- return None , None , None , None
334+ return None , None , None
335335 r = loads (data )
336336 msMCSAdmPwd = r ["p" ]
337337 username_laps = r ["n" ]
@@ -346,21 +346,17 @@ def laps_search(self, username, password, cred_type, domain):
346346 self .logger .debug (f"Host: { sAMAccountName :<20} Password: { msMCSAdmPwd } { self .hostname } " )
347347 else :
348348 self .logger .fail (f"msMCSAdmPwd or msLAPS-Password is empty or account cannot read LAPS property for { self .hostname } " )
349- return None , None , None , None
349+ return None , None , None
350350
351351 if msMCSAdmPwd == "" :
352352 self .logger .fail (f"msMCSAdmPwd or msLAPS-Password is empty or account cannot read LAPS property for { self .hostname } " )
353- return None , None , None , None
354-
355- hash_ntlm = None
356- if cred_type [0 ] == "hash" :
357- hash_ntlm = hashlib .new ("md4" , msMCSAdmPwd .encode ("utf-16le" )).digest ()
358- hash_ntlm = binascii .hexlify (hash_ntlm ).decode ()
353+ return None , None , None
359354
360355 username = username_laps if username_laps else self .args .laps
361356 password = msMCSAdmPwd
362357 domain = self .hostname
363358 self .args .local_auth = True
359+ self .args .kerberos = False
364360 self .logger .extra ["protocol" ] = prev_protocol
365361 self .logger .extra ["port" ] = prev_port
366- return username , password , domain , hash_ntlm
362+ return username , password , domain
0 commit comments