def sendClientChallengeResponse(self, platformChallenge): """ @summary: generate valid challenge response @param platformChallenge: {ServerPlatformChallenge} """ serverEncryptedChallenge = platformChallenge.encryptedPlatformChallenge.blobData.value #decrypt server challenge #it should be TEST word in unicode format serverChallenge = rc4.crypt(rc4.RC4Key(self._licenseKey), serverEncryptedChallenge) if serverChallenge != "T\x00E\x00S\x00T\x00\x00\x00": raise InvalidExpectedDataException("bad license server challenge") #generate hwid s = Stream() s.writeType((UInt32Le(2), String(self._hostname + self._username + "\x00" * 16))) hwid = s.getvalue()[:20] message = ClientPLatformChallengeResponse() message.encryptedPlatformChallengeResponse.blobData.value = serverEncryptedChallenge message.encryptedHWID.blobData.value = rc4.crypt( rc4.RC4Key(self._licenseKey), hwid) message.MACData.value = sec.macData(self._macSalt, serverChallenge + hwid) self._transport.sendFlagged(sec.SecurityFlag.SEC_LICENSE_PKT, LicPacket(message))
def sendClientRandom(self): """ @summary: generate and send client random and init session keys """ #generate client random clientRandom = rsa.random(256) self._macKey, self._initialDecrytKey, self._initialEncryptKey = generateKeys( clientRandom, self.getGCCServerSettings().SC_SECURITY.serverRandom.value, self.getGCCServerSettings().SC_SECURITY.encryptionMethod.value) #initialize keys self._currentDecrytKey = self._initialDecrytKey self._currentEncryptKey = self._initialEncryptKey self._decryptRc4 = rc4.RC4Key(self._currentDecrytKey) self._encryptRc4 = rc4.RC4Key(self._currentEncryptKey) #verify certificate if not self.getGCCServerSettings( ).SC_SECURITY.serverCertificate.certData.verify(): log.warning("cannot verify server identity") #send client random encrypted with serverPublicKey = self.getGCCServerSettings( ).SC_SECURITY.serverCertificate.certData.getPublicKey() message = ClientSecurityExchangePDU() #reverse because bignum in little endian message.encryptedClientRandom.value = rsa.encrypt( clientRandom[::-1], serverPublicKey)[::-1] self.sendFlagged(SecurityFlag.SEC_EXCHANGE_PKT, message)
def recvClientRandom(self, s): """ @summary: receive client random and generate session keys @param s: {Stream} """ #packet preambule securityFlag = UInt16Le() securityFlagHi = UInt16Le() s.readType((securityFlag, securityFlagHi)) if not (securityFlag.value & SecurityFlag.SEC_EXCHANGE_PKT): raise InvalidExpectedDataException("waiting client random") message = ClientSecurityExchangePDU() s.readType(message) clientRandom = rsa.decrypt(message.encryptedClientRandom.value[::-1], self._rsaPrivateKey)[::-1] self._macKey, self._initialEncryptKey, self._initialDecrytKey = generateKeys( clientRandom, self.getGCCServerSettings().SC_SECURITY.serverRandom.value, self.getGCCServerSettings().SC_SECURITY.encryptionMethod.value) #initialize keys self._currentDecrytKey = self._initialDecrytKey self._currentEncryptKey = self._initialEncryptKey self._decryptRc4 = rc4.RC4Key(self._currentDecrytKey) self._encryptRc4 = rc4.RC4Key(self._currentEncryptKey) self.setNextState(self.recvInfoPkt)
def getAuthenticateMessage(self, challenge, authMessage): """ @summary: Client last handshake message @param s: {Stream} challenge message stream @return: {(AuthenticateMessage, NTLMv2SecurityInterface)} Last handshake message and security interface use to encrypt @see: https://msdn.microsoft.com/en-us/library/cc236676.aspx """ self._challengeMessage = ChallengeMessage() challenge.readType(self._challengeMessage) ServerChallenge = self._challengeMessage.ServerChallenge.value ClientChallenge = random(64) computeMIC = False ServerName = self._challengeMessage.getTargetInfo() infos = self._challengeMessage.getTargetInfoAsAvPairArray() if infos.has_key(AvId.MsvAvTimestamp): Timestamp = infos[AvId.MsvAvTimestamp] computeMIC = False else: Timestamp = CurrentFileTimes() NtChallengeResponse, LmChallengeResponse, SessionBaseKey = ComputeResponsev2( self._ResponseKeyNT, self._ResponseKeyLM, ServerChallenge, ClientChallenge, Timestamp, ServerName) KeyExchangeKey = KXKEYv2(SessionBaseKey, LmChallengeResponse, ServerChallenge) ExportedSessionKey = random(128) EncryptedRandomSessionKey = RC4K(KeyExchangeKey, ExportedSessionKey) domain, user = self._domain, self._user if self._challengeMessage.NegotiateFlags.value & Negotiate.NTLMSSP_NEGOTIATE_UNICODE: self._enableUnicode = True domain, user = UNICODE(domain), UNICODE(user) self._authenticateMessage = AuthenticateMessage() ss = Stream(type.String(authMessage)) self._authenticateMessage.read(ss) if computeMIC: self._authenticateMessage.MIC.value = MIC( ExportedSessionKey, self._negotiateMessage, self._challengeMessage, self._authenticateMessage) else: self._authenticateMessage.MIC._conditional = lambda: False ClientSigningKey = SIGNKEY(ExportedSessionKey, True) ServerSigningKey = SIGNKEY(ExportedSessionKey, False) ClientSealingKey = SEALKEY(ExportedSessionKey, True) ServerSealingKey = SEALKEY(ExportedSessionKey, False) interface = NTLMv2SecurityInterface(rc4.RC4Key(ClientSealingKey), rc4.RC4Key(ServerSealingKey), ClientSigningKey, ServerSigningKey) return self._authenticateMessage, interface
def testCSSPNTLMAuthentication(self): negotiate_data_request = cssp.decodeDERTRequest(peer0_0.decode('base64')) challenge_data_request = cssp.decodeDERTRequest(peer1_0.decode('base64')) authenticate_data_request = cssp.decodeDERTRequest(peer0_1.decode('base64')) negotiate_data = cssp.getNegoTokens(negotiate_data_request)[0] challenge_data = cssp.getNegoTokens(challenge_data_request)[0] authenticate_data = cssp.getNegoTokens(authenticate_data_request)[0] negotiate = ntlm.NegotiateMessage() negotiate_data.readType(negotiate) challenge = ntlm.ChallengeMessage() challenge_data.readType(challenge) ServerChallenge = challenge.ServerChallenge.value ServerName = challenge.getTargetInfo() authenticate = ntlm.AuthenticateMessage() authenticate_data.readType(authenticate) NtChallengeResponseTemp = authenticate.getNtChallengeResponse() NTProofStr = NtChallengeResponseTemp[:16] temp = NtChallengeResponseTemp[16:] Timestamp = temp[8:16] ClientChallenge = temp[16:24] EncryptedRandomSessionKey = authenticate.getEncryptedRandomSession() domain = "coco" user = "******" password = "******" ResponseKeyNT = ntlm.NTOWFv2(password, user, domain) ResponseKeyLM = ntlm.LMOWFv2(password, user, domain) NtChallengeResponse, LmChallengeResponse, SessionBaseKey = ntlm.ComputeResponsev2(ResponseKeyNT, ResponseKeyLM, ServerChallenge, ClientChallenge, Timestamp, ServerName) KeyExchangeKey = ntlm.KXKEYv2(SessionBaseKey, LmChallengeResponse, ServerChallenge) ExportedSessionKey = ntlm.RC4K(KeyExchangeKey, EncryptedRandomSessionKey) domain, user = domain, user if challenge.NegotiateFlags.value & ntlm.Negotiate.NTLMSSP_NEGOTIATE_UNICODE: domain, user = ntlm.UNICODE(domain), ntlm.UNICODE(user) ClientSigningKey = ntlm.SIGNKEY(ExportedSessionKey, True) ServerSigningKey = ntlm.SIGNKEY(ExportedSessionKey, False) ClientSealingKey = ntlm.SEALKEY(ExportedSessionKey, True) ServerSealingKey = ntlm.SEALKEY(ExportedSessionKey, False) interface = ntlm.NTLMv2SecurityInterface(rc4.RC4Key(ClientSealingKey), rc4.RC4Key(ServerSealingKey), ClientSigningKey, ServerSigningKey) EncryptedPubKeySrc = cssp.getPubKeyAuth(authenticate_data_request) EncryptedPubKeyDst = interface.GSS_WrapEx(pubKeyHex.decode('base64')) self.assertTrue(EncryptedPubKeySrc == EncryptedPubKeyDst, "Public key must be equals")
def readEncryptedPayload(self, s, saltedMacGeneration): """ @summary: decrypt basic RDP security payload @param s: {Stream} encrypted stream @param saltedMacGeneration: {bool} use salted mac generation @return: {Stream} decrypted """ #if update is needed if self._nbDecryptedPacket == 4096: log.debug("update decrypt key") self._currentDecrytKey = updateKey( self._initialDecrytKey, self._currentDecrytKey, self.getGCCServerSettings().SC_SECURITY.encryptionMethod.value) self._decryptRc4 = rc4.RC4Key(self._currentDecrytKey) self._nbDecryptedPacket = 0 signature = String(readLen = CallableValue(8)) encryptedPayload = String() s.readType((signature, encryptedPayload)) decrypted = rc4.crypt(self._decryptRc4, encryptedPayload.value) #ckeck signature if not saltedMacGeneration and macData(self._macKey, decrypted)[:8] != signature.value: raise InvalidExpectedDataException("bad signature") if saltedMacGeneration and macSaltedData(self._macKey, decrypted, self._nbDecryptedPacket)[:8] != signature.value: raise InvalidExpectedDataException("bad signature") #count self._nbDecryptedPacket += 1 return Stream(decrypted)
def writeEncryptedPayload(self, data, saltedMacGeneration): """ @summary: sign and crypt data @param data: {Type} raw stream @param saltedMacGeneration: {bool} use salted mac generation @return: {Tuple} (signature, encryptedData) """ if self._nbEncryptedPacket == 4096: log.debug("update encrypt key") self._currentEncryptKey = updateKey( self._initialEncryptKey, self._currentEncryptKey, self.getGCCServerSettings().SC_SECURITY.encryptionMethod.value) self._encryptRc4 = rc4.RC4Key(self._currentEncryptKey) self._nbEncryptedPacket = 0 self._nbEncryptedPacket += 1 s = Stream() s.writeType(data) if saltedMacGeneration: return (String( macSaltedData(self._macKey, s.getvalue(), self._nbEncryptedPacket - 1)[:8]), String(rc4.crypt(self._encryptRc4, s.getvalue()))) else: return (String(macData(self._macKey, s.getvalue())[:8]), String(rc4.crypt(self._encryptRc4, s.getvalue())))
def RC4K(key, plaintext): """ @summary: Context free of rc4 encoding @param key: {str} key @param plaintext: {str} plaintext @return {str} encrypted text """ return rc4.crypt(rc4.RC4Key(key), plaintext)
def updateKey(initialKey, currentKey, method): """ @summary: update session key @param initialKey: {str} Initial key @param currentKey: {str} Current key @return newKey: {str} key to use @see: http://msdn.microsoft.com/en-us/library/cc240792.aspx """ #generate valid key if method == gcc.EncryptionMethod.ENCRYPTION_FLAG_40BIT: tempKey128 = tempKey(initialKey[:8], currentKey[:8]) return gen40bits(rc4.crypt(rc4.RC4Key(tempKey128[:8]), tempKey128[:8])) elif method == gcc.EncryptionMethod.ENCRYPTION_FLAG_56BIT: tempKey128 = tempKey(initialKey[:8], currentKey[:8]) return gen56bits(rc4.crypt(rc4.RC4Key(tempKey128[:8]), tempKey128[:8])) elif method == gcc.EncryptionMethod.ENCRYPTION_FLAG_128BIT: tempKey128 = tempKey(initialKey, currentKey) return rc4.crypt(rc4.RC4Key(tempKey128), tempKey128)
def test_rc4_secret_attack_at_down(self): self.assertEqual("\x45\xA0\x1F\x64\x5F\xC3\x5B\x38\x35\x52\x54\x4B\x9B\xF5", rc4.crypt(rc4.RC4Key("Secret"), "Attack at dawn"), "RC4 bad crypt") self.assertEqual("Attack at dawn", rc4.crypt(rc4.RC4Key("Secret"), "\x45\xA0\x1F\x64\x5F\xC3\x5B\x38\x35\x52\x54\x4B\x9B\xF5"), "RC4 bad crypt")
def test_rc4_wiki_pedia(self): self.assertEqual("\x10\x21\xBF\x04\x20", rc4.crypt(rc4.RC4Key("Wiki"), "pedia"), "RC4 bad crypt") self.assertEqual("pedia", rc4.crypt(rc4.RC4Key("Wiki"), "\x10\x21\xBF\x04\x20"), "RC4 bad crypt")
def test_rc4_key_plaintext(self): self.assertEqual("\xBB\xF3\x16\xE8\xD9\x40\xAF\x0A\xD3", rc4.crypt(rc4.RC4Key("Key"), "Plaintext"), "RC4 bad crypt") self.assertEqual("Plaintext", rc4.crypt(rc4.RC4Key("Key"), "\xBB\xF3\x16\xE8\xD9\x40\xAF\x0A\xD3"), "RC4 bad crypt")