def getData(self): credentials = pack('B', 0xa1) credentials += asn1encode( pack('B', ASN1_OCTET_STRING) + asn1encode(self['credentials'])) ans = pack('B', ASN1_SEQUENCE) ans += asn1encode( pack('B', 0xa0) + asn1encode( pack('B', 0x02) + asn1encode(pack('B', self['credType']))) + credentials) return ans
def getData(self): # Let's pack the credentials field credentials = pack('B',0xa1) credentials += asn1encode(pack('B',ASN1_OCTET_STRING) + asn1encode(self['credentials'])) ans = pack('B',ASN1_SEQUENCE) ans += asn1encode( pack('B', 0xa0) + asn1encode( pack('B', 0x02) + asn1encode( pack('B', self['credType']))) + credentials) return ans
def getData(self): # Let's pack the credentials field credentials = pack('B',0xa1) credentials += asn1encode(pack('B',ASN1_OCTET_STRING) + asn1encode(self['credentials'])) asn = pack('B',ASN1_SEQUENCE) asn += asn1encode( pack('B', 0xa0) + asn1encode( pack('B', 0x02) + asn1encode( pack('B', self['credType']))) + credentials) return asn
def getPubKey(): cert = open("./server.crt",'r') crt = crypto.load_certificate(crypto.FILETYPE_PEM,cert.read()) pubkeyObj = crt.get_pubkey() pubkeyStr = crypto.dump_privatekey(crypto.FILETYPE_ASN1,pubkeyObj) pubkeyStr = pubkeyStr[7:] pubkeyStr = b'\x30' + asn1encode(pubkeyStr) return pubkeyStr
def getData(self): ans = pack('B', ASN1_SEQUENCE) ans += asn1encode( pack('B', 0xa0) + asn1encode( pack('B', ASN1_OCTET_STRING) + asn1encode( self['domainName'].encode('utf-16le'))) + pack('B', 0xa1) + asn1encode( pack('B', ASN1_OCTET_STRING) + asn1encode( self['userName'].encode('utf-16le'))) + pack('B', 0xa2) + asn1encode( pack('B', ASN1_OCTET_STRING) + asn1encode( self['password'].encode('utf-16le'))) ) return ans
def check_rdp(host, username, password, domain, hashes=None): if hashes is not None: lmhash, nthash = hashes.split(':') lmhash = a2b_hex(lmhash) nthash = a2b_hex(nthash) else: lmhash = '' nthash = '' tpkt = TPKT() tpdu = TPDU() rdp_neg = RDP_NEG_REQ() rdp_neg['Type'] = TYPE_RDP_NEG_REQ rdp_neg['requestedProtocols'] = PROTOCOL_HYBRID | PROTOCOL_SSL tpdu['VariablePart'] = rdp_neg.getData() tpdu['Code'] = TDPU_CONNECTION_REQUEST tpkt['TPDU'] = tpdu.getData() s = socket.socket() s.connect((host, 3389)) #port default s.sendall(tpkt.getData()) pkt = s.recv(8192) tpkt.fromString(pkt) tpdu.fromString(tpkt['TPDU']) cr_tpdu = CR_TPDU(tpdu['VariablePart']) if cr_tpdu['Type'] == TYPE_RDP_NEG_FAILURE: rdp_failure = RDP_NEG_FAILURE(tpdu['VariablePart']) rdp_failure.dump() logging.error( "Server doesn't support PROTOCOL_HYBRID, hence we can't use CredSSP to check credentials" ) return else: rdp_neg.fromString(tpdu['VariablePart']) # Since we were accepted to talk PROTOCOL_HYBRID, below is its implementation # 1. The CredSSP client and CredSSP server first complete the TLS handshake, # as specified in [RFC2246]. After the handshake is complete, all subsequent # CredSSP Protocol messages are encrypted by the TLS channel. # The CredSSP Protocol does not extend the TLS wire protocol. As part of the TLS # handshake, the CredSSP server does not request the client's X.509 certificate # (thus far, the client is anonymous). Also, the CredSSP Protocol does not require # the client to have a commonly trusted certification authority root with the # CredSSP server. Thus, the CredSSP server MAY use, for example, # a self-signed X.509 certificate. # Switching to TLS now ctx = SSL.Context(SSL.TLSv1_2_METHOD) ctx.set_cipher_list(b'RC4,AES') tls = SSL.Connection(ctx, s) tls.set_connect_state() tls.do_handshake() # If you want to use Python internal ssl, uncomment this and comment # the previous lines #tls = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1, ciphers='RC4') # 2. Over the encrypted TLS channel, the SPNEGO handshake between the client # and server completes mutual authentication and establishes an encryption key # that is used by the SPNEGO confidentiality services, as specified in [RFC4178]. # All SPNEGO tokens as well as the underlying encryption algorithms are opaque to # the calling application (the CredSSP client and CredSSP server). # The wire protocol for SPNEGO is specified in [MS-SPNG]. # The SPNEGO tokens exchanged between the client and the server are encapsulated # in the negoTokens field of the TSRequest structure. Both the client and the # server use this structure as many times as necessary to complete the SPNEGO # exchange.<9> # # Note During this phase of the protocol, the OPTIONAL authInfo field is omitted # from the TSRequest structure by the client and server; the OPTIONAL pubKeyAuth # field is omitted by the client unless the client is sending the last SPNEGO token. # If the client is sending the last SPNEGO token, the TSRequest structure MUST have # both the negoToken and the pubKeyAuth fields filled in. # NTLMSSP stuff auth = ntlm.getNTLMSSPType1('', '', True, use_ntlmv2=True) ts_request = TSRequest() ts_request['NegoData'] = auth.getData() tls.send(ts_request.getData()) buff = tls.recv(4096) ts_request.fromString(buff) # 3. The client encrypts the public key it received from the server (contained # in the X.509 certificate) in the TLS handshake from step 1, by using the # confidentiality support of SPNEGO. The public key that is encrypted is the # ASN.1-encoded SubjectPublicKey sub-field of SubjectPublicKeyInfo from the X.509 # certificate, as specified in [RFC3280] section 4.1. The encrypted key is # encapsulated in the pubKeyAuth field of the TSRequest structure and is sent over # the TLS channel to the server. # # Note During this phase of the protocol, the OPTIONAL authInfo field is omitted # from the TSRequest structure; the client MUST send its last SPNEGO token to the # server in the negoTokens field (see step 2) along with the encrypted public key # in the pubKeyAuth field. # Last SPNEGO token calculation #ntlmChallenge = ntlm.NTLMAuthChallenge(ts_request['NegoData']) type3, exportedSessionKey = ntlm.getNTLMSSPType3( auth, ts_request['NegoData'], username, password, domain, lmhash, nthash, use_ntlmv2=True) # Get server public key server_cert = tls.get_peer_certificate() pkey = server_cert.get_pubkey() dump = crypto.dump_privatekey(crypto.FILETYPE_ASN1, pkey) # Fix up due to PyOpenSSL lack for exporting public keys dump = dump[7:] dump = b'\x30' + asn1encode(dump) cipher = SPNEGOCipher(type3['flags'], exportedSessionKey) signature, cripted_key = cipher.encrypt(dump) ts_request['NegoData'] = type3.getData() ts_request['pubKeyAuth'] = signature.getData() + cripted_key try: # Sending the Type 3 NTLM blob tls.send(ts_request.getData()) # The other end is waiting for the pubKeyAuth field, but looks like it's # not needed to check whether authentication worked. # If auth is unsuccessful, it throws an exception with the previous send(). # If auth is successful, the server waits for the pubKeyAuth and doesn't answer # anything. So, I'm sending garbage so the server returns an error. # Luckily, it's a different error so we can determine whether or not auth worked ;) buff = tls.recv(1024) except Exception as err: if str(err).find("denied") > 0: # logging.error("Access Denied") sys.stdout.write('\r[-] [%s:%s] Access Denied ' % (username, password)) else: logging.error(err) time.sleep(5) return # 4. After the server receives the public key in step 3, it first verifies that # it has the same public key that it used as part of the TLS handshake in step 1. # The server then adds 1 to the first byte representing the public key (the ASN.1 # structure corresponding to the SubjectPublicKey field, as described in step 3) # and encrypts the binary result by using the SPNEGO encryption services. # Due to the addition of 1 to the binary data, and encryption of the data as a binary # structure, the resulting value may not be valid ASN.1-encoded values. # The encrypted binary data is encapsulated in the pubKeyAuth field of the TSRequest # structure and is sent over the encrypted TLS channel to the client. # The addition of 1 to the first byte of the public key is performed so that the # client-generated pubKeyAuth message cannot be replayed back to the client by an # attacker. # # Note During this phase of the protocol, the OPTIONAL authInfo and negoTokens # fields are omitted from the TSRequest structure. ts_request = TSRequest(buff) # Now we're decrypting the certificate + 1 sent by the server. Not worth checking ;) signature, plain_text = cipher.decrypt(ts_request['pubKeyAuth'][16:]) # 5. After the client successfully verifies server authenticity by performing a # binary comparison of the data from step 4 to that of the data representing # the public key from the server's X.509 certificate (as specified in [RFC3280], # section 4.1), it encrypts the user's credentials (either password or smart card # PIN) by using the SPNEGO encryption services. The resulting value is # encapsulated in the authInfo field of the TSRequest structure and sent over # the encrypted TLS channel to the server. # The TSCredentials structure within the authInfo field of the TSRequest # structure MAY contain either a TSPasswordCreds or a TSSmartCardCreds structure, # but MUST NOT contain both. # # Note During this phase of the protocol, the OPTIONAL pubKeyAuth and negoTokens # fields are omitted from the TSRequest structure. tsp = TSPasswordCreds() tsp['domainName'] = domain tsp['userName'] = username tsp['password'] = password tsc = TSCredentials() tsc['credType'] = 1 # TSPasswordCreds tsc['credentials'] = tsp.getData() signature, cripted_creds = cipher.encrypt(tsc.getData()) ts_request = TSRequest() ts_request['authInfo'] = signature.getData() + cripted_creds tls.send(ts_request.getData()) tls.close() # logging.info("\rAccess Granted\n") sys.stdout.write('\r[+] [%s:%s] Access Granted\n' % (username, password)) return True
def check_rdp(host, username, password, domain, hashes=None): if hashes is not None: lmhash, nthash = hashes.split(':') lmhash = a2b_hex(lmhash) nthash = a2b_hex(nthash) else: lmhash = '' nthash = '' tpkt = TPKT() tpdu = TPDU() rdp_neg = RDP_NEG_REQ() rdp_neg['Type'] = TYPE_RDP_NEG_REQ rdp_neg['requestedProtocols'] = PROTOCOL_HYBRID | PROTOCOL_SSL tpdu['VariablePart'] = rdp_neg.getData() tpdu['Code'] = TDPU_CONNECTION_REQUEST tpkt['TPDU'] = tpdu.getData() s = socket.socket() s.connect((host, 3389)) #port default s.sendall(tpkt.getData()) pkt = s.recv(8192) tpkt.fromString(pkt) tpdu.fromString(tpkt['TPDU']) cr_tpdu = CR_TPDU(tpdu['VariablePart']) if cr_tpdu['Type'] == TYPE_RDP_NEG_FAILURE: rdp_failure = RDP_NEG_FAILURE(tpdu['VariablePart']) rdp_failure.dump() logging.error( "Server doesn't support PROTOCOL_HYBRID, hence we can't use CredSSP to check credentials" ) return else: rdp_neg.fromString(tpdu['VariablePart']) ctx = SSL.Context(SSL.TLSv1_2_METHOD) ctx.set_cipher_list(b'RC4,AES') tls = SSL.Connection(ctx, s) tls.set_connect_state() tls.do_handshake() auth = ntlm.getNTLMSSPType1('', '', True, use_ntlmv2=True) ts_request = TSRequest() ts_request['NegoData'] = auth.getData() tls.send(ts_request.getData()) buff = tls.recv(4096) ts_request.fromString(buff) type3, exportedSessionKey = ntlm.getNTLMSSPType3( auth, ts_request['NegoData'], username, password, domain, lmhash, nthash, use_ntlmv2=True) # Get server public key server_cert = tls.get_peer_certificate() pkey = server_cert.get_pubkey() dump = crypto.dump_privatekey(crypto.FILETYPE_ASN1, pkey) # Fix up due to PyOpenSSL lack for exporting public keys dump = dump[7:] dump = b'\x30' + asn1encode(dump) cipher = SPNEGOCipher(type3['flags'], exportedSessionKey) signature, cripted_key = cipher.encrypt(dump) ts_request['NegoData'] = type3.getData() ts_request['pubKeyAuth'] = signature.getData() + cripted_key try: # Sending the Type 3 NTLM blob tls.send(ts_request.getData()) buff = tls.recv(1024) except Exception as err: if str(err).find("denied") > 0: # logging.error("Access Denied") sys.stdout.write('\r[-] [%s:%s:%s] Access Denied ' % (host, username, password)) else: logging.error(err) time.sleep(5) return ts_request = TSRequest(buff) signature, plain_text = cipher.decrypt(ts_request['pubKeyAuth'][16:]) tsp = TSPasswordCreds() tsp['domainName'] = domain tsp['userName'] = username tsp['password'] = password tsc = TSCredentials() tsc['credType'] = 1 # TSPasswordCreds tsc['credentials'] = tsp.getData() signature, cripted_creds = cipher.encrypt(tsc.getData()) ts_request = TSRequest() ts_request['authInfo'] = signature.getData() + cripted_creds tls.send(ts_request.getData()) tls.close() sys.stdout.write( f"\r{colored('[+]', 'green')} {colored('Host:','blue')}{host},{colored('Username:'******'blue')}{username},{colored('Password:'******'blue')}{password},{colored('Domain:','blue')}{domain} [{colored('SUCESS', 'green')}] \n" ) return True
#chkField['Flags'] = GSS_C_INTEG_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DCE_STYLE authenticator['cksum']['checksum'] = chkField.getData() authenticator['seq-number'] = 0 encodedAuthenticator = encoder.encode(authenticator) # Key Usage 11 # AP-REQ Authenticator (includes application authenticator # subkey), encrypted with the application session key # (Section 5.5.1) encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 11, encodedAuthenticator, None) apReq['authenticator'] = noValue apReq['authenticator']['etype'] = cipher.enctype apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator blob['MechToken'] = struct.pack('B', ASN1_AID) + asn1encode( struct.pack('B', ASN1_OID) + asn1encode( TypesMech['KRB5 - Kerberos 5'] ) + KRB5_AP_REQ + encoder.encode(apReq)) return cipher, sessionKey, blob.getData() class KerberosError(SessionError): """ This is the exception every client should catch regardless of the underlying SMB version used. We'll take care of that. NETBIOS exceptions are NOT included, since all SMB versions share the same NETBIOS instances. """ def __init__( self, error = 0, packet=0): SessionError.__init__(self) self.error = error self.packet = packet if packet != 0: self.error = self.packet['error-code']
def check_rdp(host, username, password, domain, hashes = None): if hashes is not None: lmhash, nthash = hashes.split(':') lmhash = a2b_hex(lmhash) nthash = a2b_hex(nthash) else: lmhash = '' nthash = '' tpkt = TPKT() tpdu = TPDU() rdp_neg = RDP_NEG_REQ() rdp_neg['Type'] = TYPE_RDP_NEG_REQ rdp_neg['requestedProtocols'] = PROTOCOL_HYBRID | PROTOCOL_SSL tpdu['VariablePart'] = str(rdp_neg) tpdu['Code'] = TDPU_CONNECTION_REQUEST tpkt['TPDU'] = str(tpdu) s = socket.socket() s.connect((host,3389)) s.sendall(str(tpkt)) pkt = s.recv(8192) tpkt.fromString(pkt) tpdu.fromString(tpkt['TPDU']) cr_tpdu = CR_TPDU(tpdu['VariablePart']) if cr_tpdu['Type'] == TYPE_RDP_NEG_FAILURE: rdp_failure = RDP_NEG_FAILURE(tpdu['VariablePart']) rdp_failure.dump() logging.error("Server doesn't support PROTOCOL_HYBRID, hence we can't use CredSSP to check credentials") return else: rdp_neg.fromString(tpdu['VariablePart']) # Since we were accepted to talk PROTOCOL_HYBRID, below is its implementation # 1. The CredSSP client and CredSSP server first complete the TLS handshake, # as specified in [RFC2246]. After the handshake is complete, all subsequent # CredSSP Protocol messages are encrypted by the TLS channel. # The CredSSP Protocol does not extend the TLS wire protocol. As part of the TLS # handshake, the CredSSP server does not request the client's X.509 certificate # (thus far, the client is anonymous). Also, the CredSSP Protocol does not require # the client to have a commonly trusted certification authority root with the # CredSSP server. Thus, the CredSSP server MAY use, for example, # a self-signed X.509 certificate. # Switching to TLS now ctx = SSL.Context(SSL.TLSv1_METHOD) ctx.set_cipher_list('RC4') tls = SSL.Connection(ctx,s) tls.set_connect_state() tls.do_handshake() # If you want to use Python internal ssl, uncomment this and comment # the previous lines #tls = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1, ciphers='RC4') # 2. Over the encrypted TLS channel, the SPNEGO handshake between the client # and server completes mutual authentication and establishes an encryption key # that is used by the SPNEGO confidentiality services, as specified in [RFC4178]. # All SPNEGO tokens as well as the underlying encryption algorithms are opaque to # the calling application (the CredSSP client and CredSSP server). # The wire protocol for SPNEGO is specified in [MS-SPNG]. # The SPNEGO tokens exchanged between the client and the server are encapsulated # in the negoTokens field of the TSRequest structure. Both the client and the # server use this structure as many times as necessary to complete the SPNEGO # exchange.<9> # # Note During this phase of the protocol, the OPTIONAL authInfo field is omitted # from the TSRequest structure by the client and server; the OPTIONAL pubKeyAuth # field is omitted by the client unless the client is sending the last SPNEGO token. # If the client is sending the last SPNEGO token, the TSRequest structure MUST have # both the negoToken and the pubKeyAuth fields filled in. # NTLMSSP stuff auth = ntlm.getNTLMSSPType1('','',True, use_ntlmv2 = True) ts_request = TSRequest() ts_request['NegoData'] = str(auth) tls.send(ts_request.getData()) buff = tls.recv(4096) ts_request.fromString(buff) # 3. The client encrypts the public key it received from the server (contained # in the X.509 certificate) in the TLS handshake from step 1, by using the # confidentiality support of SPNEGO. The public key that is encrypted is the # ASN.1-encoded SubjectPublicKey sub-field of SubjectPublicKeyInfo from the X.509 # certificate, as specified in [RFC3280] section 4.1. The encrypted key is # encapsulated in the pubKeyAuth field of the TSRequest structure and is sent over # the TLS channel to the server. # # Note During this phase of the protocol, the OPTIONAL authInfo field is omitted # from the TSRequest structure; the client MUST send its last SPNEGO token to the # server in the negoTokens field (see step 2) along with the encrypted public key # in the pubKeyAuth field. # Last SPNEGO token calculation #ntlmChallenge = ntlm.NTLMAuthChallenge(ts_request['NegoData']) type3, exportedSessionKey = ntlm.getNTLMSSPType3(auth, ts_request['NegoData'], username, password, domain, lmhash, nthash, use_ntlmv2 = True) # Get server public key server_cert = tls.get_peer_certificate() pkey = server_cert.get_pubkey() dump = crypto.dump_privatekey(crypto.FILETYPE_ASN1, pkey) # Fix up due to PyOpenSSL lack for exporting public keys dump = dump[7:] dump = '\x30'+ asn1encode(dump) cipher = SPNEGOCipher(type3['flags'], exportedSessionKey) signature, cripted_key = cipher.encrypt(dump) ts_request['NegoData'] = str(type3) ts_request['pubKeyAuth'] = str(signature) + cripted_key try: # Sending the Type 3 NTLM blob tls.send(ts_request.getData()) # The other end is waiting for the pubKeyAuth field, but looks like it's # not needed to check whether authentication worked. # If auth is unsuccessful, it throws an exception with the previous send(). # If auth is successful, the server waits for the pubKeyAuth and doesn't answer # anything. So, I'm sending garbage so the server returns an error. # Luckily, it's a different error so we can determine whether or not auth worked ;) buff = tls.recv(1024) except Exception, err: if str(err).find("denied") > 0: logging.error("Access Denied") else: logging.error(err) return
def clientConnect(host, username, password, domain, connect=True): tpkt = TPKT() tpdu = TPDU() rdp_neg = RDP_NEG_REQ() rdp_neg['Type'] = TYPE_RDP_NEG_REQ rdp_neg[ 'requestedProtocols'] = PROTOCOL_HYBRID_EX | PROTOCOL_HYBRID | PROTOCOL_SSL tpdu['VariablePart'] = rdp_neg.getData() tpdu['Code'] = TDPU_CONNECTION_REQUEST tpkt['TPDU'] = tpdu.getData() s = socket.socket() s.connect((host, 3389)) s.sendall(tpkt.getData()) pkt = s.recv(8192) tpkt.fromString(pkt) tpdu.fromString(tpkt['TPDU']) cr_tpdu = CR_TPDU(tpdu['VariablePart']) if cr_tpdu['Type'] == TYPE_RDP_NEG_FAILURE: rdp_failure = RDP_NEG_FAILURE(tpdu['VariablePart']) rdp_failure.dump() logging.error( "Server doesn't support PROTOCOL_HYBRID, hence we can't use CredSSP to check credentials" ) return else: rdp_neg.fromString(tpdu['VariablePart']) #Here we start the SPNEGO exchange #Step1 : Start the SSL connection ctx = SSL.Context(SSL.TLSv1_2_METHOD) ctx.set_cipher_list('RC4,AES') tls = SSL.Connection(ctx, s) tls.set_connect_state() tls.do_handshake() #Step2: Send the SPNEGO handshake auth = ntlm.getNTLMSSPType1('', '', True, use_ntlmv2=True) ts_request = TSRequest() ts_request['NegoData'] = auth.getData() tls.send(ts_request.getData()) buff = tls.recv(4096) ts_request.fromString(buff) #Step3: We should have an NTLM Challenge. Answer the challenge and sign the server pubkey lmhash = '' nthash = '' type3, exportedSessionKey = ntlm.getNTLMSSPType3(auth, ts_request['NegoData'], username, password, domain, lmhash, nthash, use_ntlmv2=True) # Get server public key server_cert = tls.get_peer_certificate() pkey = server_cert.get_pubkey() dump = crypto.dump_privatekey(crypto.FILETYPE_ASN1, pkey) # Fix up due to PyOpenSSL lack for exporting public keys dump = dump[7:] pubKeyStr = b'\x30' + asn1encode(dump) clientNonce = "A" * 32 magic = b"CredSSP Client-To-Server Binding Hash\x00" h2 = hashlib.sha256() h2.update(magic) h2.update(clientNonce) h2.update(pubKeyStr) cipher = SPNEGOCipher(type3['flags'], exportedSessionKey) signature, cripted_key = cipher.clientEncrypt(h2.digest()) ts_request['NegoData'] = type3.getData() ts_request['clientNonce'] = clientNonce ts_request['pubKeyAuth'] = signature.getData() + cripted_key try: # Sending the Type 3 NTLM blob tls.send(ts_request.getData()) buff = tls.recv(1024) except Exception as err: if str(err).find("denied") > 0: logging.error("Access Denied") else: print(err) return #Step4: Server should send its pubkey signature. try: ts_request = TSRequest(buff) #if password is invalid buff can't be decode # Now we're decrypting the certificate + 1 sent by the server. Not worth checking ;) signature, plain_text = cipher.decrypt(ts_request['pubKeyAuth']) if username != "" and password != "": print "Found valid credentials: " + username + ":" + password except Exception as err: return 0 #Step5: Send the encrypted credentials to the server if connect == True: tsp = TSPasswordCreds() tsp['domainName'] = domain tsp['userName'] = username tsp['password'] = password tsc = TSCredentials() tsc['credType'] = 1 # TSPasswordCreds tsc['credentials'] = tsp.getData() signature, cripted_creds = cipher.clientEncrypt(tsc.getData()) ts_request = TSRequest() ts_request['authInfo'] = signature.getData() + cripted_creds tls.send(ts_request.getData()) print "Credentials sent" return tls else: return 1
def getData(self): if 'pubKeyAuth' in self.fields: pubKeyAuth = pack('B', 0xa3) pubKeyAuth += asn1encode( pack('B', ASN1_OCTET_STRING) + asn1encode(self['pubKeyAuth'])) else: pubKeyAuth = b'' if 'authInfo' in self.fields: authInfo = pack('B', 0xa2) authInfo += asn1encode( pack('B', ASN1_OCTET_STRING) + asn1encode(self['authInfo'])) else: authInfo = b'' if 'NegoData' in self.fields: negoData = pack('B', 0xa1) negoData += asn1encode( pack('B', ASN1_SEQUENCE) + asn1encode( pack('B', ASN1_SEQUENCE) + asn1encode( pack('B', 0xa0) + asn1encode( pack('B', ASN1_OCTET_STRING) + asn1encode(self['NegoData']))))) else: negoData = b'' ans = pack('B', ASN1_SEQUENCE) ans += asn1encode( pack('B', 0xa0) + asn1encode(pack('B', 0x02) + asn1encode(pack('B', 0x02))) + negoData + authInfo + pubKeyAuth) return ans
def getData(self): # Do we have pubKeyAuth? if self.fields.has_key('pubKeyAuth'): pubKeyAuth = pack('B',0xa3) pubKeyAuth += asn1encode(pack('B', ASN1_OCTET_STRING) + asn1encode(self['pubKeyAuth'])) else: pubKeyAuth = '' if self.fields.has_key('authInfo'): authInfo = pack('B',0xa2) authInfo+= asn1encode(pack('B', ASN1_OCTET_STRING) + asn1encode(self['authInfo'])) else: authInfo = '' if self.fields.has_key('NegoData'): negoData = pack('B',0xa1) negoData += asn1encode(pack('B', ASN1_SEQUENCE) + asn1encode(pack('B', ASN1_SEQUENCE) + asn1encode(pack('B', 0xa0) + asn1encode(pack('B', ASN1_OCTET_STRING) + asn1encode(self['NegoData']))))) else: negoData = '' ans = pack('B', ASN1_SEQUENCE) ans += asn1encode(pack('B',0xa0) + asn1encode(pack('B',0x02) + asn1encode(pack('B',0x02))) + negoData + authInfo + pubKeyAuth) return ans
def getKRBData(self): # Do we have pubKeyAuth? if 'pubKeyAuth' in self.fields: pubKeyAuth = pack('B',0xa3) pubKeyAuth += asn1encode(pack('B', ASN1_OCTET_STRING) + asn1encode(self['pubKeyAuth'])) else: pubKeyAuth = b'' if 'authInfo' in self.fields: authInfo = pack('B',0xa2) authInfo+= asn1encode(pack('B', ASN1_OCTET_STRING) + asn1encode(self['authInfo'])) else: authInfo = b'' if 'clientNonce' in self.fields: clientNonce = pack('B',0xa5) clientNonce+= asn1encode(pack('B', ASN1_OCTET_STRING) + asn1encode(self['clientNonce'])) else: clientNonce = b'' if 'errorCode' in self.fields: errorCode = pack('B',0xa4) errorCode+= asn1encode(pack('B', ASN1_OCTET_STRING) + asn1encode(self['errorCode'])) else: errorCode = b'' if 'NegoData' in self.fields: negoData = pack('B',0xa1) negoData += asn1encode(pack('B', ASN1_SEQUENCE) + asn1encode(pack('B', ASN1_SEQUENCE) + asn1encode(pack('B', 0xa0) + asn1encode(pack('B', ASN1_OCTET_STRING) + asn1encode(self['NegoData']))))) else: negoData = b'' if 'NegoDataKerb' in self.fields: negoDataKerb = pack('B',0xa1) negoDataKerb += asn1encode(pack('B', ASN1_SEQUENCE) + asn1encode(pack('B', ASN1_SEQUENCE) + asn1encode(pack('B', 0xa0) + asn1encode(pack('B', 0x03) + b"\x0a\x01\x01")))) else: negoDataKerb = b'' #insert version if 'Version' in self.fields: version = asn1encode(pack('B',self['Version'])) #if version not found, default to version 6 wich is most recent else: version = asn1encode(pack('B',0x06)) ans = pack('B', ASN1_SEQUENCE) ans += asn1encode(pack('B',0xa0) + asn1encode(pack('B',0x0a) + version) + authInfo + pubKeyAuth + errorCode + clientNonce) realans = pack('B',0xa1) + asn1encode(ans) return realans
def check_rdp(host, username, password, domain, port=3389, hashes=None): if hashes is not None: lmhash, nthash = hashes.split(':') lmhash = a2b_hex(lmhash) nthash = a2b_hex(nthash) else: lmhash = '' nthash = '' tpkt = TPKT() tpdu = TPDU() rdp_neg = RDP_NEG_REQ() rdp_neg['Type'] = 1 rdp_neg['requestedProtocols'] = 2 | 1 tpdu['VariablePart'] = rdp_neg.getData() tpdu['Code'] = 0xe0 tpkt['TPDU'] = tpdu.getData() s = socket.socket() s.connect((host, port)) s.sendall(tpkt.getData()) pkt = s.recv(8192) tpkt.fromString(pkt) tpdu.fromString(tpkt['TPDU']) cr_tpdu = CR_TPDU(tpdu['VariablePart']) if cr_tpdu['Type'] == 3: rdp_failure = RDP_NEG_FAILURE(tpdu['VariablePart']) rdp_failure.dump() logger.error( "Server doesn't support PROTOCOL_HYBRID, hence we can't use CredSSP to check credentials" ) return else: rdp_neg.fromString(tpdu['VariablePart']) ctx = SSL.Context(SSL.TLSv1_2_METHOD) ctx.set_cipher_list(b'RC4,AES') tls = SSL.Connection(ctx, s) tls.set_connect_state() tls.do_handshake() auth = ntlm.getNTLMSSPType1('', '', True, use_ntlmv2=True) ts_request = TSRequest() ts_request['NegoData'] = auth.getData() tls.send(ts_request.getData()) buff = tls.recv(4096) ts_request.fromString(buff) type3, exportedSessionKey = ntlm.getNTLMSSPType3(auth, ts_request['NegoData'], username, password, domain, lmhash, nthash, use_ntlmv2=True) server_cert = tls.get_peer_certificate() pkey = server_cert.get_pubkey() dump = crypto.dump_privatekey(crypto.FILETYPE_ASN1, pkey) dump = dump[7:] dump = b'\x30' + asn1encode(dump) cipher = SPNEGOCipher(type3['flags'], exportedSessionKey) signature, cripted_key = cipher.encrypt(dump) ts_request['NegoData'] = type3.getData() ts_request['pubKeyAuth'] = signature.getData() + cripted_key try: tls.send(ts_request.getData()) buff = tls.recv(1024) except Exception as err: if str(err).find("denied") > 0: logger.info("rdp Access Denied") return else: logger.warning(err) return ts_request = TSRequest(buff) signature, plain_text = cipher.decrypt(ts_request['pubKeyAuth'][16:]) tsp = TSPasswordCreds() tsp['domainName'] = domain tsp['userName'] = username tsp['password'] = password tsc = TSCredentials() tsc['credType'] = 1 # TSPasswordCreds tsc['credentials'] = tsp.getData() signature, cripted_creds = cipher.encrypt(tsc.getData()) ts_request = TSRequest() ts_request['authInfo'] = signature.getData() + cripted_creds tls.send(ts_request.getData()) tls.close() # logger.success("Access Granted") logger.success("rdp success: {}/{}:{}@{}:{}".format( domain, username, password, host, port)) return { 'ip': host, 'user': username, 'password': password, 'port': port, 'serviceName': 'rdp', 'detail': { 'domain': domain, 'hash': hashes } }
def getKerberosType1(username, password, domain, lmhash, nthash, aesKey='', TGT=None, TGS=None, targetName='', kdcHost=None, useCache=True): # Convert to binary form, just in case we're receiving strings if isinstance(lmhash, str): try: lmhash = unhexlify(lmhash) except TypeError: pass if isinstance(nthash, str): try: nthash = unhexlify(nthash) except TypeError: pass if isinstance(aesKey, str): try: aesKey = unhexlify(aesKey) except TypeError: pass if TGT is None and TGS is None: if useCache is True: try: ccache = CCache.loadFile(os.getenv('KRB5CCNAME')) except Exception: # No cache present pass else: # retrieve domain information from CCache file if needed if domain == '': domain = ccache.principal.realm['data'].decode('utf-8') LOG.debug('Domain retrieved from CCache: %s' % domain) LOG.debug("Using Kerberos Cache: %s" % os.getenv('KRB5CCNAME')) principal = 'host/%s@%s' % (targetName.upper(), domain.upper()) creds = ccache.getCredential(principal) if creds is None: # Let's try for the TGT and go from there principal = 'krbtgt/%s@%s' % (domain.upper(), domain.upper()) creds = ccache.getCredential(principal) if creds is not None: TGT = creds.toTGT() LOG.debug('Using TGT from cache') else: LOG.debug("No valid credentials found in cache. ") else: TGS = creds.toTGS(principal) # retrieve user information from CCache file if needed if username == '' and creds is not None: username = creds['client'].prettyPrint().split( b'@')[0].decode('utf-8') LOG.debug('Username retrieved from CCache: %s' % username) elif username == '' and len(ccache.principal.components) > 0: username = ccache.principal.components[0]['data'].decode( 'utf-8') LOG.debug('Username retrieved from CCache: %s' % username) # First of all, we need to get a TGT for the user userName = Principal(username, type=constants.PrincipalNameType.NT_PRINCIPAL.value) while True: if TGT is None: if TGS is None: try: tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT( userName, password, domain, lmhash, nthash, aesKey, kdcHost) except KerberosError as e: if e.getErrorCode( ) == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value: # We might face this if the target does not support AES # So, if that's the case we'll force using RC4 by converting # the password to lm/nt hashes and hope for the best. If that's already # done, byebye. if lmhash == b'' and nthash == b'' and ( aesKey == b'' or aesKey is None ) and TGT is None and TGS is None: from impacket.ntlm import compute_lmhash, compute_nthash LOG.debug( 'Got KDC_ERR_ETYPE_NOSUPP, fallback to RC4') lmhash = compute_lmhash(password) nthash = compute_nthash(password) continue else: raise else: raise else: tgt = TGT['KDC_REP'] cipher = TGT['cipher'] sessionKey = TGT['sessionKey'] # Now that we have the TGT, we should ask for a TGS for cifs if TGS is None: serverName = Principal( 'host/%s' % targetName, type=constants.PrincipalNameType.NT_SRV_INST.value) try: tgs, cipher, oldSessionKey, sessionKey = getKerberosTGS( serverName, domain, kdcHost, tgt, cipher, sessionKey) except KerberosError as e: if e.getErrorCode( ) == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value: # We might face this if the target does not support AES # So, if that's the case we'll force using RC4 by converting # the password to lm/nt hashes and hope for the best. If that's already # done, byebye. if lmhash == b'' and nthash == b'' and ( aesKey == b'' or aesKey is None) and TGT is None and TGS is None: from impacket.ntlm import compute_lmhash, compute_nthash LOG.debug('Got KDC_ERR_ETYPE_NOSUPP, fallback to RC4') lmhash = compute_lmhash(password) nthash = compute_nthash(password) else: raise else: raise else: break else: tgs = TGS['KDC_REP'] cipher = TGS['cipher'] sessionKey = TGS['sessionKey'] break # Let's build a NegTokenInit with a Kerberos REQ_AP blob = SPNEGO_NegTokenInit() # Kerberos blob['MechTypes'] = [TypesMech['MS KRB5 - Microsoft Kerberos 5']] # Let's extract the ticket from the TGS tgs = decoder.decode(tgs, asn1Spec=TGS_REP())[0] ticket = Ticket() ticket.from_asn1(tgs['ticket']) # Now let's build the AP_REQ apReq = AP_REQ() apReq['pvno'] = 5 apReq['msg-type'] = int(constants.ApplicationTagNumbers.AP_REQ.value) opts = list() opts.append(constants.APOptions.mutual_required.value) apReq['ap-options'] = constants.encodeFlags(opts) seq_set(apReq, 'ticket', ticket.to_asn1) authenticator = Authenticator() authenticator['authenticator-vno'] = 5 authenticator['crealm'] = domain seq_set(authenticator, 'cname', userName.components_to_asn1) now = datetime.datetime.utcnow() authenticator['cusec'] = now.microsecond authenticator['ctime'] = KerberosTime.to_asn1(now) authenticator['cksum'] = noValue authenticator['cksum']['cksumtype'] = 0x8003 chkField = CheckSumField() chkField['Lgth'] = 16 chkField[ 'Flags'] = GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DCE_STYLE #chkField['Flags'] = GSS_C_INTEG_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DCE_STYLE authenticator['cksum']['checksum'] = chkField.getData() authenticator['seq-number'] = 0 encodedAuthenticator = encoder.encode(authenticator) # Key Usage 11 # AP-REQ Authenticator (includes application authenticator # subkey), encrypted with the application session key # (Section 5.5.1) encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 11, encodedAuthenticator, None) apReq['authenticator'] = noValue apReq['authenticator']['etype'] = cipher.enctype apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator blob['MechToken'] = struct.pack('B', ASN1_AID) + asn1encode( struct.pack('B', ASN1_OID) + asn1encode(TypesMech['KRB5 - Kerberos 5']) + KRB5_AP_REQ + encoder.encode(apReq)) return cipher, sessionKey, blob.getData()
def check_rdp(host, username, password, domain, hashes = None): if hashes is not None: lmhash, nthash = hashes.split(':') lmhash = a2b_hex(lmhash) nthash = a2b_hex(nthash) else: lmhash = '' nthash = '' tpkt = TPKT() tpdu = TPDU() rdp_neg = RDP_NEG_REQ() rdp_neg['Type'] = TYPE_RDP_NEG_REQ rdp_neg['requestedProtocols'] = PROTOCOL_HYBRID | PROTOCOL_SSL tpdu['VariablePart'] = str(rdp_neg) tpdu['Code'] = TDPU_CONNECTION_REQUEST tpkt['TPDU'] = str(tpdu) s = socket.socket() s.connect((host,3389)) s.sendall(str(tpkt)) pkt = s.recv(8192) tpkt.fromString(pkt) tpdu.fromString(tpkt['TPDU']) cr_tpdu = CR_TPDU(tpdu['VariablePart']) if cr_tpdu['Type'] == TYPE_RDP_NEG_FAILURE: rdp_failure = RDP_NEG_FAILURE(tpdu['VariablePart']) rdp_failure.dump() logging.error("Server doesn't support PROTOCOL_HYBRID, hence we can't use CredSSP to check credentials") return else: rdp_neg.fromString(tpdu['VariablePart']) # Since we were accepted to talk PROTOCOL_HYBRID, below is its implementation # 1. The CredSSP client and CredSSP server first complete the TLS handshake, # as specified in [RFC2246]. After the handshake is complete, all subsequent # CredSSP Protocol messages are encrypted by the TLS channel. # The CredSSP Protocol does not extend the TLS wire protocol. As part of the TLS # handshake, the CredSSP server does not request the client's X.509 certificate # (thus far, the client is anonymous). Also, the CredSSP Protocol does not require # the client to have a commonly trusted certification authority root with the # CredSSP server. Thus, the CredSSP server MAY use, for example, # a self-signed X.509 certificate. # Switching to TLS now ctx = SSL.Context(SSL.TLSv1_2_METHOD) ctx.set_cipher_list('RC4,AES') tls = SSL.Connection(ctx,s) tls.set_connect_state() tls.do_handshake() # If you want to use Python internal ssl, uncomment this and comment # the previous lines #tls = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1, ciphers='RC4') # 2. Over the encrypted TLS channel, the SPNEGO handshake between the client # and server completes mutual authentication and establishes an encryption key # that is used by the SPNEGO confidentiality services, as specified in [RFC4178]. # All SPNEGO tokens as well as the underlying encryption algorithms are opaque to # the calling application (the CredSSP client and CredSSP server). # The wire protocol for SPNEGO is specified in [MS-SPNG]. # The SPNEGO tokens exchanged between the client and the server are encapsulated # in the negoTokens field of the TSRequest structure. Both the client and the # server use this structure as many times as necessary to complete the SPNEGO # exchange.<9> # # Note During this phase of the protocol, the OPTIONAL authInfo field is omitted # from the TSRequest structure by the client and server; the OPTIONAL pubKeyAuth # field is omitted by the client unless the client is sending the last SPNEGO token. # If the client is sending the last SPNEGO token, the TSRequest structure MUST have # both the negoToken and the pubKeyAuth fields filled in. # NTLMSSP stuff auth = ntlm.getNTLMSSPType1('','',True, use_ntlmv2 = True) ts_request = TSRequest() ts_request['NegoData'] = str(auth) tls.send(ts_request.getData()) buff = tls.recv(4096) ts_request.fromString(buff) # 3. The client encrypts the public key it received from the server (contained # in the X.509 certificate) in the TLS handshake from step 1, by using the # confidentiality support of SPNEGO. The public key that is encrypted is the # ASN.1-encoded SubjectPublicKey sub-field of SubjectPublicKeyInfo from the X.509 # certificate, as specified in [RFC3280] section 4.1. The encrypted key is # encapsulated in the pubKeyAuth field of the TSRequest structure and is sent over # the TLS channel to the server. # # Note During this phase of the protocol, the OPTIONAL authInfo field is omitted # from the TSRequest structure; the client MUST send its last SPNEGO token to the # server in the negoTokens field (see step 2) along with the encrypted public key # in the pubKeyAuth field. # Last SPNEGO token calculation #ntlmChallenge = ntlm.NTLMAuthChallenge(ts_request['NegoData']) type3, exportedSessionKey = ntlm.getNTLMSSPType3(auth, ts_request['NegoData'], username, password, domain, lmhash, nthash, use_ntlmv2 = True) # Get server public key server_cert = tls.get_peer_certificate() pkey = server_cert.get_pubkey() dump = crypto.dump_privatekey(crypto.FILETYPE_ASN1, pkey) # Fix up due to PyOpenSSL lack for exporting public keys dump = dump[7:] dump = '\x30'+ asn1encode(dump) cipher = SPNEGOCipher(type3['flags'], exportedSessionKey) signature, cripted_key = cipher.encrypt(dump) ts_request['NegoData'] = str(type3) ts_request['pubKeyAuth'] = str(signature) + cripted_key try: # Sending the Type 3 NTLM blob tls.send(ts_request.getData()) # The other end is waiting for the pubKeyAuth field, but looks like it's # not needed to check whether authentication worked. # If auth is unsuccessful, it throws an exception with the previous send(). # If auth is successful, the server waits for the pubKeyAuth and doesn't answer # anything. So, I'm sending garbage so the server returns an error. # Luckily, it's a different error so we can determine whether or not auth worked ;) buff = tls.recv(1024) except Exception, err: if str(err).find("denied") > 0: logging.error("Access Denied") else: logging.error(err) return
def getKerberosType1(username, password, domain, lmhash, nthash, aesKey='', TGT = None, TGS = None, targetName='', kdcHost = None, useCache = True): if TGT is None and TGS is None: if useCache is True: try: ccache = CCache.loadFile(os.getenv('KRB5CCNAME')) except Exception: # No cache present pass else: # retrieve domain information from CCache file if needed if domain == '': domain = ccache.principal.realm['data'].decode('utf-8') LOG.debug('Domain retrieved from CCache: %s' % domain) LOG.debug("Using Kerberos Cache: %s" % os.getenv('KRB5CCNAME')) principal = 'host/%s@%s' % (targetName.upper(), domain.upper()) creds = ccache.getCredential(principal) if creds is None: # Let's try for the TGT and go from there principal = 'krbtgt/%s@%s' % (domain.upper(),domain.upper()) creds = ccache.getCredential(principal) if creds is not None: TGT = creds.toTGT() LOG.debug('Using TGT from cache') else: LOG.debug("No valid credentials found in cache. ") else: TGS = creds.toTGS(principal) # retrieve user information from CCache file if needed if username == '' and creds is not None: username = creds['client'].prettyPrint().split(b'@')[0] LOG.debug('Username retrieved from CCache: %s' % username) elif username == '' and len(ccache.principal.components) > 0: username = ccache.principal.components[0]['data'] LOG.debug('Username retrieved from CCache: %s' % username) # First of all, we need to get a TGT for the user userName = Principal(username, type=constants.PrincipalNameType.NT_PRINCIPAL.value) while True: if TGT is None: if TGS is None: try: tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, password, domain, lmhash, nthash, aesKey, kdcHost) except KerberosError as e: if e.getErrorCode() == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value: # We might face this if the target does not support AES # So, if that's the case we'll force using RC4 by converting # the password to lm/nt hashes and hope for the best. If that's already # done, byebye. if lmhash is '' and nthash is '' and (aesKey is '' or aesKey is None) and TGT is None and TGS is None: from impacket.ntlm import compute_lmhash, compute_nthash LOG.debug('Got KDC_ERR_ETYPE_NOSUPP, fallback to RC4') lmhash = compute_lmhash(password) nthash = compute_nthash(password) continue else: raise else: raise else: tgt = TGT['KDC_REP'] cipher = TGT['cipher'] sessionKey = TGT['sessionKey'] # Now that we have the TGT, we should ask for a TGS for cifs if TGS is None: serverName = Principal('host/%s' % targetName, type=constants.PrincipalNameType.NT_SRV_INST.value) try: tgs, cipher, oldSessionKey, sessionKey = getKerberosTGS(serverName, domain, kdcHost, tgt, cipher, sessionKey) except KerberosError as e: if e.getErrorCode() == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value: # We might face this if the target does not support AES # So, if that's the case we'll force using RC4 by converting # the password to lm/nt hashes and hope for the best. If that's already # done, byebye. if lmhash is '' and nthash is '' and (aesKey is '' or aesKey is None) and TGT is None and TGS is None: from impacket.ntlm import compute_lmhash, compute_nthash LOG.debug('Got KDC_ERR_ETYPE_NOSUPP, fallback to RC4') lmhash = compute_lmhash(password) nthash = compute_nthash(password) else: raise else: raise else: break else: tgs = TGS['KDC_REP'] cipher = TGS['cipher'] sessionKey = TGS['sessionKey'] break # Let's build a NegTokenInit with a Kerberos REQ_AP blob = SPNEGO_NegTokenInit() # Kerberos blob['MechTypes'] = [TypesMech['MS KRB5 - Microsoft Kerberos 5']] # Let's extract the ticket from the TGS tgs = decoder.decode(tgs, asn1Spec = TGS_REP())[0] ticket = Ticket() ticket.from_asn1(tgs['ticket']) # Now let's build the AP_REQ apReq = AP_REQ() apReq['pvno'] = 5 apReq['msg-type'] = int(constants.ApplicationTagNumbers.AP_REQ.value) opts = list() opts.append(constants.APOptions.mutual_required.value) apReq['ap-options'] = constants.encodeFlags(opts) seq_set(apReq,'ticket', ticket.to_asn1) authenticator = Authenticator() authenticator['authenticator-vno'] = 5 authenticator['crealm'] = domain seq_set(authenticator, 'cname', userName.components_to_asn1) now = datetime.datetime.utcnow() authenticator['cusec'] = now.microsecond authenticator['ctime'] = KerberosTime.to_asn1(now) authenticator['cksum'] = noValue authenticator['cksum']['cksumtype'] = 0x8003 chkField = CheckSumField() chkField['Lgth'] = 16 chkField['Flags'] = GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DCE_STYLE #chkField['Flags'] = GSS_C_INTEG_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DCE_STYLE authenticator['cksum']['checksum'] = chkField.getData() authenticator['seq-number'] = 0 encodedAuthenticator = encoder.encode(authenticator) # Key Usage 11 # AP-REQ Authenticator (includes application authenticator # subkey), encrypted with the application session key # (Section 5.5.1) encryptedEncodedAuthenticator = cipher.encrypt(sessionKey, 11, encodedAuthenticator, None) apReq['authenticator'] = noValue apReq['authenticator']['etype'] = cipher.enctype apReq['authenticator']['cipher'] = encryptedEncodedAuthenticator blob['MechToken'] = struct.pack('B', ASN1_AID) + asn1encode( struct.pack('B', ASN1_OID) + asn1encode( TypesMech['KRB5 - Kerberos 5'] ) + KRB5_AP_REQ + encoder.encode(apReq)) return cipher, sessionKey, blob.getData()